feat: add YAML policy-test harness#54
Merged
Merged
Conversation
This was referenced May 1, 2026
9a75e02 to
b45e8e1
Compare
4b57f83 to
d2c89be
Compare
vahid-ahmadi
added a commit
that referenced
this pull request
May 29, 2026
Property-transaction tax now dispatches by region: - Scotland → LBTT (LBTT (Scotland) Act 2013) - Wales → LTT (LTT and Anti-avoidance of Devolved Taxes (Wales) Act 2017) - elsewhere → SDLT (Finance Act 2003 s.55, unchanged) 2025/26 residential bands per: - SSI 2015/126 (Scotland) - WSI 2018/128 (Wales) Adds: - `lbtt` and `ltt` parameter blocks in `parameters/2025_26.yaml` - `Parameters.lbtt`/`Parameters.ltt` Rust fields and Python wrapper exposure - `calculate_property_transaction_tax` dispatch function in `src/variables/wealth_taxes.rs` - New `baseline_property_transaction_tax` and `reform_property_transaction_tax` per-household microdata columns - Six Rust unit tests covering LBTT/LTT/SDLT dispatch and nil-band edges - Six YAML policy-test cases (`tests/policy/property_transaction_tax.yaml`) Stacked on #54 (YAML test harness). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `policyengine_uk_compiled.yaml_tests` — a runner that mirrors the
format used by `policyengine_uk/tests/policy/` so cases can be ported one
at a time.
The runner accepts either single-person flat input
(`input: { employment_income: 50000 }`) or full-situation input
(`input: { people: ..., benunits: ..., households: ... }`), supports
absolute and relative error margins, and writes outputs against the Rust
microdata column names (`baseline_income_tax`, `baseline_universal_credit`,
`baseline_net_income`, etc.).
This PR ships:
- The runner module with CLI: `python -m policyengine_uk_compiled.yaml_tests tests/policy`
- 11 hand-written YAML cases under `tests/policy/` covering income tax,
employee NI, and Child Benefit (single + multi-person)
- A pytest module that auto-discovers and parametrizes the YAML cases
- 21 unit tests for the runner itself (input mapping, tolerance, parsing)
- pyyaml added to the package's runtime dependencies
Stacked on #53 (parity harness) which is itself stacked on #52
(Simulation.from_situation). Future PRs port more of the 196 Python YAML
tests that already exist in `policyengine_uk/tests/policy/`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d2c89be to
3e78c00
Compare
Contributor
Author
|
Rebased onto This was previously stacked on #53/#52 and imported
|
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #47 in part — ships the runner and a starter set of YAML cases. Stacked on #53 (parity harness) → #52 (
from_situation).YAML cases mirror the format used by
policyengine_uk/tests/policy/, so the existing 196 Python YAML tests can be ported into this repo one at a time without touching the runner.Run them:
…or pick them up automatically as parametrized pytest cases:
What's included
Runner (
interfaces/python/policyengine_uk_compiled/yaml_tests.py):employment_income: 50000→ auto-builds a one-person household) and full situation (people:/benunits:/households:matchingfrom_situation).persons,benunits, orhouseholdsmicrodata and summed across rows.False ≈ True).python -m policyengine_uk_compiled.yaml_tests <path>(file or dir).Initial YAML cases (
tests/policy/, 11 cases):income_tax.yaml: zero income, below PA, basic-rate band, basic↔higher span, fully-tapered PA at £150knational_insurance.yaml: below PT, main band, partial-higher tier, well above UELchild_benefit.yaml: two children with full CB, no children = £0Pytest integration (
test_yaml_policy_cases.py): auto-discovers every YAML case and runs each as a parametrized test, skipping cleanly when the Rust binary isn't built.Runner unit tests (21 cases in
test_yaml_test_runner.py): cover input routing, tolerance edge cases (incl. boolean comparison), YAML parsing, and validation errors.pyyamladded to runtime dependencies inpyproject.tomlso the runner is usable from the installed package.Verified locally
cargo test: 135 passingpytest interfaces/python/tests: 69 passing (37 from feat: add Simulation.from_situation for situation-JSON input #52/feat: add Python ↔ Rust parity harness #53 + 21 runner unit tests + 11 YAML cases)python -m policyengine_uk_compiled.yaml_tests tests/policy: 11/11 passingStacking
vahid/yaml-test-harness←vahid/parity-harness(#53) ←vahid/from-situation(#52). Once #52 and #53 merge, GitHub will auto-rebase this onto main.Test plan
python -m policyengine_uk_compiled.yaml_tests tests/policyprints 11 passestests/policy/is automatically picked up by pytest without code changes🤖 Generated with Claude Code