test-reporting 3.7.2__tar.gz → 3.7.3__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.2 → test_reporting-3.7.3}/PKG-INFO +1 -1
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/publisher.py +19 -8
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/templates/project.html +31 -46
- {test_reporting-3.7.2 → test_reporting-3.7.3}/setup.py +1 -1
- {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/PKG-INFO +1 -1
- {test_reporting-3.7.2 → test_reporting-3.7.3}/LICENSE +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/README.md +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/__init__.py +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/classifier.py +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/cli.py +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/config.py +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/plugin.py +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/storage.py +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/templates/index.html +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/templates/run.html +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/setup.cfg +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/SOURCES.txt +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/dependency_links.txt +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/entry_points.txt +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/requires.txt +0 -0
- {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/top_level.txt +0 -0
|
@@ -495,6 +495,10 @@ class Publisher:
|
|
|
495
495
|
})
|
|
496
496
|
|
|
497
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
|
+
|
|
498
502
|
if tag not in regressions:
|
|
499
503
|
regressions[tag] = {'tag': tag, 'date': tag[:10], 'suites': [],
|
|
500
504
|
'total_tests': 0, 'passed': 0, 'failed': 0, 'pass_rate': 0,
|
|
@@ -503,21 +507,28 @@ class Publisher:
|
|
|
503
507
|
# Track the latest timestamp for this regression
|
|
504
508
|
if ts > reg.get('timestamp', ''):
|
|
505
509
|
reg['timestamp'] = ts
|
|
506
|
-
existing = next((s for s in reg['suites'] if s['suite'] ==
|
|
510
|
+
existing = next((s for s in reg['suites'] if s['suite'] == base_suite), None)
|
|
507
511
|
if existing:
|
|
512
|
+
# Accumulate stats for multiple runs of the same test
|
|
513
|
+
existing['total_tests'] += run.get('total_tests', 0)
|
|
514
|
+
existing['passed'] += run.get('passed', 0)
|
|
515
|
+
existing['failed'] += run.get('failed', 0)
|
|
516
|
+
existing['run_count'] = existing.get('run_count', 1) + 1
|
|
517
|
+
# Update to latest timestamp and run_id
|
|
508
518
|
if ts > existing.get('timestamp', ''):
|
|
509
|
-
existing
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
519
|
+
existing['timestamp'] = ts
|
|
520
|
+
existing['run_id'] = run.get('run_id')
|
|
521
|
+
# Recalculate pass rate based on accumulated totals
|
|
522
|
+
if existing['total_tests'] > 0:
|
|
523
|
+
existing['pass_rate'] = round((existing['passed'] / existing['total_tests']) * 100, 1)
|
|
514
524
|
else:
|
|
515
|
-
reg['suites'].append({'suite':
|
|
525
|
+
reg['suites'].append({'suite': base_suite, 'timestamp': ts,
|
|
516
526
|
'run_id': run.get('run_id'),
|
|
517
527
|
'pass_rate': run.get('pass_rate', 0),
|
|
518
528
|
'total_tests': run.get('total_tests', 0),
|
|
519
529
|
'passed': run.get('passed', 0),
|
|
520
|
-
'failed': run.get('failed', 0)
|
|
530
|
+
'failed': run.get('failed', 0),
|
|
531
|
+
'run_count': 1})
|
|
521
532
|
|
|
522
533
|
# Compute regression combined stats
|
|
523
534
|
for reg in regressions.values():
|
|
@@ -555,75 +555,53 @@
|
|
|
555
555
|
const rc2 = rateColor(reg.pass_rate);
|
|
556
556
|
const total = lastReg ? lastReg.total_tests || 1 : 1;
|
|
557
557
|
|
|
558
|
-
//
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
(reg.suites || []).forEach(function(s) {
|
|
562
|
-
// Remove [TAG] suffix like [RERUN], [RETRY], etc.
|
|
563
|
-
const baseName = s.suite.replace(/\s*\[.*?\]\s*$/, '');
|
|
564
|
-
if (!suiteGroups[baseName]) {
|
|
565
|
-
suiteGroups[baseName] = [];
|
|
566
|
-
}
|
|
567
|
-
suiteGroups[baseName].push(s);
|
|
558
|
+
// Sort suites alphabetically
|
|
559
|
+
const sortedSuites = (reg.suites || []).slice().sort(function(a, b) {
|
|
560
|
+
return a.suite.localeCompare(b.suite);
|
|
568
561
|
});
|
|
569
562
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
const
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
// Calculate accumulated averages
|
|
578
|
-
let totalTests = 0;
|
|
579
|
-
let totalFailed = 0;
|
|
580
|
-
let totalSkipped = 0;
|
|
581
|
-
let totalPassed = 0;
|
|
582
|
-
let avgPassRate = 0;
|
|
583
|
-
|
|
584
|
-
runs.forEach(function(run) {
|
|
585
|
-
totalTests += run.total_tests;
|
|
586
|
-
totalFailed += run.failed;
|
|
587
|
-
totalSkipped += (run.skipped || 0);
|
|
588
|
-
totalPassed += (run.total_tests - run.failed - (run.skipped || 0));
|
|
589
|
-
avgPassRate += run.pass_rate;
|
|
590
|
-
});
|
|
591
|
-
|
|
592
|
-
avgPassRate = avgPassRate / runCount;
|
|
593
|
-
|
|
594
|
-
// Use first run's ID for navigation
|
|
595
|
-
const firstRunId = runs[0].run_id;
|
|
563
|
+
const fileRows = sortedSuites.map(function(s) {
|
|
564
|
+
const runCount = s.run_count || 1;
|
|
565
|
+
const totalTests = s.total_tests;
|
|
566
|
+
const totalFailed = s.failed;
|
|
567
|
+
const totalPassed = s.passed;
|
|
568
|
+
const passRate = s.pass_rate;
|
|
596
569
|
|
|
597
570
|
const failedPct = totalTests > 0 ? (totalFailed / totalTests * 100) : 0;
|
|
598
|
-
const
|
|
599
|
-
const
|
|
571
|
+
const passedPct = totalTests > 0 ? (totalPassed / totalTests * 100) : 0;
|
|
572
|
+
const skippedPct = Math.max(0, 100 - failedPct - passedPct);
|
|
600
573
|
|
|
601
574
|
const runBadge = runCount > 1
|
|
602
575
|
? '<span class="run-count-badge" title="Ran ' + runCount + ' times">×' + runCount + '</span>'
|
|
603
576
|
: '';
|
|
604
577
|
|
|
605
578
|
const metaText = runCount > 1
|
|
606
|
-
? totalTests + ' tests total · ' + totalFailed + ' failed ·
|
|
579
|
+
? totalTests + ' tests total · ' + totalFailed + ' failed · accumulated across ' + runCount + ' runs'
|
|
607
580
|
: totalTests + ' tests · ' + totalFailed + ' failed';
|
|
608
581
|
|
|
609
|
-
|
|
610
|
-
|
|
582
|
+
// If multiple runs, navigate to history with search; otherwise go to single run
|
|
583
|
+
const clickHandler = runCount > 1
|
|
584
|
+
? 'onclick="navigateToHistoryWithSearch(\'' + s.suite + '\')"'
|
|
585
|
+
: 'onclick="goToRun(\'' + s.run_id + '\')"';
|
|
586
|
+
|
|
587
|
+
return '<div class="suite-row" ' + clickHandler + '>' +
|
|
588
|
+
'<div class="suite-name"><span>' + s.suite + '</span>' + runBadge + '</div>' +
|
|
611
589
|
'<div class="suite-meta">' + metaText + '</div>' +
|
|
612
590
|
'<div class="suite-bar">' +
|
|
613
|
-
'<div class="stacked-bar" title="Passed: ' + totalPassed + ' | Failed: ' + totalFailed +
|
|
591
|
+
'<div class="stacked-bar" title="Passed: ' + totalPassed + ' | Failed: ' + totalFailed + (runCount > 1 ? ' (accumulated across ' + runCount + ' runs)' : '') + '">' +
|
|
614
592
|
'<div class="stacked-green" style="width:' + passedPct.toFixed(1) + '%"></div>' +
|
|
615
593
|
'<div class="stacked-red" style="width:' + failedPct.toFixed(1) + '%"></div>' +
|
|
616
594
|
'<div class="stacked-grey" style="width:' + skippedPct.toFixed(1) + '%"></div>' +
|
|
617
595
|
'</div>' +
|
|
618
596
|
'</div>' +
|
|
619
|
-
'<div class="suite-rate ' + rateColor(
|
|
597
|
+
'<div class="suite-rate ' + rateColor(passRate) + '">' + passRate.toFixed(0) + '%</div>' +
|
|
620
598
|
'</div>';
|
|
621
599
|
}).join('');
|
|
622
600
|
|
|
623
601
|
const isOpen = i === 0;
|
|
624
602
|
const regDateTime = reg.timestamp ? fmtDateTime(reg.timestamp) : '';
|
|
625
603
|
const regTitle = regDateTime ? reg.tag + ' · ' + regDateTime : reg.tag;
|
|
626
|
-
const uniqueSuiteCount =
|
|
604
|
+
const uniqueSuiteCount = sortedSuites.length;
|
|
627
605
|
return '<div class="regression">' +
|
|
628
606
|
'<div class="reg-head" onclick="toggleReg(this)">' +
|
|
629
607
|
'<div>' +
|
|
@@ -686,8 +664,15 @@
|
|
|
686
664
|
}
|
|
687
665
|
|
|
688
666
|
function navigateToHistoryWithSearch(fileName) {
|
|
689
|
-
//
|
|
690
|
-
|
|
667
|
+
// Find and click the Run History tab button
|
|
668
|
+
const historyBtn = Array.from(document.querySelectorAll('.tab-btn')).find(function(btn) {
|
|
669
|
+
return btn.textContent.trim() === 'Run History';
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
if (historyBtn) {
|
|
673
|
+
switchTab('history', historyBtn);
|
|
674
|
+
}
|
|
675
|
+
|
|
691
676
|
// Wait for tab to render, then set search value and trigger filter
|
|
692
677
|
setTimeout(function() {
|
|
693
678
|
const searchInput = document.getElementById('historySearch');
|
|
@@ -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.3',
|
|
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
|