"""黄金集回归 pytest 入口(marker=golden;无 MEIDA_RUN_INTEGRATION 时整体 skip). 薄壳(任务文档 §3.4):加载/执行/指标/明细全部在 ``runner.py``——本文件只把 ``SubsetReport`` 的指标对齐 thresholds,退化时把逐用例明细完整抛给 CI 日志。 Run: MEIDA_RUN_INTEGRATION=1 .venv/bin/pytest -m golden --no-cov(即 make golden) """ from __future__ import annotations import os from collections.abc import AsyncIterator import pytest from packages.shared.db import dispose_engine from tests.golden import runner pytestmark = [ pytest.mark.golden, pytest.mark.skipif( not os.getenv("MEIDA_RUN_INTEGRATION"), reason="需要真实 PostgreSQL/pgvector:MEIDA_RUN_INTEGRATION=1(make golden)", ), ] @pytest.fixture(autouse=True) async def _hermetic_engine() -> AsyncIterator[None]: """每个用例前后重建全局 engine:asyncpg 连接绑定创建它的事件循环, pytest-asyncio 给每个用例一个新 loop,复用池里旧连接会报 "attached to a different loop"(与 tests/integration 同一处理)。""" await dispose_engine() yield await dispose_engine() def test_rules_subset_meets_thresholds() -> None: """规则子集阈值 = 1.0:核心结论由规则产出,一条不许退(README 详述原因).""" report = runner.run_rules_subset() assert report.pass_rate >= report.pass_rate_min, f"规则黄金集指标退化:\n{report.summary()}" async def test_retrieval_subset_meets_thresholds() -> None: """检索子集 0.8 起步:pass_rate 与 first_hit_in_top3 双指标对齐阈值.""" report = await runner.run_retrieval_subset() detail = report.summary() assert report.pass_rate >= report.pass_rate_min, f"检索黄金集指标退化:\n{detail}" rate = report.first_hit_in_top3_rate assert rate is not None and rate >= report.first_hit_in_top3_min, ( f"检索黄金集 first_hit_in_top3 指标退化(或无用例声明该指标):\n{detail}" )