titan-iac/testing/tests/test_publish_test_metrics_paths.py

142 lines
5.7 KiB
Python
Raw Normal View History

"""Unit tests for test-case path parsing and fallback metric labeling behavior."""
from __future__ import annotations
import json
from pathlib import Path
from ci.scripts import publish_test_metrics
def test_collect_junit_cases_handles_missing_files_and_multiple_root_shapes(tmp_path: Path, monkeypatch):
missing = tmp_path / "missing.xml"
testsuites_path = tmp_path / "suite-cases.xml"
testsuites_path.write_text(
(
"<testsuites>"
'<testsuite tests="3">'
'<testcase classname="alpha" name="ok_case" />'
'<testcase classname="alpha" name="skip_case"><skipped /></testcase>'
'<testcase classname="alpha"><failure /></testcase>'
"</testsuite>"
"</testsuites>"
),
encoding="utf-8",
)
unknown_root_path = tmp_path / "unknown-root.xml"
unknown_root_path.write_text("<root><testcase classname='x' name='ignored' /></root>", encoding="utf-8")
monkeypatch.setattr(
publish_test_metrics,
"glob",
lambda _pattern: [str(missing), str(testsuites_path), str(unknown_root_path)],
)
cases = publish_test_metrics._collect_junit_cases("ignored-glob")
assert ("alpha.ok_case", "passed") in cases
assert ("alpha.skip_case", "skipped") in cases
assert not any(name.endswith("ignored") for name, _ in cases)
def test_build_payload_includes_explicit_test_case_series():
payload = publish_test_metrics._build_payload(
suite="titan-iac",
status="ok",
tests={"tests": 2, "failures": 1, "errors": 0, "skipped": 0},
test_cases=[("alpha::case_one", "failed"), ("beta::case_two", "passed")],
ok_count=3,
failed_count=1,
branch="main",
build_number="5",
jenkins_job="titan-iac",
workspace_line_coverage_percent=95.0,
source_lines_over_500=0,
check_statuses={"tests": "failed"},
)
assert (
'platform_quality_gate_test_case_result{suite="titan-iac",branch="main",build_number="5",jenkins_job="titan-iac",test="alpha::case_one",status="failed"} 1'
in payload
)
assert (
'platform_quality_gate_test_case_result{suite="titan-iac",branch="main",build_number="5",jenkins_job="titan-iac",test="beta::case_two",status="passed"} 1'
in payload
)
def test_main_uses_reported_coverage_and_loc_without_fallback(tmp_path: Path, monkeypatch, capsys):
build_dir = tmp_path / "build"
build_dir.mkdir()
(build_dir / "junit.xml").write_text(
'<testsuite tests="1" failures="0" errors="0" skipped="0" />',
encoding="utf-8",
)
(build_dir / "quality-gate.rc").write_text("0\n", encoding="utf-8")
(build_dir / "quality-gate-summary.json").write_text(
json.dumps(
{
"workspace_line_coverage_percent": 99.5,
"source_lines_over_500": 2,
"results": [],
}
),
encoding="utf-8",
)
monkeypatch.setenv("JUNIT_GLOB", str(build_dir / "*.xml"))
monkeypatch.setenv("QUALITY_GATE_EXIT_CODE_PATH", str(build_dir / "quality-gate.rc"))
monkeypatch.setenv("QUALITY_GATE_SUMMARY_PATH", str(build_dir / "quality-gate-summary.json"))
monkeypatch.setattr(publish_test_metrics, "_fetch_existing_counter", lambda *args, **kwargs: 0)
monkeypatch.setattr(publish_test_metrics, "_post_text", lambda *args, **kwargs: None)
monkeypatch.setattr(
publish_test_metrics,
"_infer_workspace_coverage_percent",
lambda *args, **kwargs: (_ for _ in ()).throw(AssertionError("should not infer coverage")),
)
monkeypatch.setattr(
publish_test_metrics,
"_infer_source_lines_over_500",
lambda *args, **kwargs: (_ for _ in ()).throw(AssertionError("should not infer loc")),
)
rc = publish_test_metrics.main()
summary = json.loads(capsys.readouterr().out)
assert rc == 0
assert summary["workspace_line_coverage_percent"] == 99.5
assert summary["source_lines_over_500"] == 2
def test_main_falls_back_to_inferred_coverage_and_loc(tmp_path: Path, monkeypatch, capsys):
build_dir = tmp_path / "build"
build_dir.mkdir()
(build_dir / "junit.xml").write_text(
'<testsuite tests="1" failures="0" errors="0" skipped="0" />',
encoding="utf-8",
)
(build_dir / "quality-gate.rc").write_text("1\n", encoding="utf-8")
(build_dir / "quality-gate-summary.json").write_text(
json.dumps({"workspace_line_coverage_percent": 0.0, "source_lines_over_500": 0, "results": []}),
encoding="utf-8",
)
posted = {}
monkeypatch.setenv("JUNIT_GLOB", str(build_dir / "*.xml"))
monkeypatch.setenv("QUALITY_GATE_EXIT_CODE_PATH", str(build_dir / "quality-gate.rc"))
monkeypatch.setenv("QUALITY_GATE_SUMMARY_PATH", str(build_dir / "quality-gate-summary.json"))
monkeypatch.setattr(publish_test_metrics, "_fetch_existing_counter", lambda *args, **kwargs: 0)
monkeypatch.setattr(publish_test_metrics, "_post_text", lambda url, payload: posted.update({"url": url, "payload": payload}))
monkeypatch.setattr(publish_test_metrics, "_infer_workspace_coverage_percent", lambda *args, **kwargs: 96.4)
monkeypatch.setattr(publish_test_metrics, "_infer_source_lines_over_500", lambda *args, **kwargs: 7)
rc = publish_test_metrics.main()
summary = json.loads(capsys.readouterr().out)
assert rc == 0
assert summary["status"] == "failed"
assert summary["workspace_line_coverage_percent"] == 96.4
assert summary["source_lines_over_500"] == 7
assert 'platform_quality_gate_workspace_line_coverage_percent{suite="titan_iac"} 96.400' in posted["payload"]
assert 'platform_quality_gate_source_lines_over_500_total{suite="titan_iac"} 7' in posted["payload"]