Property-based testing
Property-based testing — popularised by QuickCheck (Haskell, 1999) and now available across most languages (Hypothesis for Python, fast-check for TypeScript, ScalaCheck) — generates many random inputs and asserts that a property of the function holds across all of them. Instead of 'assert add(2, 3) == 5', the property is 'for all integers a, b: add(a, b) == add(b, a)'.
Property-based tests find bugs that example-based tests miss because they search the input space algorithmically — including edge cases the developer didn't think to write. Classic finds: a sort function that broke on lists containing one element; a JSON parser that crashed on unicode in keys; a date library that mishandled the day before a daylight-savings transition. The art is finding the right properties: round-tripping (parse(serialize(x)) == x), invariants (the output length equals the input length), mathematical relationships (commutativity, associativity, idempotence). Property tests pair well with unit tests — they catch different bug classes — and shine on data-transformation, parser, and algorithmic code.