Spaces:
Running
Running
RemiFabre commited on
Commit ·
9edf0fd
1
Parent(s): 2a6e555
Fix test coverage merging: seed from test_coverage.json on first run
Browse filestest_results.json is git-ignored (local to each machine). When a new
contributor ran tests, their empty file caused export_web_coverage() to
overwrite test_coverage.json with only their results, erasing other
testers' data.
Now load_results() seeds from the committed test_coverage.json when
test_results.json is missing or empty, so the next export merges
results from all contributors. Same fix applied to show_matrix.py.
- tests/run_tests.py +48 -1
- tests/show_matrix.py +40 -7
tests/run_tests.py
CHANGED
|
@@ -216,8 +216,55 @@ def check_json_report_plugin() -> bool:
|
|
| 216 |
|
| 217 |
|
| 218 |
def load_results() -> list[dict]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
if RESULTS_FILE.exists():
|
| 220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 221 |
return []
|
| 222 |
|
| 223 |
|
|
|
|
| 216 |
|
| 217 |
|
| 218 |
def load_results() -> list[dict]:
|
| 219 |
+
"""Load past results from test_results.json, seeding from test_coverage.json if needed.
|
| 220 |
+
|
| 221 |
+
test_results.json is git-ignored (local to each machine). When a new
|
| 222 |
+
contributor runs for the first time, their file is empty — but the
|
| 223 |
+
committed test_coverage.json contains the matrix from other testers.
|
| 224 |
+
We import those entries so the next export *merges* instead of
|
| 225 |
+
overwriting.
|
| 226 |
+
"""
|
| 227 |
if RESULTS_FILE.exists():
|
| 228 |
+
try:
|
| 229 |
+
data = json.loads(RESULTS_FILE.read_text())
|
| 230 |
+
if data:
|
| 231 |
+
return data
|
| 232 |
+
except (json.JSONDecodeError, ValueError):
|
| 233 |
+
pass
|
| 234 |
+
|
| 235 |
+
# Seed from the committed web coverage file so we don't lose other
|
| 236 |
+
# contributors' results on first run.
|
| 237 |
+
if WEB_COVERAGE_FILE.exists():
|
| 238 |
+
try:
|
| 239 |
+
coverage = json.loads(WEB_COVERAGE_FILE.read_text())
|
| 240 |
+
entries = coverage.get("matrix", [])
|
| 241 |
+
if entries:
|
| 242 |
+
# Convert matrix entries back to results-like dicts.
|
| 243 |
+
# The matrix has: os, robot, suite, browser, status,
|
| 244 |
+
# passed, failed, total, date. We synthesise a
|
| 245 |
+
# timestamp from the generated_at field so the
|
| 246 |
+
# "latest per combo" logic still works.
|
| 247 |
+
generated = coverage.get("generated_at", datetime.now(timezone.utc).isoformat())
|
| 248 |
+
seeded = []
|
| 249 |
+
for e in entries:
|
| 250 |
+
seeded.append({
|
| 251 |
+
"timestamp": generated,
|
| 252 |
+
"os": e["os"],
|
| 253 |
+
"robot": e["robot"],
|
| 254 |
+
"suite": e["suite"],
|
| 255 |
+
"browser": e.get("browser"),
|
| 256 |
+
"passed": e.get("passed", 0),
|
| 257 |
+
"failed": e.get("failed", 0),
|
| 258 |
+
"errors": 0,
|
| 259 |
+
"total": e.get("total", 0),
|
| 260 |
+
"status": e.get("status", "pass"),
|
| 261 |
+
"returncode": 0,
|
| 262 |
+
})
|
| 263 |
+
print(f"Seeded {len(seeded)} entries from {WEB_COVERAGE_FILE.name}")
|
| 264 |
+
return seeded
|
| 265 |
+
except (json.JSONDecodeError, ValueError):
|
| 266 |
+
pass
|
| 267 |
+
|
| 268 |
return []
|
| 269 |
|
| 270 |
|
tests/show_matrix.py
CHANGED
|
@@ -122,15 +122,48 @@ def print_catalog(catalog: list[dict]) -> None:
|
|
| 122 |
print()
|
| 123 |
|
| 124 |
|
| 125 |
-
def
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
if not results:
|
| 133 |
-
print("No test results
|
| 134 |
print("Run tests first: python tests/run_tests.py")
|
| 135 |
sys.exit(1)
|
| 136 |
|
|
|
|
| 122 |
print()
|
| 123 |
|
| 124 |
|
| 125 |
+
def load_results() -> list[dict]:
|
| 126 |
+
"""Load results from test_results.json, falling back to test_coverage.json."""
|
| 127 |
+
if RESULTS_FILE.exists():
|
| 128 |
+
try:
|
| 129 |
+
data = json.loads(RESULTS_FILE.read_text())
|
| 130 |
+
if data:
|
| 131 |
+
return data
|
| 132 |
+
except (json.JSONDecodeError, ValueError):
|
| 133 |
+
pass
|
| 134 |
|
| 135 |
+
# Fall back to the committed web coverage file
|
| 136 |
+
if WEB_COVERAGE_FILE.exists():
|
| 137 |
+
try:
|
| 138 |
+
coverage = json.loads(WEB_COVERAGE_FILE.read_text())
|
| 139 |
+
entries = coverage.get("matrix", [])
|
| 140 |
+
generated = coverage.get("generated_at", "2025-01-01T00:00:00+00:00")
|
| 141 |
+
return [
|
| 142 |
+
{
|
| 143 |
+
"timestamp": generated,
|
| 144 |
+
"os": e["os"],
|
| 145 |
+
"robot": e["robot"],
|
| 146 |
+
"suite": e["suite"],
|
| 147 |
+
"browser": e.get("browser"),
|
| 148 |
+
"passed": e.get("passed", 0),
|
| 149 |
+
"failed": e.get("failed", 0),
|
| 150 |
+
"errors": 0,
|
| 151 |
+
"total": e.get("total", 0),
|
| 152 |
+
"status": e.get("status", "pass"),
|
| 153 |
+
"returncode": 0,
|
| 154 |
+
}
|
| 155 |
+
for e in entries
|
| 156 |
+
]
|
| 157 |
+
except (json.JSONDecodeError, ValueError):
|
| 158 |
+
pass
|
| 159 |
+
|
| 160 |
+
return []
|
| 161 |
+
|
| 162 |
+
|
| 163 |
+
def main() -> None:
|
| 164 |
+
results = load_results()
|
| 165 |
if not results:
|
| 166 |
+
print("No test results found.")
|
| 167 |
print("Run tests first: python tests/run_tests.py")
|
| 168 |
sys.exit(1)
|
| 169 |
|