Why TDD is Not About "Writing Tests," But About "Thinking Differently"
\n\nImagine you're building a house. You have blueprints, materials, and a crew. But you start laying bricks without checking the foundation. A month later, you find cracks in the walls. Sound familiar? In programming, this is called "we'll fix it later." And "later" usually comes at 3 AM before deployment.
\n\nTest-Driven Development (TDD) is a technique that turns the process upside down. You don't write code and then tests. You write a test first — and only then the code that passes that test. Sounds crazy? In practice, it saves hours, nerves, and makes your code cleaner than mountain morning air.
\n\nIn this article, we'll break down TDD in Java with concrete examples. No fluff — just code, the Red-Green-Refactor cycle, and real scenarios. Let's go.
\n\nWhat is TDD and How the Red-Green-Refactor Cycle Works
\n\nTDD is based on three simple steps that repeat cyclically:
\n\n- \n
- Red — write a test that fails (it must fail). \n
- Green — write the minimal code to make the test pass. \n
- Refactor — improve the code without changing its behavior. The tests remain green. \n
It may seem like this slows down development. In reality, it speeds it up. You stop wondering, "does this work?" You know: it works, because the test is green.
\n\nKey Principles of TDD
\n- \n
- Don't write a single line of production code without a test. \n
- The test should be as simple as possible and check exactly one behavior. \n
- Write just enough code to make the test pass. No "let's add this just in case." \n
Now let's move on to Java and JUnit 5 — the most popular framework for unit testing.
\n\nProject Setup: Maven, JUnit 5, and Structure
\n\nFor the examples, we'll use Maven. Add the dependency to pom.xml:
<dependency>\n <groupId>org.junit.jupiter</groupId>\n <artifactId>junit-jupiter-api</artifactId>\n <version>5.10.0</version>\n <scope>test</scope>\n</dependency>\n\nThe folder structure is standard for Maven:
\nsrc/\n main/java/com/example/\n test/java/com/example/\n\nAll test classes go into src/test/java. The test class name usually matches the tested class name with the Test suffix. For example, Calculator → CalculatorTest.
First TDD Cycle: Building a Calculator from Scratch
\n\nTask: create a method add(int a, int b) that returns the sum. With TDD, we start not with the class, but with the test.
Step 1: Red — Write a Test That Will Fail
\n\nimport org.junit.jupiter.api.Test;\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class CalculatorTest {\n\n @Test\n void shouldAddTwoNumbers() {\n Calculator calc = new Calculator();\n int result = calc.add(2, 3);\n assertEquals(5, result);\n }\n}\n\nTry to run it — the compiler complains: the Calculator class doesn't exist. Great, the red light is on.
Step 2: Green — Write the Minimal Code
\n\nCreate the Calculator class with a method that simply returns the sum:
public class Calculator {\n public int add(int a, int b) {\n return a + b;\n }\n}\n\nRun the test — it's green. The minimal possible implementation worked.
\n\nStep 3: Refactor
\n\nAt this stage, the code is already simple; there's nothing to refactor. But imagine we want to rename the method or add an overflow check. We do that, and the test still passes. If something breaks — the test will fail and immediately point to the problem.
\n\n