mirror of
https://github.com/elder-plinius/OBLITERATUS.git
synced 2026-08-17 16:37:30 +02:00
Enforce Gate 3 test quality budgets
This commit is contained in:
@@ -97,14 +97,40 @@ def junit_snapshot(path: Path) -> dict[str, Any]:
|
||||
failures: list[str] = []
|
||||
errors: list[str] = []
|
||||
skipped: list[str] = []
|
||||
durations: list[dict[str, str | float]] = []
|
||||
durations: list[dict[str, Any]] = []
|
||||
marker_totals: dict[str, dict[str, int | float]] = {}
|
||||
missing_marker_nodeids: list[str] = []
|
||||
for case in cases:
|
||||
nodeid = f"{case.attrib.get('classname', '<unknown>')}::{case.attrib.get('name', '<unknown>')}"
|
||||
try:
|
||||
duration = float(case.attrib.get("time", "0"))
|
||||
except ValueError as exc:
|
||||
raise ValueError(f"JUnit testcase {nodeid} has invalid time") from exc
|
||||
durations.append({"nodeid": nodeid, "seconds": duration})
|
||||
if not math.isfinite(duration) or duration < 0:
|
||||
raise ValueError(f"JUnit testcase {nodeid} has invalid time")
|
||||
marker_property = None
|
||||
properties = case.find("properties")
|
||||
if properties is not None:
|
||||
values = [
|
||||
item.attrib.get("value", "")
|
||||
for item in properties.findall("property")
|
||||
if item.attrib.get("name") == "duration_markers"
|
||||
]
|
||||
if len(values) > 1:
|
||||
raise ValueError(f"JUnit testcase {nodeid} repeats duration_markers")
|
||||
marker_property = values[0] if values else None
|
||||
if marker_property is None:
|
||||
missing_marker_nodeids.append(nodeid)
|
||||
markers = sorted({
|
||||
marker.strip()
|
||||
for marker in (marker_property or "unmarked").split(",")
|
||||
if marker.strip()
|
||||
})
|
||||
durations.append({"nodeid": nodeid, "seconds": duration, "markers": markers})
|
||||
for marker in markers:
|
||||
summary = marker_totals.setdefault(marker, {"tests": 0, "duration_seconds": 0.0})
|
||||
summary["tests"] = int(summary["tests"]) + 1
|
||||
summary["duration_seconds"] = float(summary["duration_seconds"]) + duration
|
||||
if case.find("failure") is not None:
|
||||
failures.append(nodeid)
|
||||
if case.find("error") is not None:
|
||||
@@ -113,6 +139,20 @@ def junit_snapshot(path: Path) -> dict[str, Any]:
|
||||
skipped.append(nodeid)
|
||||
failed = set(failures) | set(errors) | set(skipped)
|
||||
durations.sort(key=lambda item: (-float(item["seconds"]), str(item["nodeid"])))
|
||||
suites = list(root.iter("testsuite"))
|
||||
raw_suite_duration = suites[0].attrib.get("time") if suites else None
|
||||
try:
|
||||
suite_duration = (
|
||||
float(raw_suite_duration)
|
||||
if raw_suite_duration is not None
|
||||
else sum(float(item["seconds"]) for item in durations)
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise ValueError("JUnit testsuite has invalid time") from exc
|
||||
if not math.isfinite(suite_duration) or suite_duration < 0:
|
||||
raise ValueError("JUnit testsuite has invalid time")
|
||||
for summary in marker_totals.values():
|
||||
summary["duration_seconds"] = round(float(summary["duration_seconds"]), 3)
|
||||
return {
|
||||
"total": len(cases),
|
||||
"passed": len(cases) - len(failed),
|
||||
@@ -120,6 +160,11 @@ def junit_snapshot(path: Path) -> dict[str, Any]:
|
||||
"errors": errors,
|
||||
"skipped": skipped,
|
||||
"duration_seconds": round(sum(float(item["seconds"]) for item in durations), 3),
|
||||
"suite_duration_seconds": round(suite_duration, 3),
|
||||
"durations": durations,
|
||||
"marker_durations": dict(sorted(marker_totals.items())),
|
||||
"marker_metadata_complete": not missing_marker_nodeids,
|
||||
"missing_marker_nodeids": missing_marker_nodeids,
|
||||
"slowest": durations[:20],
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user