"""Tests for the separate line/branch coverage policy gate.""" from __future__ import annotations from scripts import check_coverage_thresholds as MODULE def _report(line: float = 55.0, branch: float = 42.0) -> dict[str, object]: return { "totals": { "percent_statements_covered": line, "percent_branches_covered": branch, }, "files": { "obliteratus/example.py": { "summary": {"percent_statements_covered": 70.0}, "executed_lines": [1, 2, 4], "missing_lines": [3], }, }, } def test_validate_coverage_accepts_exact_floors(): assert MODULE.validate_coverage( _report(), min_line=55.0, min_branch=42.0, ) == [] def test_validate_coverage_reports_each_regression(): failures = MODULE.validate_coverage( _report(line=54.9, branch=41.9), min_line=55.0, min_branch=42.0, ) assert failures == [ "line coverage 54.90% is below the 55.00% floor", "branch coverage 41.90% is below the 42.00% floor", ] def test_validate_coverage_rejects_malformed_totals(): assert MODULE.validate_coverage( {}, min_line=55.0, min_branch=42.0, ) == ["coverage report is missing the totals object"] def test_validate_coverage_rejects_non_numeric_metrics(): report = _report() report["totals"]["percent_statements_covered"] = True report["totals"]["percent_branches_covered"] = float("nan") assert MODULE.validate_coverage( report, min_line=55.0, min_branch=42.0, ) == [ "coverage report is missing numeric percent_statements_covered", "coverage report is missing numeric percent_branches_covered", ] def test_validate_coverage_enforces_critical_file_floors(): assert MODULE.validate_coverage( _report(), min_line=55.0, min_branch=42.0, file_floors={"obliteratus/example.py": 70.0}, ) == [] report = _report() report["files"]["obliteratus/example.py"]["summary"]["percent_statements_covered"] = 69.9 assert MODULE.validate_coverage( report, min_line=55.0, min_branch=42.0, file_floors={"obliteratus/example.py": 70.0, "missing.py": 70.0}, ) == [ "critical file obliteratus/example.py coverage 69.90% is below the 70.00% floor", "coverage report is missing critical file missing.py", ] def test_critical_file_validation_continues_and_rejects_malformed_values(): report = _report() report["files"]["bool.py"] = { "summary": {"percent_statements_covered": True}, } report["files"]["text.py"] = { "summary": {"percent_statements_covered": "70"}, } assert MODULE.validate_coverage( report, min_line=55.0, min_branch=42.0, file_floors={ "missing.py": 70.0, "bool.py": 70.0, "text.py": 70.0, }, ) == [ "coverage report is missing critical file missing.py", "coverage report is missing numeric line coverage for bool.py", "coverage report is missing numeric line coverage for text.py", ] def test_parse_changed_lines_and_measurement_ignore_non_executable_lines(): diff = """diff --git a/obliteratus/example.py b/obliteratus/example.py +++ b/obliteratus/example.py @@ -1,2 +1,4 @@ diff --git a/tests/test_example.py b/tests/test_example.py +++ b/tests/test_example.py @@ -0,0 +1,2 @@ """ changed = MODULE.parse_changed_lines(diff) assert changed == { "obliteratus/example.py": {1, 2, 3, 4}, "tests/test_example.py": {1, 2}, } assert MODULE.changed_line_coverage(_report(), changed) == (3, 4, 75.0) assert MODULE.validate_changed_coverage( _report(), changed, minimum=90.0, ) == ["changed-line coverage 75.00% (3/4) is below the 90.00% floor"] def test_changed_line_gate_passes_when_diff_has_no_measured_source(): assert MODULE.changed_line_coverage(_report(), {"tests/test_example.py": {1}}) == ( 0, 0, 100.0, ) def test_changed_line_parser_ignores_hunks_before_paths_and_defaults_count_to_one(): diff = """@@ -1 +99 @@ +++ b/obliteratus/example.py @@ -2 +3 @@ """ assert MODULE.parse_changed_lines(diff) == {"obliteratus/example.py": {3}} def test_changed_line_measurement_handles_missing_fields_and_multiple_files(): report = { "files": { "obliteratus/no-fields.py": {"summary": {}}, "obliteratus/first.py": { "executed_lines": [1], "missing_lines": [2], }, "obliteratus/second.py": { "executed_lines": [4], "missing_lines": [5], }, }, } changed = { "missing-entry.py": {1}, "obliteratus/no-fields.py": {1}, "obliteratus/first.py": {1, 2, 99}, "obliteratus/second.py": {4, 5, 100}, } assert MODULE.changed_line_coverage(report, changed) == (2, 4, 50.0) def test_changed_line_gate_accepts_exact_floor(): changed = {"obliteratus/example.py": {1, 2, 3, 4}} assert MODULE.validate_changed_coverage( _report(), changed, minimum=75.0, ) == []