Last active
October 29, 2022 18:17
-
-
Save LewisGaul/126049eec2911a5d557285cff0e3799e to your computer and use it in GitHub Desktop.
Pytest setup that runs first during fixture setup stage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__all__ = () |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
from typing import Set | |
import pytest | |
logger = logging.getLogger(__name__) | |
def pytest_configure(config: pytest.Config) -> None: | |
config.addinivalue_line( | |
"markers", | |
"require_features(FEAT, ...): specify required host features", | |
) | |
@pytest.fixture(scope="session") | |
def host(pytestconfig: pytest.Config) -> str: | |
if address := pytestconfig.getoption("host_address", None): | |
logger.info("Using host address %s", address) | |
return address | |
else: | |
logger.info("Using localhost") | |
return "localhost" | |
@pytest.fixture(scope="session", autouse=True) | |
def _skip_marked_tests_as_applicable(request: pytest.FixtureRequest, host: str) -> None: | |
session = request.node | |
host_features = _detect_host_features(host) | |
for item in session.items: | |
if mark := item.get_closest_marker("require_features"): | |
required_features = set(mark.args) | |
else: | |
required_features = set() | |
missing_features = required_features - host_features | |
if missing_features: | |
item.add_marker( | |
pytest.mark.skip( | |
f"Host missing features: " + ",".join(sorted(missing_features)) | |
) | |
) | |
def _detect_host_features(host: str) -> Set[str]: | |
# Run commands on the host over SSH to determine what features it provides. | |
... | |
return {"bar", "baz"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$PYTEST_PLUGINS=tests.plugin pytest tests/ --log-cli-level info --setup-vm | |
=============================================================== test session starts =============================================================== | |
platform linux -- Python 3.9.12, pytest-7.2.0, pluggy-1.0.0 | |
rootdir: pytest-playground, configfile: pytest.ini | |
collected 3 items | |
tests/test_1.py::test_A | |
----------------------------------------------------------------- live log setup ------------------------------------------------------------------ | |
INFO tests.plugin:plugin.py:38 Booting VM... | |
INFO tests.conftest:conftest.py:22 Using VM host 10.0.0.123 | |
------------------------------------------------------------------ live log call ------------------------------------------------------------------ | |
INFO tests.test_1:test_1.py:10 Running test A | |
PASSED [ 33%] | |
tests/test_1.py::test_B SKIPPED (Host missing features: foo) [ 66%] | |
tests/test_1.py::test_C | |
------------------------------------------------------------------ live log call ------------------------------------------------------------------ | |
INFO tests.test_1:test_1.py:20 Running test C | |
PASSED [100%] | |
---------------------------------------------------------------- live log teardown ---------------------------------------------------------------- | |
INFO tests.plugin:plugin.py:43 Tearing down the VM... | |
========================================================== 2 passed, 1 skipped in 0.03s =========================================================== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
from typing import List | |
import pytest | |
logger = logging.getLogger(__name__) | |
def pytest_addoption(parser: pytest.Parser) -> None: | |
group = parser.getgroup("vm_opts", "VM plugin opts") | |
group.addoption( | |
"--setup-vm", | |
action="store_true", | |
help="Enable setting up a VM", | |
) | |
def pytest_configure(config: pytest.Config) -> None: | |
if config.option.setup_vm: | |
config.option.host_address = "10.0.0.123" | |
def pytest_collection_modifyitems( | |
config: pytest.Config, items: List[pytest.Item] | |
) -> None: | |
# Force setup fixture to run first. | |
# Added as a dependency for all tests (effectively like autouse). | |
if config.option.setup_vm: | |
for item in items: | |
item.fixturenames.insert(0, "vm_setup") | |
@pytest.fixture(scope="session") | |
def vm_setup() -> None: | |
_boot_vm() | |
yield | |
_teardown_vm() | |
def _boot_vm(): | |
logger.info("Booting VM...") | |
... | |
def _teardown_vm(): | |
logger.info("Tearing down the VM...") | |
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import pytest | |
logger = logging.getLogger(__name__) | |
def test_A(host): | |
logger.info("Running test A") | |
@pytest.mark.require_features("foo") | |
def test_B(host): | |
logger.info("Running test B") | |
@pytest.mark.require_features("bar") | |
def test_C(host): | |
logger.info("Running test C") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment