Tests that generate their own inputs
You write the rule that must always hold; the runner spends a thousand attempts trying to break it and hands you the smallest input that did.
An example-based test says parse("2026-01-31") returns a particular date. A property says that for every valid date, format(parse(x)) equals x. The framework then generates hundreds of inputs, including the empty string, a leap day, a year with five digits and whatever else it can think of, and when one fails it shrinks the input until it has the smallest case that still breaks.
The properties that come up over and over: a round trip that must return the original, an operation that is idempotent, two orderings that must agree, a fast implementation that must match a slow obvious one, and an invariant on the output: sorted, deduplicated, sums to the input total. Parsers, serialisers, sorters, permission checks and money arithmetic all repay this.
It is not a replacement for examples. Properties are excellent at finding inputs you never imagined and useless at pinning down a specific business rule, which is exactly what an example test is for. Use properties for the boundaries and examples for the intent, and always convert a shrunk failure into a permanent example test so it can never come back.
You should now be able to
- Express an invariant as a property
- Read a shrunk counterexample and turn it into a normal test
Loading…