Skip to content

Commit e739d49

Browse files
committed
update
1 parent 8f81253 commit e739d49

File tree

1 file changed

+118
-6
lines changed

1 file changed

+118
-6
lines changed

utils/consolidated_test_report.py

Lines changed: 118 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,37 @@ def parse_stats_file(file_path):
8686
return {"tests": 0, "passed": 0, "failed": 0, "skipped": 0, "slowest_tests": []}
8787

8888

89+
def parse_durations_file(file_path):
90+
"""Parse a durations file to extract test timing information."""
91+
slowest_tests = []
92+
try:
93+
durations_file = file_path.replace("_stats.txt", "_durations.txt")
94+
if os.path.exists(durations_file):
95+
with open(durations_file, "r") as f:
96+
content = f.read()
97+
98+
# Skip the header line
99+
for line in content.split('\n')[1:]:
100+
if line.strip():
101+
# Format is typically: 10.37s call tests/path/to/test.py::TestClass::test_method
102+
parts = line.strip().split()
103+
if len(parts) >= 3:
104+
time_str = parts[0]
105+
test_path = ' '.join(parts[2:])
106+
try:
107+
time_seconds = float(time_str.rstrip('s'))
108+
slowest_tests.append({
109+
"test": test_path,
110+
"duration": time_seconds
111+
})
112+
except ValueError:
113+
pass
114+
except Exception as e:
115+
print(f"Error parsing durations file {file_path.replace('_stats.txt', '_durations.txt')}: {e}")
116+
117+
return slowest_tests
118+
119+
89120
def parse_failures_file(file_path):
90121
"""Parse a failures file to extract failed test details."""
91122
failures = []
@@ -217,6 +248,10 @@ def consolidate_reports(reports_dir):
217248

218249
# Parse stats
219250
stats = parse_stats_file(stats_file)
251+
252+
# If no slowest tests found in stats file, try the durations file directly
253+
if not stats.get("slowest_tests"):
254+
stats["slowest_tests"] = parse_durations_file(stats_file)
220255

221256
# Update total stats
222257
for key in ["tests", "passed", "failed", "skipped"]:
@@ -271,8 +306,50 @@ def consolidate_reports(reports_dir):
271306
# Get the number of slowest tests to show from environment variable or default to 10
272307
num_slowest_tests = int(os.environ.get("SHOW_SLOWEST_TESTS", "10"))
273308
top_slowest_tests = all_slow_tests[:num_slowest_tests] if all_slow_tests else []
274-
275-
return {"total_stats": total_stats, "test_suites": results, "slowest_tests": top_slowest_tests}
309+
310+
# Calculate additional duration statistics
311+
total_duration = sum(test["duration"] for test in all_slow_tests)
312+
313+
# Calculate duration per suite
314+
suite_durations = {}
315+
for test in all_slow_tests:
316+
suite_name = test["suite"]
317+
if suite_name not in suite_durations:
318+
suite_durations[suite_name] = 0
319+
suite_durations[suite_name] += test["duration"]
320+
321+
# Create duration categories
322+
duration_categories = {
323+
"under_1s": 0,
324+
"1s_to_5s": 0,
325+
"5s_to_10s": 0,
326+
"10s_to_30s": 0,
327+
"over_30s": 0
328+
}
329+
330+
for test in all_slow_tests:
331+
duration = test["duration"]
332+
if duration < 1:
333+
duration_categories["under_1s"] += 1
334+
elif duration < 5:
335+
duration_categories["1s_to_5s"] += 1
336+
elif duration < 10:
337+
duration_categories["5s_to_10s"] += 1
338+
elif duration < 30:
339+
duration_categories["10s_to_30s"] += 1
340+
else:
341+
duration_categories["over_30s"] += 1
342+
343+
return {
344+
"total_stats": total_stats,
345+
"test_suites": results,
346+
"slowest_tests": top_slowest_tests,
347+
"duration_stats": {
348+
"total_duration": total_duration,
349+
"suite_durations": suite_durations,
350+
"duration_categories": duration_categories
351+
}
352+
}
276353

277354

278355
def generate_report(consolidated_data):
@@ -289,21 +366,49 @@ def generate_report(consolidated_data):
289366
total = consolidated_data["total_stats"]
290367
report.append("## Summary")
291368

369+
# Get duration stats if available
370+
duration_stats = consolidated_data.get("duration_stats", {})
371+
total_duration = duration_stats.get("total_duration", 0)
372+
292373
summary_table = [
293374
["Total Tests", total["tests"]],
294375
["Passed", total["passed"]],
295376
["Failed", total["failed"]],
296377
["Skipped", total["skipped"]],
297378
["Success Rate", f"{(total['passed'] / total['tests'] * 100):.2f}%" if total["tests"] > 0 else "N/A"],
379+
["Total Duration", f"{total_duration:.2f}s" if total_duration else "N/A"],
298380
]
299381

300382
report.append(tabulate(summary_table, tablefmt="pipe"))
301383
report.append("")
384+
385+
# Add duration distribution if available
386+
duration_categories = duration_stats.get("duration_categories")
387+
if duration_categories:
388+
report.append("### Test Duration Distribution")
389+
390+
distribution_table = [
391+
["Duration Range", "Number of Tests"],
392+
["Under 1s", duration_categories.get("under_1s", 0)],
393+
["1s to 5s", duration_categories.get("1s_to_5s", 0)],
394+
["5s to 10s", duration_categories.get("5s_to_10s", 0)],
395+
["10s to 30s", duration_categories.get("10s_to_30s", 0)],
396+
["Over 30s", duration_categories.get("over_30s", 0)],
397+
]
398+
399+
report.append(tabulate(distribution_table, headers="firstrow", tablefmt="pipe"))
400+
report.append("")
302401

303402
# Add test suites summary
304403
report.append("## Test Suites")
305404

306-
suites_table = [["Test Suite", "Tests", "Passed", "Failed", "Skipped", "Success Rate"]]
405+
# Include duration in test suites table if available
406+
suite_durations = consolidated_data.get("duration_stats", {}).get("suite_durations", {})
407+
408+
if suite_durations:
409+
suites_table = [["Test Suite", "Tests", "Passed", "Failed", "Skipped", "Success Rate", "Duration (s)"]]
410+
else:
411+
suites_table = [["Test Suite", "Tests", "Passed", "Failed", "Skipped", "Success Rate"]]
307412

308413
# Sort test suites by number of failures (descending)
309414
sorted_suites = sorted(
@@ -313,9 +418,16 @@ def generate_report(consolidated_data):
313418
for suite_name, suite_data in sorted_suites:
314419
stats = suite_data["stats"]
315420
success_rate = f"{(stats['passed'] / stats['tests'] * 100):.2f}%" if stats["tests"] > 0 else "N/A"
316-
suites_table.append(
317-
[suite_name, stats["tests"], stats["passed"], stats["failed"], stats["skipped"], success_rate]
318-
)
421+
422+
if suite_durations:
423+
duration = suite_durations.get(suite_name, 0)
424+
suites_table.append(
425+
[suite_name, stats["tests"], stats["passed"], stats["failed"], stats["skipped"], success_rate, f"{duration:.2f}"]
426+
)
427+
else:
428+
suites_table.append(
429+
[suite_name, stats["tests"], stats["passed"], stats["failed"], stats["skipped"], success_rate]
430+
)
319431

320432
report.append(tabulate(suites_table, headers="firstrow", tablefmt="pipe"))
321433
report.append("")

0 commit comments

Comments
 (0)