test-reporting 3.1.1__tar.gz → 3.2.0__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.1.1 → test_reporting-3.2.0}/PKG-INFO +64 -5
- {test_reporting-3.1.1 → test_reporting-3.2.0}/README.md +63 -4
- {test_reporting-3.1.1 → test_reporting-3.2.0}/reporting/cli.py +104 -1
- {test_reporting-3.1.1 → test_reporting-3.2.0}/reporting/config.py +8 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/reporting/publisher.py +2 -6
- test_reporting-3.2.0/reporting/templates/index.html +507 -0
- test_reporting-3.2.0/reporting/templates/project.html +1080 -0
- test_reporting-3.2.0/reporting/templates/run.html +627 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/setup.py +1 -1
- {test_reporting-3.1.1 → test_reporting-3.2.0}/test_reporting.egg-info/PKG-INFO +64 -5
- test_reporting-3.1.1/reporting/templates/index.html +0 -208
- test_reporting-3.1.1/reporting/templates/project.html +0 -641
- test_reporting-3.1.1/reporting/templates/run.html +0 -398
- {test_reporting-3.1.1 → test_reporting-3.2.0}/LICENSE +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/reporting/__init__.py +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/reporting/classifier.py +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/reporting/plugin.py +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/reporting/storage.py +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/setup.cfg +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/test_reporting.egg-info/SOURCES.txt +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/test_reporting.egg-info/dependency_links.txt +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/test_reporting.egg-info/entry_points.txt +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/test_reporting.egg-info/requires.txt +0 -0
- {test_reporting-3.1.1 → test_reporting-3.2.0}/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.
|
|
3
|
+
Version: 3.2.0
|
|
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
|
|
@@ -43,12 +43,22 @@ Multi-project test reporting dashboard. Collects pytest results, publishes to a
|
|
|
43
43
|
## How it works
|
|
44
44
|
|
|
45
45
|
```
|
|
46
|
-
Project A
|
|
47
|
-
Project B
|
|
48
|
-
Project C
|
|
46
|
+
Project A: pytest → local SQLite → publish → ┐
|
|
47
|
+
Project B: pytest → local SQLite → publish → ┼─► Central store (local/S3) ─► Dashboard
|
|
48
|
+
Project C: pytest → local SQLite → publish → ┘
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
**Local (per project):**
|
|
52
|
+
- Tests run and results are saved to a local SQLite database (`test_results.db`)
|
|
53
|
+
- SQLite is a scratchpad for local commands (`stats`, `suites`, `cleanup`)
|
|
54
|
+
- SQLite is **never** pushed to the store
|
|
55
|
+
|
|
56
|
+
**Central store (shared):**
|
|
57
|
+
- `test-report publish` reads from SQLite and publishes JSON files to the store
|
|
58
|
+
- Store contains: run files, artifacts (screenshots/traces), and `data.json`
|
|
59
|
+
- Dashboard reads from the store and aggregates all projects
|
|
60
|
+
|
|
61
|
+
The HTML files are static — deployed once. The `data.json` is rebuilt after every publish.
|
|
52
62
|
|
|
53
63
|
---
|
|
54
64
|
|
|
@@ -224,8 +234,14 @@ auto_publish = false
|
|
|
224
234
|
# Local SQLite — used by stats/suites/cleanup commands
|
|
225
235
|
db_path = test_results.db
|
|
226
236
|
retention_days = 365
|
|
237
|
+
|
|
238
|
+
# Dashboard data retention (affects data.json size and loading speed)
|
|
239
|
+
dashboard_max_days = 90 # Days of history in dashboard (default: 90)
|
|
240
|
+
dashboard_max_runs_per_suite = 50 # Run history per suite (default: 50)
|
|
227
241
|
```
|
|
228
242
|
|
|
243
|
+
**Note:** `retention_days` controls manual cleanup commands, while `dashboard_max_days` and `dashboard_max_runs_per_suite` control what appears in the dashboard automatically. Individual run files remain accessible regardless of these settings.
|
|
244
|
+
|
|
229
245
|
---
|
|
230
246
|
|
|
231
247
|
## CLI commands
|
|
@@ -238,6 +254,49 @@ retention_days = 365
|
|
|
238
254
|
| `test-report stats` | Show stats from latest run (reads local SQLite) |
|
|
239
255
|
| `test-report suites` | Show suite statistics (reads local SQLite) |
|
|
240
256
|
| `test-report cleanup` | Delete old runs from local SQLite |
|
|
257
|
+
| `test-report cleanup-artifacts` | Delete old screenshots and traces (preserves data) |
|
|
258
|
+
|
|
259
|
+
### Cleaning up old data
|
|
260
|
+
|
|
261
|
+
Both cleanup commands use the `retention_days` setting from `reporting.ini` (default: 365 days).
|
|
262
|
+
|
|
263
|
+
#### `test-report cleanup`
|
|
264
|
+
Removes **all test data** from the **local SQLite database only**:
|
|
265
|
+
- Deletes test runs, results, steps, logs, and analytics older than `retention_days`
|
|
266
|
+
- Use this to free up local database space
|
|
267
|
+
- **Does not affect the published store** (JSON files, artifacts, or dashboard data remain intact)
|
|
268
|
+
- Only impacts local commands like `stats` and `suites`
|
|
269
|
+
|
|
270
|
+
#### `test-report cleanup-artifacts`
|
|
271
|
+
Removes **only screenshots and traces** while preserving all test data:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
test-report cleanup-artifacts
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
This will:
|
|
278
|
+
- Remove screenshots (`.png`) and traces (`.zip`) older than `retention_days`
|
|
279
|
+
- Clean **local** directories (`screenshots/`, `traces/`)
|
|
280
|
+
- Clean **published store** artifacts (`store_path/artifacts/` for local stores)
|
|
281
|
+
- Show file count and total size before deletion
|
|
282
|
+
- Ask for confirmation
|
|
283
|
+
- **Preserve all local SQLite data and published JSON files** (logs, error messages, analytics remain intact)
|
|
284
|
+
|
|
285
|
+
**Why use this?** Traces can be 10-50 MB each. This frees disk space on both local machines and the published store while keeping all test data for trend analysis.
|
|
286
|
+
|
|
287
|
+
**What happens in the UI?** The dashboard gracefully handles missing artifacts:
|
|
288
|
+
- Screenshots show: "Screenshot cleaned up" (dashed border placeholder)
|
|
289
|
+
- Trace links show: "Trace file cleaned up" (yellow badge)
|
|
290
|
+
- All test data, logs, and error messages remain visible
|
|
291
|
+
|
|
292
|
+
**Note:** Only failed tests have screenshots and traces saved. Passed tests don't generate these artifacts.
|
|
293
|
+
|
|
294
|
+
**S3 limitation:** Currently only cleans local artifacts. S3 artifact cleanup will be added in a future version.
|
|
295
|
+
|
|
296
|
+
Configure retention in `reporting.ini`:
|
|
297
|
+
```ini
|
|
298
|
+
retention_days = 90 # Keep 90 days of artifacts and data
|
|
299
|
+
```
|
|
241
300
|
|
|
242
301
|
---
|
|
243
302
|
|
|
@@ -7,12 +7,22 @@ Multi-project test reporting dashboard. Collects pytest results, publishes to a
|
|
|
7
7
|
## How it works
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
Project A
|
|
11
|
-
Project B
|
|
12
|
-
Project C
|
|
10
|
+
Project A: pytest → local SQLite → publish → ┐
|
|
11
|
+
Project B: pytest → local SQLite → publish → ┼─► Central store (local/S3) ─► Dashboard
|
|
12
|
+
Project C: pytest → local SQLite → publish → ┘
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
**Local (per project):**
|
|
16
|
+
- Tests run and results are saved to a local SQLite database (`test_results.db`)
|
|
17
|
+
- SQLite is a scratchpad for local commands (`stats`, `suites`, `cleanup`)
|
|
18
|
+
- SQLite is **never** pushed to the store
|
|
19
|
+
|
|
20
|
+
**Central store (shared):**
|
|
21
|
+
- `test-report publish` reads from SQLite and publishes JSON files to the store
|
|
22
|
+
- Store contains: run files, artifacts (screenshots/traces), and `data.json`
|
|
23
|
+
- Dashboard reads from the store and aggregates all projects
|
|
24
|
+
|
|
25
|
+
The HTML files are static — deployed once. The `data.json` is rebuilt after every publish.
|
|
16
26
|
|
|
17
27
|
---
|
|
18
28
|
|
|
@@ -188,8 +198,14 @@ auto_publish = false
|
|
|
188
198
|
# Local SQLite — used by stats/suites/cleanup commands
|
|
189
199
|
db_path = test_results.db
|
|
190
200
|
retention_days = 365
|
|
201
|
+
|
|
202
|
+
# Dashboard data retention (affects data.json size and loading speed)
|
|
203
|
+
dashboard_max_days = 90 # Days of history in dashboard (default: 90)
|
|
204
|
+
dashboard_max_runs_per_suite = 50 # Run history per suite (default: 50)
|
|
191
205
|
```
|
|
192
206
|
|
|
207
|
+
**Note:** `retention_days` controls manual cleanup commands, while `dashboard_max_days` and `dashboard_max_runs_per_suite` control what appears in the dashboard automatically. Individual run files remain accessible regardless of these settings.
|
|
208
|
+
|
|
193
209
|
---
|
|
194
210
|
|
|
195
211
|
## CLI commands
|
|
@@ -202,6 +218,49 @@ retention_days = 365
|
|
|
202
218
|
| `test-report stats` | Show stats from latest run (reads local SQLite) |
|
|
203
219
|
| `test-report suites` | Show suite statistics (reads local SQLite) |
|
|
204
220
|
| `test-report cleanup` | Delete old runs from local SQLite |
|
|
221
|
+
| `test-report cleanup-artifacts` | Delete old screenshots and traces (preserves data) |
|
|
222
|
+
|
|
223
|
+
### Cleaning up old data
|
|
224
|
+
|
|
225
|
+
Both cleanup commands use the `retention_days` setting from `reporting.ini` (default: 365 days).
|
|
226
|
+
|
|
227
|
+
#### `test-report cleanup`
|
|
228
|
+
Removes **all test data** from the **local SQLite database only**:
|
|
229
|
+
- Deletes test runs, results, steps, logs, and analytics older than `retention_days`
|
|
230
|
+
- Use this to free up local database space
|
|
231
|
+
- **Does not affect the published store** (JSON files, artifacts, or dashboard data remain intact)
|
|
232
|
+
- Only impacts local commands like `stats` and `suites`
|
|
233
|
+
|
|
234
|
+
#### `test-report cleanup-artifacts`
|
|
235
|
+
Removes **only screenshots and traces** while preserving all test data:
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
test-report cleanup-artifacts
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
This will:
|
|
242
|
+
- Remove screenshots (`.png`) and traces (`.zip`) older than `retention_days`
|
|
243
|
+
- Clean **local** directories (`screenshots/`, `traces/`)
|
|
244
|
+
- Clean **published store** artifacts (`store_path/artifacts/` for local stores)
|
|
245
|
+
- Show file count and total size before deletion
|
|
246
|
+
- Ask for confirmation
|
|
247
|
+
- **Preserve all local SQLite data and published JSON files** (logs, error messages, analytics remain intact)
|
|
248
|
+
|
|
249
|
+
**Why use this?** Traces can be 10-50 MB each. This frees disk space on both local machines and the published store while keeping all test data for trend analysis.
|
|
250
|
+
|
|
251
|
+
**What happens in the UI?** The dashboard gracefully handles missing artifacts:
|
|
252
|
+
- Screenshots show: "Screenshot cleaned up" (dashed border placeholder)
|
|
253
|
+
- Trace links show: "Trace file cleaned up" (yellow badge)
|
|
254
|
+
- All test data, logs, and error messages remain visible
|
|
255
|
+
|
|
256
|
+
**Note:** Only failed tests have screenshots and traces saved. Passed tests don't generate these artifacts.
|
|
257
|
+
|
|
258
|
+
**S3 limitation:** Currently only cleans local artifacts. S3 artifact cleanup will be added in a future version.
|
|
259
|
+
|
|
260
|
+
Configure retention in `reporting.ini`:
|
|
261
|
+
```ini
|
|
262
|
+
retention_days = 90 # Keep 90 days of artifacts and data
|
|
263
|
+
```
|
|
205
264
|
|
|
206
265
|
---
|
|
207
266
|
|
|
@@ -197,6 +197,28 @@ def show_suites():
|
|
|
197
197
|
print("\n" + "="*80)
|
|
198
198
|
|
|
199
199
|
|
|
200
|
+
def rebuild_dashboard(config_file='reporting.ini'):
|
|
201
|
+
"""Rebuild data.json from existing run files in the store."""
|
|
202
|
+
config = ReportingConfig(config_file=config_file)
|
|
203
|
+
publisher = Publisher(config=config)
|
|
204
|
+
|
|
205
|
+
store_type = config.STORE_TYPE
|
|
206
|
+
store_location = config.S3_BUCKET if store_type == 's3' else str(config.STORE_PATH)
|
|
207
|
+
print(f"[Reporting] Rebuilding dashboard from {store_type}: {store_location}")
|
|
208
|
+
|
|
209
|
+
if store_type == 's3':
|
|
210
|
+
s3 = publisher._get_s3_client()
|
|
211
|
+
publisher._rebuild_data_json_s3(s3, config.S3_BUCKET)
|
|
212
|
+
else:
|
|
213
|
+
store = config.STORE_PATH
|
|
214
|
+
if not store.exists():
|
|
215
|
+
print(f"[Reporting] Store path does not exist: {store}")
|
|
216
|
+
sys.exit(1)
|
|
217
|
+
publisher._rebuild_data_json_local(store)
|
|
218
|
+
|
|
219
|
+
print(f"[Reporting] Dashboard rebuilt successfully!")
|
|
220
|
+
|
|
221
|
+
|
|
200
222
|
def cleanup_old_data():
|
|
201
223
|
"""Clean up old test data based on retention policy."""
|
|
202
224
|
import sqlite3
|
|
@@ -233,15 +255,96 @@ def cleanup_old_data():
|
|
|
233
255
|
print(f"[Reporting] Remaining: {after_count} test runs")
|
|
234
256
|
|
|
235
257
|
|
|
258
|
+
def cleanup_artifacts():
|
|
259
|
+
"""Clean up old screenshots and traces while keeping database records."""
|
|
260
|
+
import os
|
|
261
|
+
from datetime import datetime, timedelta
|
|
262
|
+
|
|
263
|
+
config = ReportingConfig()
|
|
264
|
+
|
|
265
|
+
print(f"\n[Reporting] Artifact Cleanup")
|
|
266
|
+
print("=" * 60)
|
|
267
|
+
print(f"This will delete screenshots and traces older than {config.RETENTION_DAYS} days.")
|
|
268
|
+
print("Database records and logs will be preserved.")
|
|
269
|
+
print(f"\nLocal directories:")
|
|
270
|
+
print(f" Screenshots: {config.SCREENSHOTS_DIR}")
|
|
271
|
+
print(f" Traces: {config.TRACES_DIR}")
|
|
272
|
+
|
|
273
|
+
# Count files to delete
|
|
274
|
+
cutoff_date = datetime.now() - timedelta(days=config.RETENTION_DAYS)
|
|
275
|
+
|
|
276
|
+
screenshots_to_delete = []
|
|
277
|
+
traces_to_delete = []
|
|
278
|
+
|
|
279
|
+
if config.SCREENSHOTS_DIR.exists():
|
|
280
|
+
for file in config.SCREENSHOTS_DIR.glob('*.png'):
|
|
281
|
+
if datetime.fromtimestamp(file.stat().st_mtime) < cutoff_date:
|
|
282
|
+
screenshots_to_delete.append(file)
|
|
283
|
+
|
|
284
|
+
if config.TRACES_DIR.exists():
|
|
285
|
+
for file in config.TRACES_DIR.glob('*.zip'):
|
|
286
|
+
if datetime.fromtimestamp(file.stat().st_mtime) < cutoff_date:
|
|
287
|
+
traces_to_delete.append(file)
|
|
288
|
+
|
|
289
|
+
# Also clean up published artifacts in store
|
|
290
|
+
store_artifacts = []
|
|
291
|
+
if config.STORE_TYPE == 'local' and config.STORE_PATH.exists():
|
|
292
|
+
artifacts_dir = config.STORE_PATH / 'artifacts'
|
|
293
|
+
if artifacts_dir.exists():
|
|
294
|
+
print(f" Store: {artifacts_dir}")
|
|
295
|
+
for file in artifacts_dir.glob('*'):
|
|
296
|
+
if file.suffix in ['.png', '.zip']:
|
|
297
|
+
if datetime.fromtimestamp(file.stat().st_mtime) < cutoff_date:
|
|
298
|
+
store_artifacts.append(file)
|
|
299
|
+
|
|
300
|
+
total_files = len(screenshots_to_delete) + len(traces_to_delete) + len(store_artifacts)
|
|
301
|
+
|
|
302
|
+
if total_files == 0:
|
|
303
|
+
print(f"\n[Reporting] No artifacts older than {config.RETENTION_DAYS} days found.")
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
# Calculate total size
|
|
307
|
+
total_size = sum(f.stat().st_size for f in screenshots_to_delete + traces_to_delete + store_artifacts)
|
|
308
|
+
size_mb = total_size / (1024 * 1024)
|
|
309
|
+
|
|
310
|
+
print(f"\nFound artifacts to delete:")
|
|
311
|
+
print(f" Local screenshots: {len(screenshots_to_delete)}")
|
|
312
|
+
print(f" Local traces: {len(traces_to_delete)}")
|
|
313
|
+
if store_artifacts:
|
|
314
|
+
print(f" Store artifacts: {len(store_artifacts)}")
|
|
315
|
+
print(f" Total size: {size_mb:.2f} MB")
|
|
316
|
+
print(f"\nOlder than: {cutoff_date.strftime('%Y-%m-%d %H:%M:%S')}")
|
|
317
|
+
|
|
318
|
+
response = input(f"\n[Reporting] Delete {total_files} artifact files? (yes/no): ")
|
|
319
|
+
if response.lower() not in ['yes', 'y']:
|
|
320
|
+
print("[Reporting] Cleanup cancelled.")
|
|
321
|
+
return
|
|
322
|
+
|
|
323
|
+
# Delete files
|
|
324
|
+
deleted_count = 0
|
|
325
|
+
for file in screenshots_to_delete + traces_to_delete + store_artifacts:
|
|
326
|
+
try:
|
|
327
|
+
file.unlink()
|
|
328
|
+
deleted_count += 1
|
|
329
|
+
except Exception as e:
|
|
330
|
+
print(f"[Warning] Could not delete {file.name}: {e}")
|
|
331
|
+
|
|
332
|
+
print(f"\n[Reporting] Cleanup complete!")
|
|
333
|
+
print(f"Deleted {deleted_count} artifact files ({size_mb:.2f} MB freed)")
|
|
334
|
+
print(f"Database records preserved for historical analysis.")
|
|
335
|
+
|
|
336
|
+
|
|
236
337
|
def main():
|
|
237
338
|
"""Main CLI entry point."""
|
|
238
339
|
commands = {
|
|
239
340
|
'publish': (publish, 'Push latest test run to the configured store'),
|
|
240
341
|
'deploy': (deploy, 'Deploy static dashboard HTML to the store (run once)'),
|
|
342
|
+
'rebuild': (rebuild_dashboard, 'Rebuild data.json from existing run files'),
|
|
241
343
|
'open': (open_dashboard, 'Open local dashboard in browser'),
|
|
242
344
|
'stats': (show_stats, 'Show quick stats from latest run'),
|
|
243
345
|
'suites': (show_suites, 'Show statistics for all test suites'),
|
|
244
346
|
'cleanup': (cleanup_old_data, 'Clean up old data from local SQLite'),
|
|
347
|
+
'cleanup-artifacts': (cleanup_artifacts, 'Clean up old screenshots and traces'),
|
|
245
348
|
}
|
|
246
349
|
|
|
247
350
|
if len(sys.argv) < 2 or sys.argv[1] not in commands:
|
|
@@ -271,7 +374,7 @@ def main():
|
|
|
271
374
|
command_func = commands[command_name][0]
|
|
272
375
|
|
|
273
376
|
# Only pass config_file to commands that support it
|
|
274
|
-
if command_name in ['publish', 'deploy']:
|
|
377
|
+
if command_name in ['publish', 'deploy', 'rebuild']:
|
|
275
378
|
command_func(config_file=config_file)
|
|
276
379
|
else:
|
|
277
380
|
command_func()
|
|
@@ -33,6 +33,10 @@ class ReportingConfig:
|
|
|
33
33
|
self.LATEST_JSON_PATH = self.REPORTS_DIR / 'latest.json'
|
|
34
34
|
self.DASHBOARD_DIR = Path(s.get('dashboard_dir', 'dashboard'))
|
|
35
35
|
self.RETENTION_DAYS = int(s.get('retention_days', 365))
|
|
36
|
+
|
|
37
|
+
# Dashboard data retention (affects data.json size and performance)
|
|
38
|
+
self.DASHBOARD_MAX_DAYS = int(s.get('dashboard_max_days', 90))
|
|
39
|
+
self.DASHBOARD_MAX_RUNS_PER_SUITE = int(s.get('dashboard_max_runs_per_suite', 50))
|
|
36
40
|
|
|
37
41
|
# Store config
|
|
38
42
|
self.STORE_TYPE = s.get('store_type', 'local') # local | s3
|
|
@@ -62,6 +66,10 @@ class ReportingConfig:
|
|
|
62
66
|
self.DB_PATH = Path('test_results.db')
|
|
63
67
|
self.LATEST_JSON_PATH = self.REPORTS_DIR / 'latest.json'
|
|
64
68
|
self.RETENTION_DAYS = 365
|
|
69
|
+
|
|
70
|
+
# Dashboard data retention
|
|
71
|
+
self.DASHBOARD_MAX_DAYS = 90
|
|
72
|
+
self.DASHBOARD_MAX_RUNS_PER_SUITE = 50
|
|
65
73
|
|
|
66
74
|
self.STORE_TYPE = os.getenv('STORE_TYPE', 'local')
|
|
67
75
|
self.STORE_PATH = Path(os.getenv('STORE_PATH', 'dashboard'))
|
|
@@ -12,10 +12,6 @@ from collections import defaultdict
|
|
|
12
12
|
from .config import ReportingConfig
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
# How many run summaries to keep per suite in data.json
|
|
16
|
-
MAX_RUNS_PER_SUITE = 50
|
|
17
|
-
# How many days of run history to keep in data.json
|
|
18
|
-
MAX_DAYS = 90
|
|
19
15
|
# Minimum runs before flagging a test as flaky
|
|
20
16
|
MIN_RUNS_FOR_FLAKY = 3
|
|
21
17
|
# Minimum avg duration (seconds) to appear in slowest tests
|
|
@@ -514,7 +510,7 @@ class Publisher:
|
|
|
514
510
|
# Trim suite run lists
|
|
515
511
|
for s in suites.values():
|
|
516
512
|
s['runs'] = sorted(s['runs'], key=lambda r: r['timestamp'], reverse=True)
|
|
517
|
-
s['runs'] = s['runs'][:
|
|
513
|
+
s['runs'] = s['runs'][:self.config.DASHBOARD_MAX_RUNS_PER_SUITE]
|
|
518
514
|
|
|
519
515
|
# Sort regressions newest first
|
|
520
516
|
regressions = dict(sorted(regressions.items(), key=lambda x: x[0], reverse=True))
|
|
@@ -772,5 +768,5 @@ class Publisher:
|
|
|
772
768
|
# ------------------------------------------------------------------
|
|
773
769
|
|
|
774
770
|
def _cutoff_date(self) -> str:
|
|
775
|
-
cutoff = datetime.now(timezone.utc) - timedelta(days=
|
|
771
|
+
cutoff = datetime.now(timezone.utc) - timedelta(days=self.config.DASHBOARD_MAX_DAYS)
|
|
776
772
|
return cutoff.isoformat()
|