85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
import glob
|
|
import json
|
|
from collections import defaultdict
|
|
from datetime import datetime
|
|
|
|
statuses = ['passed', 'failed', 'broken', 'skipped', 'unknown']
|
|
|
|
# Structure : results[file][test_func]['status_counts']
|
|
results = defaultdict(lambda: defaultdict(lambda: {
|
|
'status_counts': defaultdict(int)
|
|
}))
|
|
|
|
totals = defaultdict(int)
|
|
errors_by_file = defaultdict(list) # file -> list of (func, status, msg)
|
|
|
|
for f in glob.glob('allure-results/*-result.json'):
|
|
with open(f) as j:
|
|
data = json.load(j)
|
|
status = data.get('status', 'unknown').lower()
|
|
full_name = data.get('fullName', 'unknown')
|
|
|
|
if '#' in full_name:
|
|
file_part, func_part = full_name.split('#', 1)
|
|
else:
|
|
file_part, func_part = full_name, 'unknown'
|
|
|
|
file_name = file_part.replace('.', '/').strip() + '.py'
|
|
test_name = func_part.strip()
|
|
|
|
# Update count
|
|
results[file_name][test_name]['status_counts'][status] += 1
|
|
totals[status] += 1
|
|
|
|
# Collect individual error messages for failed/broken
|
|
if status in ['failed', 'broken']:
|
|
msg = data.get('statusDetails', {}).get('message', '').strip()
|
|
if msg:
|
|
errors_by_file[file_name].append((test_name, status, msg))
|
|
|
|
# Write markdown
|
|
with open('ci-reports/markdown/test-summary.md', 'w') as out:
|
|
out.write('# Test Summary\n\n')
|
|
|
|
for file in sorted(results):
|
|
file_totals = defaultdict(int)
|
|
out.write(f'## {file}\n\n')
|
|
out.write('| Test Function | Passed | Failed | Broken | Skipped | Unknown |\n')
|
|
out.write('|---------------|--------|--------|--------|---------|---------|\n')
|
|
|
|
for test_func in sorted(results[file]):
|
|
row = [test_func]
|
|
counts = results[file][test_func]['status_counts']
|
|
for s in statuses:
|
|
count = counts.get(s, 0)
|
|
file_totals[s] += count
|
|
row.append(str(count))
|
|
out.write('| ' + ' | '.join(row) + ' |\n')
|
|
|
|
# Totals per file
|
|
total_row = ['**Total**'] + [str(file_totals[s]) for s in statuses]
|
|
out.write('| ' + ' | '.join(total_row) + ' |\n\n')
|
|
|
|
# Failure details
|
|
if errors_by_file[file]:
|
|
out.write('### Failure Details\n\n')
|
|
grouped = defaultdict(list)
|
|
for func_name, status, msg in errors_by_file[file]:
|
|
grouped[func_name].append((status, msg))
|
|
|
|
for func_name in sorted(grouped):
|
|
out.write(f'#### {func_name}\n')
|
|
for i, (status, msg) in enumerate(grouped[func_name], 1):
|
|
safe_msg = msg.replace('\n', ' ').replace('|', '¦')
|
|
out.write(f'- **{status.capitalize()} #{i}**: `{safe_msg}`\n')
|
|
out.write('\n')
|
|
|
|
# Global totals
|
|
out.write('## Total Summary\n\n')
|
|
out.write('| Status | Count |\n')
|
|
out.write('|---------|-------|\n')
|
|
for s in statuses:
|
|
out.write(f'| {s.capitalize():<7} | {totals[s]} |\n')
|
|
|
|
# Optional timestamp
|
|
out.write(f'\n_Last updated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}_\n') |