"""Tests for the separate line/branch coverage policy gate.""" from __future__ import annotations import importlib.util from pathlib import Path SCRIPT = Path(__file__).parents[1] / "scripts" / "check_coverage_thresholds.py" SPEC = importlib.util.spec_from_file_location("check_coverage_thresholds", SCRIPT) assert SPEC is not None and SPEC.loader is not None MODULE = importlib.util.module_from_spec(SPEC) SPEC.loader.exec_module(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_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, )