forked from ChelseaKR/permit-bearings
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_harness.py
More file actions
132 lines (115 loc) · 4.1 KB
/
Copy pathtest_harness.py
File metadata and controls
132 lines (115 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import json
from datetime import date
from pathlib import Path
import pytest
from permit_pathways.harness import verify_rules
from permit_pathways.harness.runner import load_golden
from permit_pathways.screening import load_rules
DATA = Path(__file__).parent.parent / "data"
RULES = DATA / "rules"
GOLDEN = DATA / "golden" / "example.json"
AS_OF = date(2026, 7, 30)
def test_report_accepts_the_bounded_davis_record_with_dated_evidence():
report = verify_rules(RULES, GOLDEN, today=AS_OF)
# The Davis record verifies only the City's published processing
# categories. Its notes preserve HCD's unresolved ordinance-status warning
# instead of treating the handout as operative law or an eligibility test.
assert report.unverified == []
assert report.stale == []
assert len(report.verified) == 19
assert report.golden_failed == []
assert report.automated_checks_pass
def test_changed_source_flips_dependent_rules_to_stale():
# Rehearse a legislative amendment touching Gov. Code § 66321
# (ADU size/setback/height standards): both dependent rules must go
# stale; unrelated rules stay verified.
report = verify_rules(RULES, GOLDEN, today=AS_OF, changed_sources=["ca-gov-66321"])
assert set(report.stale) == {
"adu-protected-minimum",
"adu-height-standards",
"adu-size-allowances",
"adu-multifamily-66323",
"adu-multifamily-proposed-66323",
}
assert "sb9-two-unit-ministerial" in report.verified
assert not report.automated_checks_pass
def test_verification_goes_stale_after_max_age():
report = verify_rules(RULES, GOLDEN, today=date(2027, 7, 27))
assert report.verified == []
assert len(report.stale) == 19
def test_jurisdiction_layers_ride_on_the_statewide_base():
report = verify_rules(RULES, GOLDEN, today=AS_OF)
assert {
"davis-new-detached-adu-local-layer",
"woodland-new-detached-adu-local-layer",
} <= set(report.golden_passed)
def test_golden_rule_dependencies_are_explicit_and_cover_expected_rules():
rules = load_rules(RULES, today=AS_OF)
cases = load_golden(GOLDEN, rules)
assert len(cases) == 29
assert all(
case.rule_dependency_ids == sorted(case.rule_dependency_ids) for case in cases
)
assert all(case.rule_dependency_ids for case in cases)
assert all(
set(case.expected_rule_ids) <= set(case.rule_dependency_ids) for case in cases
)
assert {
"sb9-adu-interaction",
"sb9-two-unit-ministerial",
} == set(
next(
case.rule_dependency_ids
for case in cases
if case.case_id == "sb9-duplex-tenant-occupied"
)
)
@pytest.mark.parametrize(
("mutate", "message"),
[
(
lambda record: record.pop("rule_dependency_ids"),
"exactly the Golden case fields",
),
(
lambda record: record.update(
{"rule_dependency_ids": list(reversed(record["rule_dependency_ids"]))}
),
"sorted unique list",
),
(
lambda record: record.update(
{
"rule_dependency_ids": [
*record["rule_dependency_ids"],
"unknown-rule",
]
}
),
"unknown rule IDs",
),
(
lambda record: record.update(
{
"rule_dependency_ids": [
rule_id
for rule_id in record["rule_dependency_ids"]
if rule_id != record["expected_rule_ids"][0]
]
}
),
"must include expected rule IDs",
),
],
)
def test_golden_loader_rejects_unbound_rule_dependencies(
tmp_path,
mutate,
message,
):
payload = json.loads(GOLDEN.read_text(encoding="utf-8"))
mutate(payload[0])
path = tmp_path / "golden.json"
path.write_text(json.dumps(payload), encoding="utf-8")
with pytest.raises(ValueError, match=message):
load_golden(path, load_rules(RULES, today=AS_OF))