Books / Law as Code in Practice: German Housing Benefit (Wohngeld) / Chapter 5
Part II · Chapter 5
How a Scenario Is Written

Contents of Law as Code in Practice: German Housing Benefit (Wohngeld)
By the end you can read one scenario, say where its expected numbers come from, and explain what its success establishes and what it does not.
Lawyer: whether the expectation follows the published text or example.
Analyst: which edge or example the scenario exercises.
Developer: facts, question, expectation and the declared world.
1. The question
How do we know the model’s €485 is right? Not because the model says so. We know because someone outside the model — the federal ministry — published the same family and the same answer, and a scenario holds the model to it.
2. Where the expectation comes from
The BMWSB publishes worked examples of the Wohngeld calculation: ten for 2023 and eleven for 2025. Each gives a household, its rent and income, the intermediate values and the monthly amount. The model’s scenarios take their expected numbers from these PDFs, not from a run of the engine. A scenario that was written by copying the engine’s output would test nothing.
Rechenbeispiel 7 of 2025 — the Vogts’ example — gives Y = €1,710.00, M = €777.80, the ceiling plus climate component €800.40, and Wohngeld €485. The ministry writes the income in one line: €2,240 − €102.50 = €2,137.50; minus 20 % = €1,710.00. The rent: €580 + €197.80 = €777.80.
Before each scenario stands a comment saying which PDF, which example, and which assumptions the case had to make where the PDF is silent. For example 7: the PDF does not give the children’s ages; the case enters 10 and 6, which do not affect the amount.
3. Facts, question, expectation
A scenario has three parts. Here is the shape of the one for example 7, shortened:
test "BMWSB 2025 Rechenbeispiel 7: Ehepaar mit zwei Kindern, Weimar (Mietenstufe III) — 485 EUR" {
given {
context { legal_time @2025-01-01; timezone "Europe/Berlin"; … }
assert "wohnort": wohnort(haushalt, "Thüringen", "Weimar, Stadt") { origin case_input; }
assert "entgelt": vereinbartes_entgelt(mietverhaeltnis, 580.00 EUR) { origin case_input; }
assert "ehefrau-lohn": arbeitslohn_in_geld(ehefrau, 26880.00 EUR) { origin case_input; }
assert "ehefrau-abzug16": abzugsmerkmale_16(ehefrau, NEIN, JA, JA) { origin case_input; }
assert "behoerde-21-nr3": not missbraeuchliche_inanspruchnahme(haushalt) { origin adjudicated; }
…
}
evaluate truth(monatliches_gesamteinkommen(haushalt, 1710.00 EUR));
expect truth_status == TRUE_ONLY;
evaluate truth(zu_beruecksichtigende_miete(haushalt, 777.80 EUR));
expect truth_status == TRUE_ONLY;
evaluate truth(hoechstbetrag_mit_klimakomponente(haushalt, 800.40 EUR));
expect truth_status == TRUE_ONLY;
evaluate truth(wohngeld_monatlich(haushalt, 485 EUR));
expect truth_status == TRUE_ONLY;
evaluate truth(wohngeldanspruch(haushalt, 485 EUR));
expect truth_status == TRUE_ONLY;
expect judgment_requests(0);
}
givenholds the facts, each with its origin. Most arecase_input— what the household declared. One isadjudicated: the authority’s own assessment under § 21 Nr. 3 (Chapter 6).evaluateasks a question of the model. Here, five questions: the intermediate values the PDF prints, the amount and the claim.expectstates the answer the source requires.TRUE_ONLYmeans established. The expected income, rent, ceiling and amount come from the PDF. The expected claim does not: the ministry’s examples expressly establish no claim. The scenario adds the authority’s assessment under § 21 Nr. 3 as a decided fact (adjudicated), and only with it does the claim follow;judgment_requests(0)then says nothing is left for the authority.
The scenario checks the intermediate values, not only the last line. A model that reached €485 by two errors that cancel out would fail at M or Y.
4. The declared world
A scenario runs against a declared set of canons — its world: here the Wohngeld canon and the two it reads, the ordinance with the rent levels and the income definitions of the EStG. The world is part of the test. A scenario that passed against a different set of rules would prove something else.
5. What the scenarios cover today
| Source | Examples | In the model | Outside the model |
|---|---|---|---|
| BMWSB worked examples 2023 | 10 | 9 tenant examples | 1 — Lastenzuschuss |
| BMWSB worked examples 2025 | 11 | 9 tenant examples | 2 — Lastenzuschuss |
18 of 21 published examples are executed; the three outside the model are owner-occupier subsidies, which this model does not cover (Chapter 8). Next to the published examples stand scenarios for the change of edition, missing and conflicting facts, exclusions and the authority’s judgment — the suites Chapters 1, 6, 7 and 8 draw on.
On 12 October 2026, with law 0.1.12, the 2023 suite passed 9 of 9 scenarios and the 2025 suite 10 of 10 — one more scenario than published tenant examples, because example 1 is run twice, with two assumptions about the taxable share of the pension that the PDF does not state; the edition suite 6 of 6; the suite of missing and conflicting facts 7 of 7; the suite of exclusions and judgments 16 of 16.
6. A case package is a scenario you can ask
The scenarios test the canon. The case package familie-weimar — the one this book asks — holds the same family as a set of standing files: four cases (Familie2025, Familie20241231, FamilieOhneWuerdigung, AlleinGrundsicherung) and six saved questions. Its check script asks eleven case–question pairs and verifies, for each:
- the status of the answer and any request for the authority’s judgment;
- that the decisive rule applied, with its anchor in the edition of the date;
- which row of Anlage 2 the formula used, and that row’s anchor to the BGBl issue;
- that a replay of the saved answer gives the same bytes.
7. What a passing scenario establishes — and what it does not
A passing scenario establishes that the model, with these facts and this world, gives the answer the published example gives — including its intermediate values. It does not establish that the published example is right, that the model covers every case the Act covers, or that a particular office applies the Act the same way. Agreement with the ministry’s examples is strong evidence about the formula; it is not a legal opinion.
8. Where Catala stands on this
Catala has a mature testing workflow: clerk test discovers scope tests and command-output tests, with backend checks available (Catala book, ch. 3.3). This is shared ground: both approaches preserve examples and expectations. Arxo adds built-in query statuses — established, not established, contradictory, waiting for an authority — so a scenario can expect “not established” or “the Wohngeldbehörde must assess” as precisely as it expects €485.
9. Run the scenarios
law test <canon> --file tests/bmwsb-2025.lawtest
law test <canon> --file tests/redaktionen.lawtest
Each line reports every scenario as passed or failed, and a total.
Exercise
- Why must the expected €485 come from the ministry’s PDF and not from the model?
- The scenario for example 7 also expects M = €777.80 and the ceiling €800.40. What kind of error would these extra expectations catch that the final €485 alone would not?
- Three of the 21 published examples are not executed. Is that a failure of the scenarios?