Property-Based Testing
debt(d8/e5/b3/t5)
Closest to 'silent in production until users hit it' (d8). The absence of property-based tests is not flagged by Eris or PHPUnit themselves — detection_hints.automated is 'no'. Edge cases surface in production; slightly better than d9 because code review can sometimes flag pure functions lacking robust testing.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix says to adopt Eris/fast-check and write generative tests for pure functions — this is more than a one-line swap; it requires adding a dependency, writing property definitions, and refactoring test suites within the testing component.
Closest to 'localised tax' (b3). applies_to covers web/cli but the choice lives in the test suite — it doesn't shape production architecture. Adds maintenance load to the testing component only.
Closest to 'notable trap most devs eventually learn' (t5). The misconception is that property-based testing replaces unit tests; common_mistakes show developers write properties that are just unit tests, skip shrinking, or only test happy paths — documented gotchas that practitioners learn through experience.
Also Known As
TL;DR
Explanation
Instead of writing test cases with specific inputs (unit tests), property-based testing defines properties that must hold for all valid inputs: 'reversing a list twice gives the original list', 'sorting is idempotent', 'encode then decode returns the original'. The framework generates random inputs and shrinks failing cases to the minimal reproducing example. Haskell's QuickCheck popularised the approach; PHP has Eris.
Common Misconception
Why It Matters
Common Mistakes
- Writing properties that are too specific — 'the output equals 42 for input 6 and 7' is just a unit test.
- Not using shrinking — a good property test framework minimises the failing input to the simplest reproducing case.
- Properties that only test the happy path — include properties that verify error conditions too.
- Giving up when a property is hard to define — the difficulty of defining properties reveals unclear specifications.
Code Examples
// Unit test — only tests one specific case:
public function testReverseArray(): void {
$this->assertEquals([3, 2, 1], array_reverse([1, 2, 3]));
// What about empty arrays? Single elements? Large arrays? Unicode strings?
}
// Property test — tests the invariant for random inputs (Eris):
public function testReverseTwiceIsIdentity(): void {
$this->forAll(
Generator\seq(Generator\int())
)->then(function(array $list) {
$this->assertEquals(
$list,
array_reverse(array_reverse($list)) // Property: reverse twice = identity
);
});
}