test_traceability.mojo (6296B)
1 import std.os 2 from std.collections import List 3 from std.os.path import dirname, isfile 4 from std.pathlib import Path, _dir_of_current_file 5 from safe_tempdir import SafeTempDir 6 from std.testing import TestSuite, assert_equal, assert_true 7 from json import loads 8 9 from fixture_validator import ( 10 FixtureValidationIssue, 11 validate_requirement_traceability, 12 validate_step_states, 13 ) 14 15 16 def _write(path: Path, text: String) raises: 17 _ = std.os.makedirs(dirname(path.__fspath__()), exist_ok=True) 18 path.write_text(text) 19 assert_true( 20 isfile(path.__fspath__()), 21 "expected a regular file at " + path.__fspath__(), 22 ) 23 24 25 def _make_corpus(base: Path, mutation: String) raises: 26 var manifest = '{"cases":[{"case_id":"T001"}]}' 27 var steps = '{"steps":[{"id":"S001","dependencies":[]}]}' 28 var registry = ( 29 '{"requirements":[{"id":"HYF-TEST-001",' 30 '"verification_method":"fixture-schema and traceability checks",' 31 '"implementation_steps":["S001"],"fixture_ids":["T001"]}]}' 32 ) 33 if mutation == "duplicate_requirement": 34 registry = registry.replace( 35 "]}]}", 36 ( 37 ']},{"id":"HYF-TEST-001","verification_method":"x",' 38 '"implementation_steps":["S001"],"fixture_ids":["T001"]}]}' 39 ), 40 ) 41 elif mutation == "unknown_step": 42 registry = registry.replace('["S001"]', '["S999"]') 43 elif mutation == "dangling_fixture": 44 registry = registry.replace('["T001"]', '["MISSING"]') 45 elif mutation == "uncovered_requirement": 46 registry = registry.replace( 47 '"implementation_steps":["S001"]', '"implementation_steps":[]' 48 ) 49 elif mutation == "missing_verification_method": 50 registry = registry.replace( 51 '"fixture-schema and traceability checks"', '""' 52 ) 53 elif mutation == "dangling_dependency": 54 steps = '{"steps":[{"id":"S001","dependencies":["S404"]}]}' 55 elif mutation == "duplicate_step": 56 steps = ( 57 '{"steps":[{"id":"S001","dependencies":[]},' 58 '{"id":"S001","dependencies":[]}]}' 59 ) 60 _write(base / "manifest.json", manifest) 61 _write(base / "steps.json", steps) 62 _write(base / "registry.json", registry) 63 64 65 def _validate(base: Path) raises -> List[FixtureValidationIssue]: 66 return validate_requirement_traceability( 67 (base / "registry.json").__fspath__(), 68 (base / "manifest.json").__fspath__(), 69 (base / "steps.json").__fspath__(), 70 ) 71 72 73 def test_requirement_traceability_accepts_registry_and_rejects_dangling() raises: 74 var root = _dir_of_current_file() 75 assert_equal( 76 len( 77 validate_requirement_traceability( 78 ( 79 root / "requirements" / "hyf_v1_jev.requirements.json" 80 ).__fspath__(), 81 ( 82 root / "fixtures" / "hyf_v1_jev" / "manifest.json" 83 ).__fspath__(), 84 (root / "requirements" / "hyf_v1_jev.steps.json").__fspath__(), 85 ) 86 ), 87 0, 88 ) 89 90 var mutations = List[String]() 91 mutations.append("duplicate_requirement") 92 mutations.append("unknown_step") 93 mutations.append("dangling_fixture") 94 mutations.append("uncovered_requirement") 95 mutations.append("missing_verification_method") 96 mutations.append("dangling_dependency") 97 mutations.append("duplicate_step") 98 for mutation in mutations: 99 with SafeTempDir() as temp_dir: 100 var base = Path(temp_dir) 101 _make_corpus(base, mutation) 102 assert_true( 103 len(_validate(base)) > 0, 104 "traceability accepted corruption: " + mutation, 105 ) 106 107 108 def test_step_state_contract_is_valid_and_rejects_corruption() raises: 109 var path = ( 110 _dir_of_current_file() / "requirements" / "hyf_v1_jev.step_states.json" 111 ) 112 assert_equal(len(validate_step_states(path.__fspath__())), 0) 113 114 with SafeTempDir() as temp_dir: 115 var base = Path(temp_dir) 116 _write( 117 base / "states.json", 118 ( 119 '{"states":["PASSED","PASSED","NOT_RUN","NOT_APPLICABLE"],' 120 '"passed_requires_executed_evidence":true,"rules":["x"]}' 121 ), 122 ) 123 assert_true( 124 len(validate_step_states((base / "states.json").__fspath__())) > 0 125 ) 126 with SafeTempDir() as temp_dir: 127 var base = Path(temp_dir) 128 _write( 129 base / "states.json", 130 ( 131 '{"states":["PASSED","NOT_RUN","NOT_APPLICABLE"],' 132 '"passed_requires_executed_evidence":false,"rules":["x"]}' 133 ), 134 ) 135 assert_true( 136 len(validate_step_states((base / "states.json").__fspath__())) > 0 137 ) 138 139 140 def main() raises: 141 TestSuite.discover_tests[__functions_in_module()]().run() 142 143 144 from fixture_validator import validate_requirement_traceability as _vrt 145 146 147 def test_requirement_and_fixture_closure_audit() raises: 148 var root = _dir_of_current_file() 149 var registry = loads( 150 (root / "requirements" / "hyf_v1_jev.requirements.json").read_text() 151 ) 152 var steps = loads( 153 (root / "requirements" / "hyf_v1_jev.steps.json").read_text() 154 ) 155 var step_ids = List[String]() 156 for step in steps["steps"].array_items(): 157 step_ids.append(step["id"].string_value()) 158 assert_equal(len(step_ids), 138) 159 var covered = 0 160 for requirement in registry["requirements"].array_items(): 161 assert_true(len(requirement["implementation_steps"].array_items()) > 0) 162 covered += 1 163 assert_equal(covered, 85) 164 165 var manifest = loads( 166 (root / "fixtures" / "hyf_v1_jev" / "manifest.json").read_text() 167 ) 168 var planned = 0 169 for entry in manifest["cases"].array_items(): 170 var doc = loads( 171 ( 172 root / "fixtures" / "hyf_v1_jev" / entry["path"].string_value() 173 ).read_text() 174 ) 175 var found_step = False 176 for known in step_ids: 177 if known == entry["required_from_step"].string_value(): 178 found_step = True 179 assert_true(found_step) 180 assert_equal(doc["implementation_status"].string_value(), "planned") 181 planned += 1 182 assert_equal(planned, 116)