test-reporting 3.7.3__tar.gz → 3.7.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {test_reporting-3.7.3 → test_reporting-3.7.4}/PKG-INFO +1 -1
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/publisher.py +35 -28
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/templates/project.html +15 -7
- {test_reporting-3.7.3 → test_reporting-3.7.4}/setup.py +1 -1
- {test_reporting-3.7.3 → test_reporting-3.7.4}/test_reporting.egg-info/PKG-INFO +1 -1
- {test_reporting-3.7.3 → test_reporting-3.7.4}/LICENSE +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/README.md +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/__init__.py +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/classifier.py +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/cli.py +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/config.py +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/plugin.py +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/storage.py +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/templates/index.html +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/reporting/templates/run.html +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/setup.cfg +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/test_reporting.egg-info/SOURCES.txt +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/test_reporting.egg-info/dependency_links.txt +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/test_reporting.egg-info/entry_points.txt +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/test_reporting.egg-info/requires.txt +0 -0
- {test_reporting-3.7.3 → test_reporting-3.7.4}/test_reporting.egg-info/top_level.txt +0 -0
|
@@ -473,7 +473,7 @@ class Publisher:
|
|
|
473
473
|
tag = run.get('regression_tag') or self._date_tag(run.get('timestamp'))
|
|
474
474
|
ts = run.get('timestamp', '')
|
|
475
475
|
|
|
476
|
-
# Suite summary
|
|
476
|
+
# Suite summary (kept for backwards compatibility)
|
|
477
477
|
if suite not in suites:
|
|
478
478
|
suites[suite] = {'name': suite, 'last_run': ts,
|
|
479
479
|
'last_pass_rate': 0, 'runs': []}
|
|
@@ -494,11 +494,7 @@ class Publisher:
|
|
|
494
494
|
'duration_seconds': run.get('duration_seconds', 0),
|
|
495
495
|
})
|
|
496
496
|
|
|
497
|
-
# Regression grouping
|
|
498
|
-
# Strip [TAG] suffix to group reruns with original runs
|
|
499
|
-
import re
|
|
500
|
-
base_suite = re.sub(r'\s*\[.*?\]\s*$', '', suite)
|
|
501
|
-
|
|
497
|
+
# Regression grouping - group by actual test files, not suite names
|
|
502
498
|
if tag not in regressions:
|
|
503
499
|
regressions[tag] = {'tag': tag, 'date': tag[:10], 'suites': [],
|
|
504
500
|
'total_tests': 0, 'passed': 0, 'failed': 0, 'pass_rate': 0,
|
|
@@ -507,28 +503,39 @@ class Publisher:
|
|
|
507
503
|
# Track the latest timestamp for this regression
|
|
508
504
|
if ts > reg.get('timestamp', ''):
|
|
509
505
|
reg['timestamp'] = ts
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
if
|
|
519
|
-
|
|
520
|
-
existing['
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
existing['
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
506
|
+
|
|
507
|
+
# Process each test file in this run
|
|
508
|
+
for test_file in run.get('test_files', []):
|
|
509
|
+
file_name = test_file.get('file_name', 'unknown')
|
|
510
|
+
# Strip .py extension for consistency
|
|
511
|
+
base_file_name = file_name.replace('.py', '')
|
|
512
|
+
|
|
513
|
+
existing = next((s for s in reg['suites'] if s['suite'] == base_file_name), None)
|
|
514
|
+
if existing:
|
|
515
|
+
# Accumulate stats for multiple runs of the same file
|
|
516
|
+
existing['total_tests'] += test_file.get('total', 0)
|
|
517
|
+
existing['passed'] += test_file.get('passed', 0)
|
|
518
|
+
existing['failed'] += test_file.get('failed', 0)
|
|
519
|
+
existing['run_count'] = existing.get('run_count', 1) + 1
|
|
520
|
+
# Update to latest timestamp and run_id
|
|
521
|
+
if ts > existing.get('timestamp', ''):
|
|
522
|
+
existing['timestamp'] = ts
|
|
523
|
+
existing['run_id'] = run.get('run_id')
|
|
524
|
+
# Recalculate pass rate based on accumulated totals
|
|
525
|
+
if existing['total_tests'] > 0:
|
|
526
|
+
existing['pass_rate'] = round((existing['passed'] / existing['total_tests']) * 100, 1)
|
|
527
|
+
else:
|
|
528
|
+
file_total = test_file.get('total', 0)
|
|
529
|
+
file_passed = test_file.get('passed', 0)
|
|
530
|
+
file_failed = test_file.get('failed', 0)
|
|
531
|
+
file_pass_rate = round((file_passed / file_total * 100) if file_total > 0 else 0, 1)
|
|
532
|
+
reg['suites'].append({'suite': base_file_name, 'timestamp': ts,
|
|
533
|
+
'run_id': run.get('run_id'),
|
|
534
|
+
'pass_rate': file_pass_rate,
|
|
535
|
+
'total_tests': file_total,
|
|
536
|
+
'passed': file_passed,
|
|
537
|
+
'failed': file_failed,
|
|
538
|
+
'run_count': 1})
|
|
532
539
|
|
|
533
540
|
# Compute regression combined stats
|
|
534
541
|
for reg in regressions.values():
|
|
@@ -572,7 +572,7 @@
|
|
|
572
572
|
const skippedPct = Math.max(0, 100 - failedPct - passedPct);
|
|
573
573
|
|
|
574
574
|
const runBadge = runCount > 1
|
|
575
|
-
? '<span class="run-count-badge" title="Ran ' + runCount + ' times">×' + runCount + '</span>'
|
|
575
|
+
? '<span class="run-count-badge" title="Ran ' + runCount + ' times in this regression">×' + runCount + '</span>'
|
|
576
576
|
: '';
|
|
577
577
|
|
|
578
578
|
const metaText = runCount > 1
|
|
@@ -581,7 +581,7 @@
|
|
|
581
581
|
|
|
582
582
|
// If multiple runs, navigate to history with search; otherwise go to single run
|
|
583
583
|
const clickHandler = runCount > 1
|
|
584
|
-
? 'onclick="navigateToHistoryWithSearch(\'' + s.suite + '\')"'
|
|
584
|
+
? 'onclick="navigateToHistoryWithSearch(\'' + s.suite + '\', \'' + reg.tag + '\')"'
|
|
585
585
|
: 'onclick="goToRun(\'' + s.run_id + '\')"';
|
|
586
586
|
|
|
587
587
|
return '<div class="suite-row" ' + clickHandler + '>' +
|
|
@@ -663,7 +663,7 @@
|
|
|
663
663
|
if (runId) location.href = 'run.html?r=' + encodeURIComponent(runId) + '&p=' + encodeURIComponent(projectName);
|
|
664
664
|
}
|
|
665
665
|
|
|
666
|
-
function navigateToHistoryWithSearch(fileName) {
|
|
666
|
+
function navigateToHistoryWithSearch(fileName, tag) {
|
|
667
667
|
// Find and click the Run History tab button
|
|
668
668
|
const historyBtn = Array.from(document.querySelectorAll('.tab-btn')).find(function(btn) {
|
|
669
669
|
return btn.textContent.trim() === 'Run History';
|
|
@@ -677,7 +677,9 @@
|
|
|
677
677
|
setTimeout(function() {
|
|
678
678
|
const searchInput = document.getElementById('historySearch');
|
|
679
679
|
if (searchInput) {
|
|
680
|
-
|
|
680
|
+
// Combine file name and tag for search
|
|
681
|
+
const searchValue = tag ? fileName + ' ' + tag : fileName;
|
|
682
|
+
searchInput.value = searchValue;
|
|
681
683
|
filterHistory();
|
|
682
684
|
// Scroll to the table
|
|
683
685
|
searchInput.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
@@ -901,7 +903,9 @@
|
|
|
901
903
|
var bg = f.pass_rate >= 95 ? '#276749' : f.pass_rate >= 80 ? '#975a16' : '#9b2c2c';
|
|
902
904
|
var bgLight = f.pass_rate >= 95 ? '#38a169' : f.pass_rate >= 80 ? '#d69e2e' : '#e53e3e';
|
|
903
905
|
const hiddenClass = i >= limit ? ' treemap-cell-hidden' : '';
|
|
904
|
-
|
|
906
|
+
// Strip .py extension for search to match display format
|
|
907
|
+
const searchName = f.file_name.replace(/\.py$/, '');
|
|
908
|
+
const clickAttr = ' onclick="navigateToHistoryWithSearch(\'' + searchName + '\')" style="cursor:pointer;"';
|
|
905
909
|
return '<div class="treemap-cell' + hiddenClass + '" style="width:' + width + 'px;background:' + bgLight + ';" title="' + f.file_name + ': ' + f.pass_rate.toFixed(1) + '% pass rate (' + f.total_runs + ' runs) - Click to view all runs"' + clickAttr + '>' +
|
|
906
910
|
'<div class="treemap-rate">' + f.pass_rate.toFixed(0) + '%</div>' +
|
|
907
911
|
'<div class="treemap-name">' + f.file_name + '</div>' +
|
|
@@ -1033,7 +1037,7 @@
|
|
|
1033
1037
|
'<span style="font-size:13px;color:var(--muted)"><span id="visibleRunCount">' + recentRuns.length + '</span> of ' + recentRuns.length + ' runs across ' + names.length + ' test ' + plural(names.length, 'file') + '</span>' +
|
|
1034
1038
|
'</div>' +
|
|
1035
1039
|
'<div class="search-wrap">' +
|
|
1036
|
-
'<input type="text" id="historySearch" class="search-input" placeholder="Search by test file name..." oninput="filterHistory()" />' +
|
|
1040
|
+
'<input type="text" id="historySearch" class="search-input" placeholder="Search by test file name or tag..." oninput="filterHistory()" />' +
|
|
1037
1041
|
'</div>' +
|
|
1038
1042
|
'<div class="section-body-flush">' +
|
|
1039
1043
|
'<table class="hist-table" id="historyTable">' +
|
|
@@ -1111,9 +1115,13 @@
|
|
|
1111
1115
|
|
|
1112
1116
|
rows.forEach(function(row) {
|
|
1113
1117
|
const fileNameCell = row.querySelector('td:nth-child(3)');
|
|
1118
|
+
const tagCell = row.querySelector('td:nth-child(4)');
|
|
1114
1119
|
if (fileNameCell) {
|
|
1115
1120
|
const fileName = fileNameCell.textContent.toLowerCase();
|
|
1116
|
-
|
|
1121
|
+
const tag = tagCell ? tagCell.textContent.toLowerCase() : '';
|
|
1122
|
+
// Match if search term is in file name OR tag
|
|
1123
|
+
const combinedText = fileName + ' ' + tag;
|
|
1124
|
+
if (combinedText.includes(searchTerm)) {
|
|
1117
1125
|
row.style.display = '';
|
|
1118
1126
|
visibleCount++;
|
|
1119
1127
|
} else {
|
|
@@ -9,7 +9,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
9
9
|
|
|
10
10
|
setup(
|
|
11
11
|
name='test-reporting',
|
|
12
|
-
version='3.7.
|
|
12
|
+
version='3.7.4',
|
|
13
13
|
description='Multi-project test reporting dashboard — collect results locally or push to S3',
|
|
14
14
|
long_description=long_description,
|
|
15
15
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|