feat: extraction coverage summary in report
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user