A couple notes on software testing:
1. A test suite should be a legible description of the system under test.
Each test should clearly describe one piece of behaviour with as few independent factors and implementation details as possible. Of course, factors and details like those are the hallmarks of interesting corner cases, so this level of clarity can be difficult to implement in practice without sacrificing rigour. Still, it's astonishing how often I come across tests that say nothing explicit about the system they're meant to describe, beyond "when you run it with these inputs, you'll get those outputs."
This is the worst type of test suite: a baroque aggregation of arbitrary scenarios. Suites like this are millstones around your neck. A change in any part of the system can break hundreds of tests, and it's often unclear whether a broken test indicates a bug or simply that the system has changed.
A perfect test suite uses randomized property tests. Each test generates a thousand random inputs and validates that a particular property holds true under any possible circumstance. It's highly decoupled from implementation details and one step away from a formal proof of correctness. Not every domain is amenable to property testing, but it reaches corner cases without sacrificing clarity, so it's worth the trouble when possible.
On the other hand, I have a lot of respect for snapshot testing, even though it's about as far from the property-testing ideal as you can get. Snapshot tests (a.k.a. golden files) embrace the need to update test expectations all the time by providing automated tools for reviewing and updating changes to expectations. Perhaps this sort of test struggles to legibly describe a system, but it's great at describing the impact of a change to the system, and I like that. It feels like a pragmatic compromise for situations where you can't write perfect tests.
… continue reading Two observations about testing