Regression tests for decision rules that change
When a rule changes, the question is which rows changed with it. The entry rule gains a staff condition below, and the engine's comparison of the two versions finds exactly one row of sixteen where they differ, which is the row the regression suite must add and the rows it must keep.
Version one is (member OR invited) AND NOT banned; version two is (member OR invited OR staff) AND NOT banned. Adding an input doubles the table, from eight rows to sixteen, and the equivalence check reports the two versions as not equivalent with the witness member = FALSE, invited = FALSE, banned = FALSE, staff = TRUE: a staff member who is neither a member nor invited, now admitted. It is the only differing row. On every other row, including the banned staff member, the versions agree.
That one row is the new test, with its expected result taken from the change request (“staff may enter”). The rows that did not change are the regression suite proper: they encode everything the change was not supposed to touch, and the engine's comparison is the proof that it did not. A change that had produced two differing rows, say by also admitting banned staff, would have shown up as a second witness.
Keeping the previous version's counterexamples as tests, as the counterexamples page recommends, means the suite accumulates exactly the rows that once mattered. Inputs are matched across revisions by identity in the engine, so renaming member does not break the comparison, and a test file carries the digest of the logic it was written against.
Example
v1 := (member OR invited) AND NOT banned · outputv2 := (member OR invited OR staff) AND NOT banned · output
Exact checks
Truth table (16 rows)
| # | member | invited | banned | staff | v1 | v2 |
|---|---|---|---|---|---|---|
| 0 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE |
| 1 | FALSE | FALSE | FALSE | TRUE | FALSE | TRUE |
| 2 | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE |
| 3 | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE |
| 4 | FALSE | TRUE | FALSE | FALSE | TRUE | TRUE |
| 5 | FALSE | TRUE | FALSE | TRUE | TRUE | TRUE |
| 6 | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE |
| 7 | FALSE | TRUE | TRUE | TRUE | FALSE | FALSE |
| 8 | TRUE | FALSE | FALSE | FALSE | TRUE | TRUE |
| 9 | TRUE | FALSE | FALSE | TRUE | TRUE | TRUE |
| 10 | TRUE | FALSE | TRUE | FALSE | FALSE | FALSE |
| 11 | TRUE | FALSE | TRUE | TRUE | FALSE | FALSE |
| 12 | TRUE | TRUE | FALSE | FALSE | TRUE | TRUE |
| 13 | TRUE | TRUE | FALSE | TRUE | TRUE | TRUE |
| 14 | TRUE | TRUE | TRUE | FALSE | FALSE | FALSE |
| 15 | TRUE | TRUE | TRUE | TRUE | FALSE | FALSE |
Plain-language reading
Beginnerv1 is true exactly when both of the following hold:
1. at least one of member or invited is true (both may be true)
2. banned is false
In every other case, v1 is false.
About the operators:
- AND is true only when all of its parts are true.
- OR is inclusive: it is true when at least one part is true, including when several are.
- NOT reverses a value: true becomes false and false becomes true.
Intermediatev1 is true exactly when both of the following hold:
1. at least one of member or invited is true (both may be true)
2. banned is false
In every other case, v1 is false.
Advancedv1 is true exactly when both of the following hold [conjunction ∧]:
1. at least one of member or invited is true (both may be true) [inclusive disjunction ∨]
2. banned is false [negation ¬]
In every other case, v1 is false.
Formal notation: (member ∨ invited) ∧ ¬banned
Logic diagram
The common slip
Re-generating the whole expected-results column from the new rule after a change. The suite then agrees with the new rule by construction, including on any row the change broke; the differing rows should be reviewed against the change request, not regenerated.
Questions
Why compare versions rather than just test the new one?
Because the comparison lists the rows whose outcome changed, which is a complete statement of the change's effect. Tests of the new rule alone cannot tell an intended change from an accidental one.
What if the change adds an input?
The table doubles and the old rows are matched by the inputs they share. The comparison still finds the differing rows, as the one-row result above shows, and the new input's independence pair becomes a new test.
Related
See also
- Turning a counterexample into a regression test
- Deriving test cases from a truth table without testing every row
- Regression test: meaning and examples
- Logical equivalence checker: two expressions, exact verdict, counterexample
- Entry rule: (member OR invited) AND NOT banned, checked every way
- Lesson 9: Counterexamples (intermediate, 12 min)
- A review checklist for decision rules (for analysts and reviewers)
Testing and rules
Generated from the Tangibool engine, semantics tangibool-semantics/1, engine 1.0.0, build . Every table, map, simplification and verdict on these pages was computed by the Tangibool engine when the site was built, and every claim was re-checked by the same exact checker the app uses. Limits are stated where they apply. © 2026 Foreranger LTD.