Goal: find edge cases by checking properties across many inputs.
Use for:
- logic with broad input ranges or many edge cases
- parsers, serializers, and data transformations
- complementing example-based tests
Workflow:
- Identify an invariant that must always hold.
- Define generators for the relevant input space.
- Let the framework run many randomized cases.
- Let it shrink failures to a minimal counterexample.
- Add the counterexample as a regression test.
- Refine generators to cover meaningful edges.
Useful properties:
- round-trip: decode(encode(x)) == x
- invariant: output always satisfies a rule
- equivalence: two implementations agree
- idempotence: f(f(x)) == f(x)
Rules:
- assert properties, not specific outputs
- constrain generators to valid, meaningful inputs
- pin discovered counterexamples as fixed tests
- use seeds so failures reproduce