Skip to content
Latchkey

What Is Property-Based Testing?

Property-based testing asserts that a general property holds across many automatically generated inputs, rather than checking a few hand-picked cases.

Most tests use examples you chose by hand. Property-based testing instead states a rule that should always be true, then lets the framework generate hundreds of random inputs to try to break it. When it finds a failing input, it shrinks it to the smallest example, often revealing edge cases you would never have written by hand.

Properties instead of examples

Rather than asserting that reverse([1,2,3]) equals [3,2,1], you assert a property: reversing a list twice yields the original list. The framework then throws many random lists at that property, exploring far more of the input space than example tests do.

Generation and shrinking

The framework generates inputs from a description of the data, runs the property, and on failure shrinks the input to the minimal case that still fails. Shrinking is what makes the technique practical: instead of a giant random failure, you get a tiny, debuggable counterexample.

A quick example

A round-trip property checks that encoding then decoding any string returns the original, across many generated strings.

A round-trip property
forAll(strings, (s) => {
  expect(decode(encode(s))).toBe(s);
});

What it is good at

  • Finding boundary and edge cases humans miss.
  • Testing serialization, parsing, and round-trips.
  • Verifying mathematical or invariant-style properties.
  • Complementing example-based tests, not replacing them.

Property-based testing in CI

Because it runs each property over many inputs, property-based testing is heavier than a single example test, and a generated input can occasionally expose genuine nondeterminism. Pinning the random seed keeps runs reproducible, and running these suites on fast runners absorbs the extra input volume.

Key takeaways

  • Property-based testing checks invariants over many generated inputs.
  • Shrinking reduces a failure to a minimal, debuggable example.
  • It excels at edge cases and round-trip properties; pin seeds in CI.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →