"""全局 conftest — 配置/日志 fixtures + Allure 集成。 架构分层 (POM): core/ 框架层: 配置、日志、DB、驱动工厂、截图、Allure 集成 pages/ PO 层: 页面对象,与用例分离 config/ YAML 配置 Usage: def test_xxx(admin_config): # 管理端配置 def test_xxx(driver_android_config): # 司机安卓配置 """ import sys from pathlib import Path import allure import pytest # 兼容两种 import 风格: from tests.core.xxx (项目根为源根) # 与 from core.xxx (tests/ 为源根, 如 PyCharm 将 tests/ 标记为 Sources Root) if (tests_root := str(Path(__file__).parent)) not in sys.path: sys.path.insert(0, tests_root) @pytest.fixture(scope="session") def config(): """全局配置(session 级,只加载一次)。""" from tests.core.config_loader import load_config return load_config() @pytest.fixture(scope="function") def logger(request): """每个测试函数的 logger。""" from tests.core.logger import get_logger module_name = request.module.__name__.replace("tests.", "") return get_logger(module_name) # ═══════════════════════════════════════════════════════════════════ # 各端配置 fixture(从 config 中摘取对应 section) # ═══════════════════════════════════════════════════════════════════ @pytest.fixture(scope="session") def admin_config(config): """管理端 (Playwright) 配置。""" return config["admin"] @pytest.fixture(scope="session") def mini_program_config(config): """司机端小程序 (miniprogram-automator) 配置。""" return config["mini_program"] @pytest.fixture(scope="session") def driver_android_config(config): """司机安卓端 (Appium) 配置。""" return config["driver_android"] # ═══════════════════════════════════════════════════════════════════ # Allure 集成 # ═══════════════════════════════════════════════════════════════════ # pytest marker → Allure severity 自动映射(marker 是唯一事实源) _MARKER_SEVERITY = { "p0": allure.severity_level.BLOCKER, "p1": allure.severity_level.NORMAL, "p2": allure.severity_level.MINOR, } def pytest_collection_modifyitems(items): """按 p0/p1/p2 marker 自动设置 Allure severity。""" for item in items: for marker, severity in _MARKER_SEVERITY.items(): if item.get_closest_marker(marker): item.add_marker(allure.severity(severity)) break def pytest_sessionfinish(session): """向 allure-results 写入 environment.properties。""" # 注意: allure-pytest 的 --alluredir 选项 dest 为 allure_report_dir results_dir = session.config.getoption("allure_report_dir", default=None) if not results_dir: return from tests.core.allure_support import write_environment_properties from tests.core.config_loader import load_config write_environment_properties(results_dir, load_config()) # ═══════════════════════════════════════════════════════════════════ # Report hook — 让 request.node.rep_call.failed 可用于失败截图 # ═══════════════════════════════════════════════════════════════════ @pytest.hookimpl(tryfirst=True, hookwrapper=True) def pytest_runtest_makereport(item, call): outcome = yield rep = outcome.get_result() setattr(item, f"rep_{rep.when}", rep)