from __future__ import annotations import os from datetime import datetime from pathlib import Path import pytest import requests from parity.client import can_reach_both, can_reach_one, default_headers _DIR = Path(__file__).resolve().parent def pytest_configure(config): config._parity_rows = [] # type: ignore[attr-defined] config._smoke_rows = [] # type: ignore[attr-defined] def pytest_addoption(parser): parser.addoption( "--base-old", default=os.environ.get("ELEVATOR_BASE_OLD", "http://127.0.0.1:18080"), ) parser.addoption( "--base-new", default=os.environ.get("ELEVATOR_BASE_NEW", "http://127.0.0.1:18081"), ) parser.addoption( "--smoke-base", default=os.environ.get("ELEVATOR_SMOKE_BASE", "http://127.0.0.1:18080"), ) parser.addoption( "--smoke-label", default=os.environ.get("ELEVATOR_SMOKE_LABEL", "v1_legacy"), ) @pytest.fixture(scope="session") def base_old(request): return str(request.config.getoption("--base-old")).rstrip("/") @pytest.fixture(scope="session") def base_new(request): return str(request.config.getoption("--base-new")).rstrip("/") @pytest.fixture(scope="session") def smoke_base(request): return str(request.config.getoption("--smoke-base")).rstrip("/") @pytest.fixture(scope="session") def smoke_label(request): return str(request.config.getoption("--smoke-label")) @pytest.fixture(scope="session") def session_http(): s = requests.Session() s.headers.update(default_headers()) yield s s.close() @pytest.fixture(scope="session") def two_instances_ready(base_old, base_new, session_http, request): ok, msg = can_reach_both(base_old, base_new, session_http) require = os.environ.get("ELEVATOR_PARITY_REQUIRE_LIVE", "") if not ok and not require: pytest.skip(f"双端健康检查不通过(跳过用例): {msg}") if not ok and require: pytest.fail(f"ELEVATOR_PARITY_REQUIRE_LIVE=1 且双端不可达: {msg}") return True @pytest.fixture(scope="session") def smoke_instance_ready(smoke_base, session_http, request): ok, _ = can_reach_one(smoke_base, session_http) require = os.environ.get("ELEVATOR_SMOKE_REQUIRE", "") if not ok and not require: pytest.skip(f"单机 {smoke_base} 健康检查不通过(跳过 smoke)") if not ok and require: pytest.fail(f"ELEVATOR_SMOKE_REQUIRE=1 且 {smoke_base} 不可达") return True def _write_smoke_report(config, srows: list, report_dir: Path) -> None: from report import generate_smoke_report label = str(config.getoption("--smoke-label", default="smoke")) p2 = report_dir / f"smoke-{label}-{datetime.now().strftime('%Y%m%d-%H%M%S')}.md" generate_smoke_report.write_file( p2, str(config.getoption("--smoke-base", default="")), label, srows, ) print(f"\n[smoke] 报告: {p2}") def pytest_sessionfinish(session, exitstatus): import importlib config = session.config report_dir = _DIR / "report" report_dir.mkdir(parents=True, exist_ok=True) rows = getattr(config, "_parity_rows", None) or [] if rows: try: gen = importlib.import_module("report.generate_report") p = report_dir / gen.timestamped_name("parity") gen.write_file( p, str(config.getoption("--base-old", default="")), str(config.getoption("--base-new", default="")), rows, ) print(f"\n[parity] 对拍报告: {p}") except Exception as e: print(f"\n[parity] 对拍报告未生成: {e}") srows = getattr(config, "_smoke_rows", None) or [] if srows: try: _write_smoke_report(config, srows, report_dir) except Exception as e: print(f"\n[smoke] 报告未生成: {e}")