Test-Driven Development
01 / 02

The Red-Green-Refactor Cycle

The Red-Green-Refactor Cycle

The Defining Order: Test First

TDD isn't "has tests" — it's a specific ORDER: write the test before the implementation. That ordering is what makes it test-DRIVEN, not just tested.

// RED — write the test, confirm it fails (for the right reason)
test('adds two numbers', () => {
  expect(add(2, 3)).toBe(5);
});
// fails: add is not defined — good, that's the expected failure

// GREEN — minimal code to pass, nothing more
function add(a, b) { return a + b; }

// REFACTOR — now safe to clean up, the passing test is the safety net
// (nothing to refactor yet in this trivial example)

Confirming RED (not just writing the test) catches a subtle bug: a test that passes even before any implementation exists is testing nothing meaningful. GREEN's "minimal code" discipline resists building ahead of what's currently tested — future tests drive future functionality, not speculation.

Refactor Needs the Safety Net

With a passing test already in place, restructuring the code (removing duplication, renaming, reorganizing) is safe — the test immediately signals if behavior actually changed, not just structure. This is the same "refactoring requires tests" principle from general refactoring practice, but built incrementally, one small piece at a time.

Fast Unit Tests, Not Slow E2E

TDD's tight cycle (many times per hour) needs near-instant feedback — this is why TDD discussions center on fast unit tests, not slower integration/end-to-end tests that don't fit the rapid cadence.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free