# regarding conftest: # If you have conftest.py files which do not reside in a python package directory # (i.e. one containing an __init__.py) then “import conftest” can be ambiguous # because there might be other conftest.py files as well on your PYTHONPATH or # sys.path. It is thus good practise for projects to either put conftest.py under # a package scope or to never import anything from a conftest.py file. from pathlib import Path import pytest from dotenv import dotenv_values from icecream import ic from playwright.sync_api import BrowserContext from src.dirmanager import DirManager pytest_plugins = [ # "setup.setup_authentik", "tests_authentik.authentik_plugin" ] TIMEOUT = 5000 def pytest_addoption(parser): parser.addoption( "--env_file", action="store", ) parser.addoption( "--tests_dir", action="store", ) parser.addoption( "--session_id", action="store", ) @pytest.fixture(scope="session", autouse=True) def dirmanager(request) -> DirManager: tests_dir = request.config.getoption("--tests_dir") tests_dir = Path(tests_dir) session_id = request.config.getoption("--session_id") return DirManager(tests_dir=tests_dir, session_id=session_id) @pytest.fixture(scope="session", autouse=True) def dotenv_config(request) -> dict[str, str]: dotenv_path = request.config.getoption("--env_file") dotenv_path = Path(dotenv_path) assert dotenv_path.is_file() return dotenv_values(dotenv_path) @pytest.fixture(scope="session", autouse=True) def RECORDS(dirmanager) -> Path: assert isinstance(dirmanager, DirManager) return dirmanager.RECORDS @pytest.fixture(scope="session", autouse=True) def STATES(dirmanager) -> Path: return dirmanager.STATES @pytest.fixture(scope="session", autouse=True) def RESULTS(dirmanager) -> Path: return dirmanager.RESULTS # log failed tests @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): # execute all other hooks to obtain the report object outcome = yield rep = outcome.get_result() # we only look at actual failing test calls, not setup/teardown if rep.when == "call" and rep.failed: # saves traceback as .txt for failed test filename = f"failed-{item.nodeid}.txt" filename = filename.replace("/", "-") filename = filename.replace("::", "-") filepath = item.funcargs["RESULTS"] / filename with open(filepath, "a") as f: f.write(rep.longreprtext + "\n") # trace chrome on failed test # inspired from https://docs.pytest.org/en/6.2.x/example/simple.html#request-example """ @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield rep = outcome.get_result() # set a report attribute for each phase of a call, which can # be "setup", "call", "teardown" setattr(item, "rep_" + rep.when, rep) @pytest.fixture def setup(request, context: BrowserContext): # before test context.tracing.start(screenshots=True, snapshots=True, sources=True) context.set_default_timeout(TIMEOUT) # test execution yield context # after test if request.node.rep_setup.failed: # test setup failed pass else: if request.node.rep_call.failed: # test execution failed filename = "trace-" + request.node.originalname + ".zip" context.tracing.stop(path=filename) """