"""Unit tests for the pure single-run summary seam. build_run_summary is the single reusable落点 for one run's口径 (pass_rate / judged_pass_rate / avg_latency / connectivity split), parallel to metrics.aggregate_runs (cross-run) and judgement.combine_case_outcome (case-level). No IO — fed constructed material, asserted directly. """ from agenteval.evaluation.judgement import CaseOutcome from agenteval.evaluation.run_summary import build_run_summary def _outcomes(**kw: CaseOutcome) -> dict[str, CaseOutcome]: return dict(kw) def test_all_judged_passing(): summary = build_run_summary( case_outcomes=_outcomes( a=CaseOutcome(passed=True, connectivity=False), b=CaseOutcome(passed=True, connectivity=False), ), latencies=[100.0, 300.0], rule_passes=[True, True, True], ) assert summary.total_cases == 2 assert summary.passed_cases == 2 assert summary.failed_cases == 0 assert summary.pass_rate == 1.0 assert summary.judged_pass_rate == 1.0 assert summary.total_rules == 3 assert summary.passed_rules == 3 assert summary.avg_latency_ms == 200.0 def test_mixed_pass_fail(): summary = build_run_summary( case_outcomes=_outcomes( a=CaseOutcome(passed=True, connectivity=False), b=CaseOutcome(passed=False, connectivity=False), c=CaseOutcome(passed=False, connectivity=False), ), latencies=[], rule_passes=[True, False], ) assert summary.total_cases == 3 assert summary.passed_cases == 1 assert summary.failed_cases == 2 assert summary.pass_rate == 0.3333 assert summary.judged_pass_rate == 0.3333 assert summary.passed_rules == 1 assert summary.total_rules == 2 assert summary.avg_latency_ms is None def test_connectivity_excluded_from_judged_rate(): # 连通用例计入总通过率,但从判定型口径的分子分母双双剔除(report.py 现口径) summary = build_run_summary( case_outcomes=_outcomes( conn=CaseOutcome(passed=True, connectivity=True), judged_pass=CaseOutcome(passed=True, connectivity=False), judged_fail=CaseOutcome(passed=False, connectivity=False), ), latencies=[50.0], rule_passes=[True, False], ) assert summary.total_cases == 3 assert summary.passed_cases == 2 # conn + judged_pass assert summary.pass_rate == 0.6667 # judged: 分母 = 3 - 1 连通 = 2;分子 = 2 通过 - 1 连通 = 1 assert summary.judged_pass_rate == 0.5 def test_all_connectivity_yields_no_judged_rate(): summary = build_run_summary( case_outcomes=_outcomes( a=CaseOutcome(passed=True, connectivity=True), b=CaseOutcome(passed=True, connectivity=True), ), latencies=[10.0], rule_passes=[], ) assert summary.pass_rate == 1.0 assert summary.judged_pass_rate is None # judged_total == 0 def test_empty_run(): summary = build_run_summary(case_outcomes={}, latencies=[], rule_passes=[]) assert summary.total_cases == 0 assert summary.pass_rate == 0.0 assert summary.judged_pass_rate is None assert summary.avg_latency_ms is None def test_case_errors_and_model_configs_passed_through(): errors = [{"case_id": "x", "message": "boom"}] configs = {"judge": {"model": "gpt-4o"}} summary = build_run_summary( case_outcomes=_outcomes(x=CaseOutcome(passed=False, connectivity=False)), latencies=[], rule_passes=[], case_errors=errors, model_configs=configs, ) assert summary.case_errors == errors assert summary.model_configs == configs def test_case_outcomes_persisted_as_verdict_snapshot(): summary = build_run_summary( case_outcomes=_outcomes(a=CaseOutcome(passed=True, connectivity=True)), latencies=[], rule_passes=[], ) assert summary.case_outcomes["a"].passed is True assert summary.case_outcomes["a"].connectivity is True