50 lines
3.1 KiB
Python
50 lines
3.1 KiB
Python
import copy,importlib.util,unittest,tempfile,json
|
|
from pathlib import Path
|
|
|
|
spec=importlib.util.spec_from_file_location('successor',Path(__file__).with_name('reconcile.py'))
|
|
successor=importlib.util.module_from_spec(spec);spec.loader.exec_module(successor)
|
|
|
|
class FrontendSuccessorMembership(unittest.TestCase):
|
|
def setUp(self):
|
|
cases=[{'fullName':f'original-{i}','status':'passed'} for i in range(934)]
|
|
cases[1]['fullName']=cases[0]['fullName']
|
|
self.baseline={'testResults':[{'name':'/repo/job-tracker-ui/src/cv-builder-deep-link.test.tsx','assertionResults':cases}]}
|
|
self.actual=copy.deepcopy(self.baseline)
|
|
self.actual['testResults'][0]['assertionResults'].append({'fullName':successor.ADDED_CASE,'status':'passed'})
|
|
def test_accepts_exactly_one_declared_addition_without_mutating_reference(self):
|
|
before=copy.deepcopy(self.baseline)
|
|
self.assertEqual(len(successor.frontend_cases(self.actual,self.baseline,0)),935)
|
|
self.assertEqual(self.baseline,before)
|
|
def test_missing_original_or_changed_duplicate_multiplicity_is_rejected(self):
|
|
self.actual['testResults'][0]['assertionResults'][1]['fullName']='unexpected-replacement'
|
|
with self.assertRaises(ValueError): successor.frontend_cases(self.actual,self.baseline,0)
|
|
def test_added_case_cannot_be_skipped_or_retried(self):
|
|
self.actual['testResults'][0]['assertionResults'][-1]['status']='pending'
|
|
with self.assertRaises(ValueError): successor.frontend_cases(self.actual,self.baseline,0)
|
|
def test_nonzero_process_cannot_be_promoted(self):
|
|
with self.assertRaises(ValueError): successor.frontend_cases(self.actual,self.baseline,1)
|
|
|
|
class RepresentativeEvidence(unittest.TestCase):
|
|
def setUp(self):
|
|
self.temporary=tempfile.TemporaryDirectory();self.addCleanup(self.temporary.cleanup)
|
|
self.root=Path(self.temporary.name)
|
|
cases=[{'fixture':name,'pass':True,'failures':[]} for name in ['long-skills-minimal-en','long-skills-technical-nb']]
|
|
self.report={'total':2,'passed':2,'fixtures':cases}
|
|
self.proof={'status':'PASS','oracleExitCode':0,'cases':cases}
|
|
def test_exact_membership_and_matching_successful_cases(self):
|
|
successor.validate_representative(self.proof,self.report)
|
|
def test_empty_or_unrelated_report_is_rejected(self):
|
|
for report in [{'total':0,'passed':0,'fixtures':[]},dict(self.report,fixtures=[self.report['fixtures'][0]]*2)]:
|
|
with self.assertRaises(ValueError): successor.validate_representative(self.proof,report)
|
|
def test_failed_or_changed_case_is_rejected(self):
|
|
report=copy.deepcopy(self.report);report['fixtures'][0]['failures']=['clipping']
|
|
with self.assertRaises(ValueError): successor.validate_representative(self.proof,report)
|
|
def test_hash_drift_is_rejected(self):
|
|
file=self.root/'export.pdf';file.write_bytes(b'original')
|
|
inputs={str(file):successor.hashlib.sha256(file.read_bytes()).hexdigest()}
|
|
successor.require_unchanged(inputs)
|
|
file.write_bytes(b'changed')
|
|
with self.assertRaises(ValueError): successor.require_unchanged(inputs)
|
|
|
|
if __name__=='__main__':unittest.main()
|