How Hypothesis and invariant-driven tests find edge cases in parsers, state transitions, pagination, idempotency and data validation beyond hand-picked examples.
State the invariant first, generate inputs that exercise its boundaries and keep every discovered counterexample as durable regression evidence.
Write the property before the strategy
A property is a rule such as parse-then-serialise preserves meaning, applying an idempotent command twice equals applying it once or a cursor never returns the same item twice.
If the property is vague, a generator only creates more noise. Define valid and invalid domains, invariants and the side effects that must remain bounded before choosing strategies.
Generate realistic boundaries
Useful strategies include empty and very large collections, Unicode, duplicate identifiers, boundary timestamps, concurrent state transitions and malformed external payloads. A generator should produce cases the system could plausibly receive, not random bytes for their own sake.
Keep database and network properties focused. Use pure functions where possible, then combine generated inputs with a small number of integration scenarios for the real boundary behaviour.
Treat counterexamples as evidence
Hypothesis shrinks a failure to a smaller reproducer. Review that case, decide whether it reveals a bug or an invalid assumption and preserve the smallest useful regression test.
Control randomness and deadlines in CI. A property suite that is too slow or flaky will be disabled, which removes the very evidence it was meant to provide.
Evidence to take into review
- Properties describe business or system invariants.
- Generators include realistic boundary and invalid cases.
- Database and network effects remain bounded and observable.
- Shrunk counterexamples become regression evidence.
- Runtime and reproducibility are suitable for CI.
Explore all engineering notes.
Use PRODUCTION-7 to connect this concern with the other dimensions of a trustworthy backend.
View all articles Get the checklist