fix: [test] _measure_coverage overall 计算未排除 0 项维度 - Closes #36 #42
@@ -291,6 +291,85 @@ def _measure_coverage(ir_data: dict, parsed_data: dict) -> dict:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_measure_coverage_excludes_zero_dimensions():
|
||||||
|
"""#36: dimensions with total=0 must not drag down the overall rate.
|
||||||
|
|
||||||
|
When diagram total=0, the overall should be computed from sections and tables
|
||||||
|
only, not include a 0% diagram entry that makes the goal unreachable.
|
||||||
|
"""
|
||||||
|
parsed_data = {
|
||||||
|
"sections": [
|
||||||
|
{"source": "3.1.1 功能A", "blocks": [
|
||||||
|
{"type": "table", "rows": [{"cell": "1"}, {"cell": "2"}]}
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
"image_analysis": [], # no diagrams → total=0
|
||||||
|
}
|
||||||
|
# IR that covers the section but no table rows (table coverage = 0/2)
|
||||||
|
ir_data = {
|
||||||
|
"rules": [
|
||||||
|
{"sources": [{"section": "3.1.1"}]} # 1 section covered, 0 tables
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
cov = _measure_coverage(ir_data, parsed_data)
|
||||||
|
|
||||||
|
# Section: 1/1 = 100%, Table: 0/2 = 0%, Diagram: total=0 → excluded
|
||||||
|
assert cov["section_coverage"]["total"] == 1
|
||||||
|
assert cov["section_coverage"]["rate"] == 1.0
|
||||||
|
assert cov["table_coverage"]["total_rows"] == 2
|
||||||
|
assert cov["table_coverage"]["rate"] == 0.0
|
||||||
|
assert cov["diagram_coverage"]["total"] == 0
|
||||||
|
assert cov["diagram_coverage"]["rate"] == 1.0 # _safe_rate: 0/0 → 1.0
|
||||||
|
|
||||||
|
# Key assertion: diagram (total=0) is excluded from overall
|
||||||
|
# overall = (1.0 + 0.0) / 2 = 0.5
|
||||||
|
# NOT (1.0 + 0.0 + 1.0) / 3 = 0.667
|
||||||
|
assert cov["overall_rate"] == 0.5, (
|
||||||
|
f"Expected overall 0.5 (sections + tables only), got {cov['overall_rate']}. "
|
||||||
|
f"Zero-content dimension may be leaking into the average."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_measure_coverage_all_dimensions_have_content():
|
||||||
|
"""When all dimensions have content, all should be included."""
|
||||||
|
parsed_data = {
|
||||||
|
"sections": [
|
||||||
|
{"source": "3.1.1 功能A", "blocks": [
|
||||||
|
{"type": "table", "rows": [{"cell": "1"}]}
|
||||||
|
]}
|
||||||
|
],
|
||||||
|
"image_analysis": [{"type": "flowchart", "rid": "img_001"}],
|
||||||
|
}
|
||||||
|
ir_data = {
|
||||||
|
"rules": [
|
||||||
|
{"sources": [{"section": "3.1.1"}]},
|
||||||
|
{"sources": [{"type": "table", "section": "3.1.1", "row": 0}]},
|
||||||
|
{"sources": [{"type": "logic_tree", "image_id": "img_001"}]},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
cov = _measure_coverage(ir_data, parsed_data)
|
||||||
|
|
||||||
|
# All three dimensions have content → all included
|
||||||
|
assert cov["section_coverage"]["total"] == 1
|
||||||
|
assert cov["table_coverage"]["total_rows"] == 1
|
||||||
|
assert cov["diagram_coverage"]["total"] == 1
|
||||||
|
# overall = (1.0 + 1.0 + 1.0) / 3 = 1.0
|
||||||
|
assert cov["overall_rate"] == 1.0, (
|
||||||
|
f"Expected overall 1.0 (all covered), got {cov['overall_rate']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_measure_coverage_no_content_returns_zero():
|
||||||
|
"""When no dimensions have content, overall should be 0.0."""
|
||||||
|
parsed_data = {"sections": [], "image_analysis": []}
|
||||||
|
ir_data = {"rules": []}
|
||||||
|
|
||||||
|
cov = _measure_coverage(ir_data, parsed_data)
|
||||||
|
assert cov["overall_rate"] == 0.0
|
||||||
|
|
||||||
|
|
||||||
def test_layer_b_coverage(
|
def test_layer_b_coverage(
|
||||||
ir_data: dict,
|
ir_data: dict,
|
||||||
parsed_data: dict | None,
|
parsed_data: dict | None,
|
||||||
|
|||||||
Reference in New Issue
Block a user