Skip to content
Mastering Claude

Home / Everyday moves

Everyday moves10 minApplication

Building and refactoring with tests first

Ask for the tests before the implementation, then run the test runner to confirm they genuinely fail: red proves the test can fail, green proves the implementation satisfies it. Claude reproduces the style of the tests already in the repository, and the refactor then moves one concern at a time.

Claude examines the test files already present in a repository to reproduce their style, their test framework, and their assertion conventions, rather than imposing a convention foreign to the project. The gesture consists of requesting these tests before writing the implementation they are meant to verify, then running the test runner to confirm they genuinely fail.

Confirm red before asking for green

This sequence, known in software engineering as red, green, refactor, does not depend on any Claude Code specific feature, it remains valid with any tool. Red proves that the test can fail, green proves that the implementation satisfies it, and jumping straight to green without having seen red leaves open whether the test would have passed even without any implementation at all.

The following example fabricates its own data to stay valid for any reader. A test expects a calculerRemise function to apply a ten percent discount, before this function even exists.

function testCalculerRemise() {
  const resultat = calculerRemise(200);
  console.assert(resultat === 180, "attendu 180, obtenu " + resultat);
}

testCalculerRemise();
// ReferenceError: calculerRemise is not defined, le rouge attendu

Once this red is observed, the minimal implementation is enough to turn it green.

function calculerRemise(prix) {
  return prix * 0.9;
}

testCalculerRemise();
// aucune sortie : l'assertion est vraie, le test est au vert

Refactoring one concern at a time

The test runner stays active throughout the refactor that follows, and each change touches a single concern, one name renamed, one function extracted, never several at once in the same turn. This discipline isolates the regression: if the test runner fails after a change, the cause lies in that precise change, not in a stack of piled up modifications that would need to be untangled. Asking Claude to identify uncovered edge cases before considering a set of tests complete also helps, particularly for empty, negative, or out of range inputs that the initial implementation often ignores.

This requirement echoes the regression test that closes a bug fix.

Testing the tests with mutants

A passing test proves the code passes, not that the test detects a fault. A mutant is a fault injected on purpose into a copy of the code: if the suite still passes, it is blind to that fault. The script creates a function and its test, then a mutant that changes 0.9 to 0.8.

cat > remise.js << 'EOF'
function calculerRemise(prix) { return prix * 0.9; }
module.exports = { calculerRemise };
EOF
cat > test.js << 'EOF'
const { calculerRemise } = require('./remise.js');
if (calculerRemise(200) !== 180) { console.log('ECHEC'); process.exit(1); }
console.log('OK');
EOF
node test.js
cp remise.js remise.orig.js
sed -i 's/0\.9/0.8/' remise.js
node test.js; echo "code=$?"
cp remise.orig.js remise.js
node test.js
OK
ECHEC
code=1
OK

The mutant is killed, since the test fails. Run only the targeted test first, faster than the whole suite, then the full suite for the surviving mutants only. Restore the original copy between two mutants, and check that the original code passes, otherwise a failure proves nothing.

Non-regression is built, not listed

When a fix changes what a detection rule counts, listing the forms not to lose fails: a verifier always finds one more. Keep the old rule aside instead, judge the same inputs with the old and the new one, and require every difference to come from the instruction. For a word counter that moves from splitting on one space to splitting on any run of spaces, the expected difference concerns the extra spaces, and only them.

Figure 1

Red, green, refactor

01
Test written
A test describing the expected behaviour is written before any implementation.
02
Red observed
The test runner is executed and its failure confirms that the test does indeed test something absent.
03
Minimal implementation
The shortest code that satisfies the test is written, without anticipating needs that are not tested.
04
Green obtained
The test runner is run again and its output confirms that the implementation satisfies the test.
05
Targeted refactor
A single concern is reworked at a time, with the test runner active throughout to isolate any regression.
The sequence shows that red is not a skippable step: it proves the test can fail before green proves the implementation satisfies it.
Calibrate it yourself

A developer asks Claude Code to write a test for a discount calculation function before writing that function. She runs this test and reads the error message displayed in the terminal.

Write in one sentence what this situation establishes, and in one sentence what it does not establish.

What to remember
  • Claude examines the test files already present in the repository to reproduce their style and assertion conventions, rather than imposing a new one.
  • Red proves that the test can fail and green proves that the implementation satisfies it, jumping straight to green leaves open the question of a test that would have passed without anything implemented.
  • A refactor touches a single concern at a time, with the test runner active throughout, to isolate the cause of each regression.
  • Explicitly asking for uncovered edge cases, empty, negative, or out of range inputs, rounds out a set of tests that the initial implementation often ignores.
  • A mutant injected into a copy of the code must make the targeted test fail, and a fix is judged by comparing the old and new rule on the same inputs.
Do this now

Pick a small function you still need to write today, ask Claude Code to write the test first from your project's conventions, run that test to check that it genuinely fails, then write the minimal implementation that turns it green.

Check the source

Every datable claim in this lesson links here to the public text behind it. A source that does not open proves nothing.