"""Unit tests for the extraction_coverage block in the report summary. Both the classic pipeline and the agent runner build their summary via backend.pipeline.report.build_report, so unit tests on that function cover every summary-producing path. """ from backend.pipeline.report import build_report def _sheet(page, coverage=None, assertions=None): sheet = { "page_number": page, "sheet_number": f"S{page:03d}", "discipline": "S", "assertions": assertions if assertions is not None else [ {"text": "NOTE ALPHA", "object_type": "note"}, {"text": "NOTE BETA", "object_type": "note"}, ], } if coverage is not None: sheet["coverage"] = coverage return sheet def _cov(total, covered): return { "total_lines": total, "covered_lines": covered, "ratio": covered / total if total else 0.0, } def test_extraction_coverage_omitted_without_coverage_data(): report = build_report(conflicts=[], sheets=[_sheet(1), _sheet(2)], clusters=[]) assert "extraction_coverage" not in report["summary"] def test_extraction_coverage_healthy(): sheets = [_sheet(1, _cov(100, 95)), _sheet(2, _cov(80, 76))] report = build_report(conflicts=[], sheets=sheets, clusters=[]) cov = report["summary"]["extraction_coverage"] assert cov["pages_measured"] == 2 assert cov["pages_below_floor"] == [] assert cov["fallback_pages"] == [] assert cov["mean_ratio"] == round((0.95 + 0.95) / 2, 3) def test_extraction_coverage_flags_below_floor(): sheets = [ _sheet(1, _cov(100, 95)), _sheet(2, _cov(100, 40)), # ratio 0.4 < 0.6 floor _sheet(3, _cov(100, 59)), # ratio 0.59 < 0.6 floor ] report = build_report(conflicts=[], sheets=sheets, clusters=[]) cov = report["summary"]["extraction_coverage"] assert cov["pages_measured"] == 3 assert cov["pages_below_floor"] == [2, 3] assert cov["mean_ratio"] == round((0.95 + 0.4 + 0.59) / 3, 3) def test_extraction_coverage_flags_fallback_pages(): fallback_assertions = [ {"text": "NOTE ALPHA", "object_type": "note"}, {"text": "NOTE BETA", "object_type": "note", "grounding": "text_layer_fallback"}, ] sheets = [ _sheet(1, _cov(100, 90), assertions=fallback_assertions), _sheet(2, _cov(100, 90)), ] report = build_report(conflicts=[], sheets=sheets, clusters=[]) cov = report["summary"]["extraction_coverage"] assert cov["fallback_pages"] == [1] def test_extraction_coverage_mixed_sheets_only_counts_measured(): # Sheet 2 has no coverage dict (e.g. scanned page / older path). sheets = [_sheet(1, _cov(100, 50)), _sheet(2)] report = build_report(conflicts=[], sheets=sheets, clusters=[]) cov = report["summary"]["extraction_coverage"] assert cov["pages_measured"] == 1 assert cov["pages_below_floor"] == [1] assert cov["mean_ratio"] == 0.5