Implement role-based account journeys with database and browser acceptance suites
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a092fe-13b1-7f12-ac74-7d258af4d79c
This commit is contained in:
parent
75750c0036
commit
1127f852dd
24 changed files with 1554 additions and 148 deletions
39
scripts/run_journey_suites.py
Normal file
39
scripts/run_journey_suites.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Run mapped acceptance tests; report external gaps separately from test results."""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
ROOT=Path(__file__).resolve().parents[1]
|
||||
sys.path[:0]=[str(ROOT/'src'),str(ROOT/'tests')]
|
||||
parser=argparse.ArgumentParser()
|
||||
parser.add_argument('--role',choices=['user','tenant_admin','platform_admin'])
|
||||
parser.add_argument('--report',type=Path)
|
||||
parser.add_argument('--require-complete',action='store_true',help='Fail while any journey has an implementation or external acceptance gap')
|
||||
args=parser.parse_args()
|
||||
rows=json.loads((ROOT/'tests/journey-coverage.json').read_text())['journeys']
|
||||
expected={f'U{i:02}' for i in range(1,14)}|{f'T{i:02}' for i in range(1,9)}|{f'P{i:02}' for i in range(1,9)}
|
||||
if len(rows)!=29 or {r['id'] for r in rows}!=expected:
|
||||
raise SystemExit('Journey coverage must contain each of the 29 journey IDs exactly once')
|
||||
rows=[r for r in rows if not args.role or r['role']==args.role]
|
||||
for row in rows:
|
||||
if not row['tests'] or row['implementation'] not in {'implemented','partial','external-blocked'}:
|
||||
raise SystemExit('Invalid coverage entry: '+row['id'])
|
||||
if row['implementation']!='implemented' and not row['remaining']:
|
||||
raise SystemExit('Unexplained journey gap: '+row['id'])
|
||||
selectors=sorted({name for row in rows for name in row['tests']})
|
||||
suite=unittest.TestSuite(unittest.defaultTestLoader.loadTestsFromName(name) for name in selectors)
|
||||
result=unittest.TextTestRunner(verbosity=2).run(suite)
|
||||
failed={test.id() for test,_ in result.failures+result.errors}
|
||||
skipped={test.id() for test,_ in result.skipped}
|
||||
report={'tests_run':result.testsRun,'test_success':result.wasSuccessful(),'skipped':len(skipped),
|
||||
'journeys':[dict(row,automated_result='failed' if failed.intersection(row['tests']) else 'skipped' if skipped.intersection(row['tests']) else 'passed') for row in rows],
|
||||
'complete':result.wasSuccessful() and not skipped and all(r['implementation']=='implemented' for r in rows)}
|
||||
if args.report:
|
||||
args.report.parent.mkdir(parents=True,exist_ok=True)
|
||||
args.report.write_text(json.dumps(report,indent=2)+'\n')
|
||||
print(json.dumps({'tests_run':report['tests_run'],'test_success':report['test_success'],'complete':report['complete'],
|
||||
'unresolved_journeys':[r['id'] for r in rows if r['implementation']!='implemented']}))
|
||||
raise SystemExit(0 if result.wasSuccessful() and not skipped and (not args.require_complete or report['complete']) else 1)
|
||||
Loading…
Add table
Add a link
Reference in a new issue