First-party only — a session id and where you arrived from, so we can tell which pages are worth writing more of. No advertising, no third-party trackers, nothing that follows you off this site.
Rank before writing, the six rules, and the break-it-on-purpose step that makes tests real.
tests/backfill.md · 2.2 KB
# Backfilling tests
For code that already exists and is not covered. The trap is chasing
coverage percentage, which produces tests that run without testing.
## Order of work
Do not start at the top of the file. Start where a bug would be most
expensive.
```
This code has no tests: [file or module]
Do not write tests yet. First, rank what needs one, most valuable first.
For each, say:
- what it does
- what would break in production if it were wrong
- how hard it is to test as currently written
Then tell me which three are worth testing and which are not worth the
maintenance cost. Be willing to say a function does not need a test.
```
Then work down the list, a few at a time.
## Writing them
```
Write tests for [the top three].
Rules:
1. One behaviour per test. A test asserting three things fails ambiguously.
2. Name the behaviour, not the mechanism.
Bad: TestParseQuery_Case3
Good: TestParseQuery_RejectsNonRFC3339Since
3. Never compute the expected value using the same logic as the
implementation. If the code rounds, assert a literal you worked out
by hand.
4. Cover for each: the empty case, the single-element case, at least one
error path asserting the error TYPE not just that one occurred, and any
boundary the code mentions.
5. For each test, name a specific mutation to the implementation it would
catch. If you cannot, do not write it.
6. Do not change the implementation. If it cannot be tested without
changing it, say so and stop — that is a separate decision.
```
## The step that makes it real
```
For each test you wrote: break the implementation in the way that test is
meant to catch. Run it. Show me it failing. Then restore.
Any test that still passes with the implementation broken is decorative.
Say which, and either fix it or delete it.
```
This is the difference between a test suite and a set of functions that run.
It takes minutes and it is not optional.
## Untestable code
When a function cannot be tested without changing it — hardcoded clock,
direct global access, network call inline, constructor doing I/O — that is
a finding, not an obstacle.
Report it and let a human decide. Silently refactoring production code
during a test-writing task is exactly the scope creep this pack exists to
prevent.The rest of Review & Repair is written the same way. $29 once, yours permanently, 14-day refund.