P30 · Testing & Mocking
pytest, fixtures, mocking & property-based testing
Testing as an engineering discipline: pytest idioms, fixtures and parametrisation, mocking without over-mocking, and property-based tests - built by hand so the tools stop being magic.
A suite that asserts nothing can report one hundred per cent coverage. That one fact is the best short argument for treating testing as an engineering discipline rather than a chore with a percentage attached: the number everyone tracks measures which lines ran, never whether anybody checked what they did. This pillar is about the judgement the number cannot supply.
It teaches pytest by rebuilding it. pytest.raises is an ordinary context
manager, so you write one; a fixture is a generator with yield splitting setup
from teardown, driven in try/finally so cleanup survives a failure;
@parametrize is the three-layer decorator factory from P29 expanding one test
over a table. After that the framework is code you could have written rather
than incantation you invoke. Test doubles get the same treatment and the harder
lesson attached: you build a recording mock and the patch swap-and-restore by
hand, then learn to double only the boundaries you do not own — network, clock,
payment provider — and to run your own logic for real, because a suite that
mocks its own code tests the mocks.
The last track inverts the activity entirely. Instead of choosing examples, you
state an invariant that should hold for every input — reversing a list twice
returns it unchanged, a parser and its serialiser round-trip — and let a
generator hunt hundreds of candidates for a counterexample, then shrink that
counterexample to the minimal failing case. You build the shrinker, which is
what makes the technique intelligible rather than mysterious. The pillar's
worked example is the make quality pytest gate this repository runs, which is
the one you are standing inside.