"""Tests for common.coverage_gate — GateConfig, check_thresholds, load_totals."""
from __future__ import annotations
import json
from pathlib import Path
import pytest
from scripts.helpers.common.coverage_gate import GateConfig, check_thresholds, load_totals
from tests.helpers.fake_subprocess import FakeCompleted
def test_check_thresholds_all_met_returns_empty(gate_config: GateConfig) -> None:
failures = check_thresholds(80.0, 60.0, gate_config)
assert failures == []
def test_check_thresholds_line_equals_threshold_passes(gate_config: GateConfig) -> None:
failures = check_thresholds(70.0, 60.0, gate_config)
assert failures == []
def test_check_thresholds_line_below_reports_failure(gate_config: GateConfig) -> None:
failures = check_thresholds(65.0, 60.0, gate_config)
assert len(failures) == 1
assert "line coverage 65.0% < 70.0%" in failures[0]
def test_check_thresholds_branch_below_reports_failure(gate_config: GateConfig) -> None:
failures = check_thresholds(80.0, 45.0, gate_config)
assert len(failures) == 1
assert "branch coverage 45.0% < 50.0%" in failures[0]
def test_check_thresholds_both_below_reports_two_failures(
gate_config: GateConfig,
) -> None:
failures = check_thresholds(60.0, 40.0, gate_config)
assert len(failures) == 2
_COVERAGE_JSON_STDOUT = json.dumps(
{
"totals": {
"percent_covered_display": "85.0%",
"num_branches": 10,
"covered_branches": 8,
},
}
)
def test_load_totals_missing_file_raises(tmp_path: Path) -> None:
missing = tmp_path / ".coverage"
with pytest.raises(FileNotFoundError, match="not found"):
load_totals(missing)
@pytest.fixture(scope="module")
def coverage_data_file(tmp_path_factory: pytest.TempPathFactory) -> Path:
path = tmp_path_factory.mktemp("cov") / ".coverage"
path.write_text("", encoding="utf-8")
return path
def test_load_totals_parses_subprocess_json(monkeypatch: pytest.MonkeyPatch, coverage_data_file: Path) -> None:
monkeypatch.setattr("subprocess.run", lambda *a, **kw: FakeCompleted(0, _COVERAGE_JSON_STDOUT, ""))
totals = load_totals(coverage_data_file)
assert totals.line_percent == 85.0
assert totals.branch_percent == 80.0
def test_load_totals_subprocess_failure_raises(monkeypatch: pytest.MonkeyPatch, coverage_data_file: Path) -> None:
monkeypatch.setattr("subprocess.run", lambda *a, **kw: FakeCompleted(1, "", "coverage error"))
with pytest.raises(RuntimeError, match="coverage json failed"):
load_totals(coverage_data_file)