diff --git a/.github/workflows/integration_test.yaml b/.github/workflows/integration_test.yaml new file mode 100644 index 000000000..95396db76 --- /dev/null +++ b/.github/workflows/integration_test.yaml @@ -0,0 +1,18 @@ +name: Integration test + +on: + pull_request: + +jobs: + integration-tests: + name: Integration test + runs-on: ["self-hosted", "integration-runner"] + steps: + - name: Install tox + run: python3 -m pip install --user tox + - name: Run Integration tests + run: | + tox -e integration -- \ + --keep-models \ + --path ${{secrets.E2E_TESTING_REPO}} \ + --token ${{secrets.E2E_TESTING_TOKEN}} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 43bc27369..99e540d31 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,7 +1,7 @@ name: Tests on: - pull_request: {} + pull_request: jobs: unit-tests: diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index a74fcf8e5..b870a50f5 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,32 +1,48 @@ # Copyright 2023 Canonical Ltd. # See LICENSE file for licensing details. +"""Fixtures for github runner charm integration tests.""" + from pathlib import Path import pytest +import pytest_asyncio import yaml +from ops.model import Application +from pytest_operator.plugin import OpsTest -@pytest.fixture -def metadata(): +@pytest.fixture(scope="module") +def metadata() -> dict[str, any]: + """Metadata information of the charm""" metadata = Path("./metadata.yaml") data = yaml.safe_load(metadata.read_text()) return data -@pytest.fixture -def model(ops_test): - return ops_test.model +@pytest.fixture(scope="module") +def path(pytestconfig: pytest.Config) -> str: + path = pytestconfig.getoption("--path") + assert path is not None, "Please specify the --path command line option" + return path + + +@pytest.fixture(scope="module") +def token(pytestconfig: pytest.Config) -> str: + token = pytestconfig.getoption("--token") + assert token is not None, "Please specify the --token command line option" + return token -@pytest.fixture -def application(model, metadata): - charm_name = metadata["name"] - app = model.applications[charm_name] - return app +@pytest_asyncio.fixture(scope="module") +async def app(ops_test: OpsTest, path: str) -> Application: + charm = await ops_test.build_charm(".") + application = await ops_test.model.deploy( + charm, + series="jammy", + config={path: path, "virtual-machines": 1, "denylist": "10.0.0.0/8"}, + constraints={"cores": "4", "mem": "32G", "virt-type": "virtual-machine"}, + ) -@pytest.fixture -def units(application): - units = application.units - return units + yield application diff --git a/tests/integration/test_charm.py b/tests/integration/test_charm.py index ad6f7b6a0..775e9b45e 100644 --- a/tests/integration/test_charm.py +++ b/tests/integration/test_charm.py @@ -1,26 +1,38 @@ # Copyright 2023 Canonical Ltd. # See LICENSE file for licensing details. -import logging +"""Integration tests for github-runner charm.""" import pytest - -log = logging.getLogger(__name__) - - -async def file_contents(unit, path): - cmd = "cat {}".format(path) - action = await unit.run(cmd) - return action.results["Stdout"] +from ops.model import ActiveStatus, BlockedStatus, Application +from pytest_operator.plugin import OpsTest +@pytest.mark.asyncio @pytest.mark.abort_on_fail -async def test_build_and_deploy(ops_test): - my_charm = await ops_test.build_charm(".") - await ops_test.model.deploy(my_charm) +async def test_missing_config(ops_test: OpsTest, app: Application) -> None: + """ + arrange: Deploy an application without token configuration + act: Check the status the application + assert: The application is in blocked status. + """ await ops_test.model.wait_for_idle() + assert ops_test.model.applications["github-runner"].status == BlockedStatus.name + assert ( + ops_test.model.applications["github-runner"].status_message + == "Missing token or org/repo path config" + ) -async def test_status(units): - assert units[0].workload_status == "blocked" - assert units[0].workload_status_message == "Missing token or org/repo path config" +@pytest.mark.asyncio +@pytest.mark.abort_on_fail +@pytest.mark.requires_secrets +async def test_config(ops_test: OpsTest, app: Application, token: str) -> None: + """ + arrange: Deploy an application without token configuration + act: Set the token configuration and wait. + assert: The application is in active status. + """ + await app.set_config({"token": token}) + await ops_test.model.wait_for_idle() + assert ops_test.model.applications["github-runner"].status == ActiveStatus.name