🛠️ Testing, Tools & Ecosystem · Advanced

Test-driven development in Java

Red, green, refactor; the test pyramid.

🧩 The mysteryWhat if you wrote the test before the code, watched it fail on purpose, and then wrote just enough code to make it pass? It sounds backwards. Many teams swear by it.

Red, green, refactor

TDD is a short loop, often minutes. Red: write a small test that fails. Green: write the simplest code that passes. Refactor: improve the design while all tests stay green. Then repeat with the next small behavior.

Why watch it fail?

A failing test proves the test can detect the gap. A test that has never failed might test nothing at all: a wrong assertion, a method never called. Red first means you trust the green.

🔮 Predict it

The first green step

Your first test is assertEquals(0, sum(List.of()));. What's acceptable in the green step?

  1. Just `return 0;`
  2. A full generic summing framework
  3. Ten more tests before any code
Show the answer

**return 0;** is fine! The simplest code that passes keeps each step verified. The next test, like sum(List.of(2, 3)) == 5, then forces a real loop.

Refactor with a safety net

Once green, clean up: rename, extract methods, remove duplication. The tests tell you immediately if behavior changed. Over time the suite becomes a regression safety net, and the design is shaped by how the code is actually used.

⚠️ The trap

"Tested means bug-free"

TDD gives small verified steps, better design and a safety net. It does not guarantee the absence of bugs: tests only check the cases you thought of. A missing test is a missing check.

The test pyramid

The pyramid guides the overall mix: a wide base of fast unit tests, fewer integration tests, and a handful of slow end-to-end tests. Unit tests are fast and stable, and a failure points straight at the broken code.

💼 In the real world

An upside-down pyramid

A team has 40 slow UI end-to-end tests and almost no unit tests. Builds take an hour and failures are hard to pinpoint. The fix: move most checks into fast unit tests and keep a few E2E tests for the key user journeys.

Key takeaways

  1. Red: a failing test proves the test can detect the gap
  2. Green: simplest code that passes
  3. Refactor with the tests as a safety net
  4. Pyramid: many unit, some integration, few E2E

💡 TDD is like setting the finish line before running: you always know exactly when this lap is done.

🤯 Did you know?

Kent Beck, who popularized TDD, describes himself as having "rediscovered" it: the idea of writing the expected output before the program is much older.

Practice questions

A team has 40 slow UI end-to-end tests and almost no unit tests. Builds take an hour and failures are hard to pinpoint. What does the test pyramid suggest?

  1. Run the E2E tests only once a year
  2. Add more end-to-end tests for safety
  3. Move most checks into fast unit tests and keep a few E2E tests for key journeys
  4. Delete all tests and rely on manual QA
Check your answer

Move most checks into fast unit tests and keep a few E2E tests for key journeys. The pyramid puts cheap, fast, precise tests at the base and keeps expensive, flaky-prone tests few.

Which is NOT a benefit usually attributed to TDD?

  1. A regression safety net
  2. A guarantee that the code has no bugs
  3. Small, verified steps
  4. Design shaped by how the code is used
Check your answer

A guarantee that the code has no bugs. Tests only check the cases you thought of. TDD improves design and confidence, but it can't prove the absence of bugs.

Tests need a build that compiles, fetches libraries and runs them. Next: Maven.