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.
Files changed (21) hide show
  1. {test_reporting-3.7.2 → test_reporting-3.7.3}/PKG-INFO +1 -1
  2. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/publisher.py +19 -8
  3. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/templates/project.html +31 -46
  4. {test_reporting-3.7.2 → test_reporting-3.7.3}/setup.py +1 -1
  5. {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/PKG-INFO +1 -1
  6. {test_reporting-3.7.2 → test_reporting-3.7.3}/LICENSE +0 -0
  7. {test_reporting-3.7.2 → test_reporting-3.7.3}/README.md +0 -0
  8. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/__init__.py +0 -0
  9. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/classifier.py +0 -0
  10. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/cli.py +0 -0
  11. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/config.py +0 -0
  12. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/plugin.py +0 -0
  13. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/storage.py +0 -0
  14. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/templates/index.html +0 -0
  15. {test_reporting-3.7.2 → test_reporting-3.7.3}/reporting/templates/run.html +0 -0
  16. {test_reporting-3.7.2 → test_reporting-3.7.3}/setup.cfg +0 -0
  17. {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/SOURCES.txt +0 -0
  18. {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/dependency_links.txt +0 -0
  19. {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/entry_points.txt +0 -0
  20. {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/requires.txt +0 -0
  21. {test_reporting-3.7.2 → test_reporting-3.7.3}/test_reporting.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: test-reporting
3
- Version: 3.7.2
3
+ Version: 3.7.3
4
4
  Summary: Multi-project test reporting dashboard — collect results locally or push to S3
5
5
  Home-page: https://github.com/amahdy77/test-reporting.git
6
6
  Author: Ashfaqur Mahdy
@@ -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'] == suite), None)
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.update({'timestamp': ts, 'run_id': run.get('run_id'),
510
- 'pass_rate': run.get('pass_rate', 0),
511
- 'total_tests': run.get('total_tests', 0),
512
- 'passed': run.get('passed', 0),
513
- 'failed': run.get('failed', 0)})
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': suite, 'timestamp': ts,
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
- // Group suites by name to detect duplicates
559
- // Strip [TAG] suffix to group reruns with original runs
560
- const suiteGroups = {};
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
- // Sort suite names alphabetically
571
- const sortedSuiteNames = Object.keys(suiteGroups).sort();
572
-
573
- const fileRows = sortedSuiteNames.map(function(suiteName) {
574
- const runs = suiteGroups[suiteName];
575
- const runCount = runs.length;
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 skippedPct = totalTests > 0 ? (totalSkipped / totalTests * 100) : 0;
599
- const passedPct = Math.max(0, 100 - failedPct - skippedPct);
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 · avg across ' + runCount + ' runs'
579
+ ? totalTests + ' tests total · ' + totalFailed + ' failed · accumulated across ' + runCount + ' runs'
607
580
  : totalTests + ' tests · ' + totalFailed + ' failed';
608
581
 
609
- return '<div class="suite-row" onclick="goToRun(\'' + firstRunId + '\')">' +
610
- '<div class="suite-name"><span>' + suiteName + '</span>' + runBadge + '</div>' +
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 + ' | Skipped: ' + totalSkipped + (runCount > 1 ? ' (accumulated)' : '') + '">' +
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(avgPassRate) + '">' + avgPassRate.toFixed(0) + '%</div>' +
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 = Object.keys(suiteGroups).length;
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
- // Switch to Run History tab
690
- switchTab('history');
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.2',
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",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: test-reporting
3
- Version: 3.7.2
3
+ Version: 3.7.3
4
4
  Summary: Multi-project test reporting dashboard — collect results locally or push to S3
5
5
  Home-page: https://github.com/amahdy77/test-reporting.git
6
6
  Author: Ashfaqur Mahdy
File without changes
File without changes
File without changes