What a test buys you

Know what a test is actually buying, so you write the ones that pay and skip the ones that do not.

01of 16
≈ 11Min read
5Parts

Four things, and only one of them is "catching bugs"

The first is the big one. A codebase with tests can be changed by somebody who was not there when it was written; a codebase without them can only be added to, carefully, by the person who remembers.

A test gives youWhich matters when
Permission to change codeevery refactor, every upgrade, every rewrite of a function you did not write
A description of the behavioursomebody reads the test to find out what the thing is supposed to do
A bug that cannot come backthe regression test written the day it was fixed
Design pressurecode that is hard to test is usually hard to use

And what they cost

Every test is code: it is written, read, maintained, and it breaks when the thing it tests changes. A test that breaks every time you move a function without changing its behaviour is a cost with no benefit — that is the single most common failure, and the What to test lesson is about avoiding it.

So the question for each test is not "could this catch something" — everything could. It is "will this still be worth its maintenance in a year".

The shapes

The old advice was a pyramid: very many unit tests, fewer integration, a handful of end-to-end. The newer advice is a trophy: fewer pure units, a thick middle of integration tests, a few end-to-end. The trophy is right more often, because most real bugs live in the seams — the wiring, the query, the serialisation — and a unit test with everything mocked proves that your mocks agree with each other.

KindCoversRuns inFails because
Unitone function or module, alonemillisecondsthat unit is wrong
Integrationseveral parts together — code + database, code + HTTPtens of ms to secondsthe seam between them is wrong
End to enda real browser against a real deploymentsecondsanything, anywhere

What not to test

  • The framework. React renders. The ORM builds SQL. That is their test suite, not yours.
  • Getters, setters, and constants. A test that says expect(config.port).toBe(3000) fails only when somebody deliberately changed it.
  • Private functions, directly. Test them through the thing that uses them, or make them public because they deserve to be.
  • Exact HTML or CSS. A snapshot of markup breaks on every design change and catches nothing.
  • Anything you would delete rather than fix when it goes red. That is the test telling you it was never worth writing.

What this course does

You write the test runner in the next lesson — describe, it and expect, in about forty lines — and then use it for the rest of the course. Every real runner is that plus twenty years of features, and knowing what is underneath makes the real ones far less mysterious when they misbehave.

Practice