Add tests (#1) (#5)

* add models tests (#1)

also replace single quote to double one to confort PEP docstring
+ move _check_output to class properties to make it available for
mocking

* alpm tests implementation

* try to replace os with pathlib

* update tests for pathlib

* fix includes glob and trim version from dependencies

* build_tools package tests

* repository component tests

* add sign tests

* complete status tests

* handle exceptions in actual_version calls

* complete core tests

* move configuration to root conftest

* application tests

* complete application tests

* change copyright to more generic one

* base web tests

* complete web tests

* complete testkit

also add argument parsers test
This commit is contained in:
2021-03-28 15:30:51 +03:00
committed by GitHub
parent 69499b2d0a
commit 74a244f06c
139 changed files with 4606 additions and 1124 deletions

View File

@ -0,0 +1,13 @@
import pytest
from aiohttp import web
from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration
from ahriman.web.web import setup_service
@pytest.fixture
def application(configuration: Configuration, mocker: MockerFixture) -> web.Application:
mocker.patch("pathlib.Path.mkdir")
return setup_service("x86_64", configuration)

View File

View File

@ -0,0 +1,45 @@
import pytest
from aiohttp import web
from pytest_mock import MockerFixture
from ahriman.core.exceptions import InitializeException
from ahriman.core.status.watcher import Watcher
from ahriman.web.web import on_startup, run_server
async def test_on_startup(application: web.Application, watcher: Watcher, mocker: MockerFixture) -> None:
"""
must call load method
"""
mocker.patch("aiohttp.web.Application.__getitem__", return_value=watcher)
load_mock = mocker.patch("ahriman.core.status.watcher.Watcher.load")
await on_startup(application)
load_mock.assert_called_once()
async def test_on_startup_exception(application: web.Application, watcher: Watcher, mocker: MockerFixture) -> None:
"""
must throw exception on load error
"""
mocker.patch("aiohttp.web.Application.__getitem__", return_value=watcher)
mocker.patch("ahriman.core.status.watcher.Watcher.load", side_effect=Exception())
with pytest.raises(InitializeException):
await on_startup(application)
def test_run(application: web.Application, mocker: MockerFixture) -> None:
"""
must run application
"""
host = "localhost"
port = 8080
application["config"].set("web", "host", host)
application["config"].set("web", "port", str(port))
run_app_mock = mocker.patch("aiohttp.web.run_app")
run_server(application)
run_app_mock.assert_called_with(application, host=host, port=port,
handle_signals=False, access_log=pytest.helpers.anyvar(int))

View File

@ -0,0 +1,14 @@
import pytest
from aiohttp import web
from asyncio import BaseEventLoop
from pytest_aiohttp import TestClient
from pytest_mock import MockerFixture
from typing import Any
@pytest.fixture
def client(application: web.Application, loop: BaseEventLoop,
aiohttp_client: Any, mocker: MockerFixture) -> TestClient:
mocker.patch("pathlib.Path.iterdir", return_value=[])
return loop.run_until_complete(aiohttp_client(application))

View File

@ -0,0 +1,37 @@
from aiohttp.test_utils import TestClient
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
async def test_get(client: TestClient) -> None:
"""
must return valid service status
"""
response = await client.get("/api/v1/ahriman")
status = BuildStatus.from_json(await response.json())
assert response.status == 200
assert status.status == BuildStatusEnum.Unknown
async def test_post(client: TestClient) -> None:
"""
must update service status correctly
"""
payload = {"status": BuildStatusEnum.Success.value}
post_response = await client.post("/api/v1/ahriman", json=payload)
assert post_response.status == 204
response = await client.get("/api/v1/ahriman")
status = BuildStatus.from_json(await response.json())
assert response.status == 200
assert status.status == BuildStatusEnum.Success
async def test_post_exception(client: TestClient) -> None:
"""
must raise exception on invalid payload
"""
post_response = await client.post("/api/v1/ahriman", json={})
assert post_response.status == 400

View File

@ -0,0 +1,19 @@
from pytest_aiohttp import TestClient
async def test_get(client: TestClient) -> None:
"""
must generate status page correctly (/)
"""
response = await client.get("/")
assert response.status == 200
assert await response.text()
async def test_get_index(client: TestClient) -> None:
"""
must generate status page correctly (/index.html)
"""
response = await client.get("/index.html")
assert response.status == 200
assert await response.text()

View File

@ -0,0 +1,117 @@
from pytest_aiohttp import TestClient
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.package import Package
async def test_get(client: TestClient, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must return status for specific package
"""
await client.post(f"/api/v1/packages/{package_ahriman.base}",
json={"status": BuildStatusEnum.Success.value, "package": package_ahriman.view()})
await client.post(f"/api/v1/packages/{package_python_schedule.base}",
json={"status": BuildStatusEnum.Success.value, "package": package_python_schedule.view()})
response = await client.get(f"/api/v1/packages/{package_ahriman.base}")
assert response.status == 200
packages = [Package.from_json(item["package"]) for item in await response.json()]
assert packages
assert {package.base for package in packages} == {package_ahriman.base}
async def test_get_not_found(client: TestClient, package_ahriman: Package) -> None:
"""
must return Not Found for unknown package
"""
response = await client.get(f"/api/v1/packages/{package_ahriman.base}")
assert response.status == 404
async def test_delete(client: TestClient, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must delete single base
"""
await client.post(f"/api/v1/packages/{package_ahriman.base}",
json={"status": BuildStatusEnum.Success.value, "package": package_ahriman.view()})
await client.post(f"/api/v1/packages/{package_python_schedule.base}",
json={"status": BuildStatusEnum.Success.value, "package": package_python_schedule.view()})
response = await client.delete(f"/api/v1/packages/{package_ahriman.base}")
assert response.status == 204
response = await client.get(f"/api/v1/packages/{package_ahriman.base}")
assert response.status == 404
response = await client.get(f"/api/v1/packages/{package_python_schedule.base}")
assert response.status == 200
async def test_delete_unknown(client: TestClient, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must suppress errors on unknown package deletion
"""
await client.post(f"/api/v1/packages/{package_python_schedule.base}",
json={"status": BuildStatusEnum.Success.value, "package": package_python_schedule.view()})
response = await client.delete(f"/api/v1/packages/{package_ahriman.base}")
assert response.status == 204
response = await client.get(f"/api/v1/packages/{package_ahriman.base}")
assert response.status == 404
response = await client.get(f"/api/v1/packages/{package_python_schedule.base}")
assert response.status == 200
async def test_post(client: TestClient, package_ahriman: Package) -> None:
"""
must update package status
"""
post_response = await client.post(
f"/api/v1/packages/{package_ahriman.base}",
json={"status": BuildStatusEnum.Success.value, "package": package_ahriman.view()})
assert post_response.status == 204
response = await client.get(f"/api/v1/packages/{package_ahriman.base}")
assert response.status == 200
async def test_post_exception(client: TestClient, package_ahriman: Package) -> None:
"""
must raise exception on invalid payload
"""
post_response = await client.post(f"/api/v1/packages/{package_ahriman.base}", json={})
assert post_response.status == 400
async def test_post_light(client: TestClient, package_ahriman: Package) -> None:
"""
must update package status only
"""
post_response = await client.post(
f"/api/v1/packages/{package_ahriman.base}",
json={"status": BuildStatusEnum.Unknown.value, "package": package_ahriman.view()})
assert post_response.status == 204
post_response = await client.post(
f"/api/v1/packages/{package_ahriman.base}", json={"status": BuildStatusEnum.Success.value})
assert post_response.status == 204
response = await client.get(f"/api/v1/packages/{package_ahriman.base}")
assert response.status == 200
statuses = {
Package.from_json(item["package"]).base: BuildStatus.from_json(item["status"])
for item in await response.json()
}
assert statuses[package_ahriman.base].status == BuildStatusEnum.Success
async def test_post_not_found(client: TestClient, package_ahriman: Package) -> None:
"""
must raise exception on status update for unknown package
"""
post_response = await client.post(
f"/api/v1/packages/{package_ahriman.base}", json={"status": BuildStatusEnum.Success.value})
assert post_response.status == 400

View File

@ -0,0 +1,32 @@
from pytest_aiohttp import TestClient
from pytest_mock import MockerFixture
from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package
async def test_get(client: TestClient, package_ahriman: Package, package_python_schedule: Package) -> None:
"""
must return status for all packages
"""
await client.post(f"/api/v1/packages/{package_ahriman.base}",
json={"status": BuildStatusEnum.Success.value, "package": package_ahriman.view()})
await client.post(f"/api/v1/packages/{package_python_schedule.base}",
json={"status": BuildStatusEnum.Success.value, "package": package_python_schedule.view()})
response = await client.get("/api/v1/packages")
assert response.status == 200
packages = [Package.from_json(item["package"]) for item in await response.json()]
assert packages
assert {package.base for package in packages} == {package_ahriman.base, package_python_schedule.base}
async def test_post(client: TestClient, mocker: MockerFixture) -> None:
"""
must be able to reload packages
"""
load_mock = mocker.patch("ahriman.core.status.watcher.Watcher.load")
response = await client.post("/api/v1/packages")
assert response.status == 204
load_mock.assert_called_once()