skip to content

What is test-first development, and how does it differ from writing tests after the code?

level: juniorimportance: must knowfreq 78%

answer

  1. The order of writing is the whole idea
  2. Nothing on screen to copy from
  3. Specification versus confirmation
  4. Cases inherit the code's own branches
  5. Ambiguity blocks the assertion line

basics

~20 s

Test-first means writing an executable test for behaviour that does not exist yet, then writing code to satisfy it. Test-after writes tests against finished code, so the cases are shaped by what the code already does.

solid answer

~50 s

In test-first work the test is written before the production code it exercises, so at the moment you write it there is nothing to read except the requirement. That forces you to state the behaviour in your own words: what the operation is called, what you hand it, what comes back, and what counts as correct. In test-after work the code already exists, so its structure, its names and its branches are in front of you while you choose cases — the natural result is a set of tests that confirm what the code does rather than describe what it should do. Both orders can end with a green suite and similar coverage numbers. The difference is what you learned on the way: test-first turns a vague requirement into a concrete example early, while test-after mostly documents a decision already made.

go deeper

for a junior

Be ready to state the ordering plainly and give one honest difference: with no code on screen you must decide the call yourself, so the test describes intended behaviour instead of confirming existing behaviour.

for a middle

Explain the mechanism rather than the slogan. Say why cases chosen against finished code drift toward its branches and vocabulary, and why an interface with no reachable seam is discovered late in that order.

for a senior

Show judgement about when each order applies: new behaviour and reproduced defects go test-first, characterisation of unspecified existing code cannot. Be honest that the published evidence on outcomes is mixed rather than quoting a number.

for a principal

Own the framing you would give a team: test-first is a design and requirements feedback loop, not a coverage policy, so measuring adoption by coverage percentage will drive exactly the behaviour you did not want.

## The claim in one line Test-first development is the practice of writing an executable test for a behaviour **before** writing the production code that provides it. The whole content of the idea is in the ordering, and everything interesting follows from one fact: at the instant you write the test, there is no implementation to consult. ## What you have when the code does not exist When you sit down to write the first test for a new behaviour, the only inputs you have are the requirement, whatever examples came with it, and your own understanding. You cannot copy a method name off the screen, you cannot read a branch to see which inputs matter, and you cannot look up what the operation returns. You have to *decide* all of that and write it down as a call you would like to make. That is why the exercise is a design activity as much as a verification one. The test becomes the first client of an interface that does not exist, and everything a client cares about — the name, the arguments, the shape of the result, how a failure is reported — must be settled before a line of the implementation is typed. The result is a description of the behaviour written from the outside, by someone who wants to use it. ## What test-after gives you instead In test-after work the sequence is reversed: the code is written, then cases are chosen for it. The cases are not chosen in a vacuum. The implementation is on the screen, so the tests tend to walk its branches, adopt its vocabulary, and stop where its structure stops. This is efficient — it is often the fastest route to a covered line — but it produces **confirmation**: evidence that the code does what it does. A requirement the code never implemented is unlikely to grow a test, because nothing on the screen suggests it. There are also structural consequences. If the code was written without a caller in mind, it may have no seam a test can reach: state hidden behind a construction that also opens a connection, a result reported only through a side effect, or a wide constructor that must be satisfied before anything can be exercised. In test-after work the usual response is to reach for heavier machinery to get at the code. In test-first work that awkwardness shows up before the code exists, when it is still free to change, because you feel it while writing the call. ## The honest comparison It is worth being precise about what test-first does and does not claim. - **It is not a coverage technique.** A disciplined test-after suite can reach the same lines. Coverage is a poor way to tell the two apart. - **It is not proof of correctness.** A test written first is still only as good as the examples you thought of. - **It does change what you learn, and when.** Ambiguity surfaces as an assertion you cannot write: if you do not know what the operation should return for a given input, you cannot finish the line, and you go and find out before the code encodes a guess. - **The empirical evidence is genuinely contested.** Studies of test-first versus test-after report mixed effects on defect density and effort, and reviews disagree about how much of any benefit comes from the ordering rather than from writing small tests at all. Claiming a specific measured improvement is a weak answer; describing the mechanism honestly is a strong one. ## Where the order is not negotiable Some tests can only be written after the code, and that is not a failure of discipline. Characterisation tests for existing code with no specification are written against what the system already does, precisely because the current behaviour *is* the thing being pinned down. The reverse case is a good illustration of the rule: a reported bug is ideal test-first material, because the report supplies a concrete example and the failing test proves you have reproduced it before anything is repaired. ## What an interviewer is listening for Weak answers say test-first "gives you better coverage" or "makes sure the code works". Both are available from test-after. Strong answers name the asymmetry: the test written first is a **specification** produced by the first user of an interface, and the test written afterwards is largely a **confirmation** produced by its author reading their own code. The practical payoff is that requirement gaps, unusable interfaces and unreachable state are discovered at the cheapest possible moment — before there is any code to rework.

  • If both orders can end with the same tests and the same code, why does the order matter at all?
    Because the two orders produce different knowledge at different times. Writing first forces the requirement into a concrete example while changing it is free, and it exposes an unusable interface before any code depends on it. Writing afterwards mostly records decisions already taken, and cases tend to follow the branches that exist rather than the behaviour that was asked for.
  • Is there any legitimate place for tests written after the code?
    Yes. Characterisation tests over existing code with no specification must be written afterwards, because the point is to pin down what the system currently does before changing it. The distinction is intent: those tests document present behaviour, they do not claim to have specified it.
  • Where does a reported defect fit into a test-first habit?
    A defect report already contains a concrete example, so it converts directly into a test written before the repair. That test proves the fault is reproduced rather than guessed at, and it stays in the suite afterwards as evidence the same fault does not return.

Writing the test first is like writing the label on a parcel before you pack it: you must decide what is inside and where it goes, instead of describing whatever ended up in the box.

saying these in an interview costs you the question

  • Says test-first is mainly a way to raise coverage numbers
  • Claims tests written after the code are identical in value
  • Thinks the whole suite must be written before any code
  • Describes the first test as a plan document, not executable
  • Asserts a precise measured defect reduction as settled fact

context