“Write tests first? There isn’t even any code yet—what would I test?”
When first encountering TDD (Test-Driven Development), everyone has this reaction. The order seems backward, and it feels like you’re doubling your workload for no reason.
But after using it in real work for a few months, your perspective starts to change.
TDD is a development method that repeats “failing test (Red) → minimum code that makes it pass (Green) → cleanup (Refactor)” in very short cycles. The key is running this cycle quickly, from a few seconds to a few minutes.
Today, I’ll walk through how this Red-Green-Refactor cycle actually works.
TDD Red-Green-Refactor: A 3-Step Summary ✍️
First, here’s the entire cycle at a glance.
- Red: Write a test first for functionality that doesn’t exist yet. It fails, naturally.
- Green: Write only the minimum code needed to pass the test. It doesn’t need to be pretty.
- Refactor: Clean up the code while keeping the tests passing.
That’s all there is to it: bundle these three steps together and repeat them continuously.
The important thing is not to make each step too large. Break it down into small pieces—not “the entire login feature,” but something like “return an error when the email is empty.”
If one cycle takes 30 minutes, it’s probably just development with testing added, not TDD.
Red Stage: Why Deliberately Write Failing Code?
This is the hardest part to understand when learning TDD. You know it will fail, so why run it?
The reason is simple. To verify that the test “fails properly.”
If a test passes as soon as you write it, it may be an empty shell that validates nothing. Seeing the failure first is essentially testing the test itself.
As a simple example, suppose we’re building a function that adds two numbers. The test comes before the code.
// add The function doesn't exist yet. So this test fails(Red)
struct AddTests {
@Test func Addition_1add2is3() {
#expect(add(1, 2) == 3)
}
}
Run it in this state and you’ll get an error like “cannot find ‘add’ in scope.” Seeing this red light actually puts me at ease because the goal is clear.
From here, I have exactly one job: turn that red light green.
Green and Refactor: Where Real Skill Shows
The principle of the Green stage is “keep it embarrassingly simple.”
Here’s the fastest code that passes the test above.
// The minimum code that passes the test(Green)
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
It looks obvious, right? Yet beginners often worry about the future here and try to add exception handling, logging, and configuration values in advance.
TDD deliberately restrains that impulse. The rule is not to write code that the current test doesn’t require.
Only after the green light comes on do you move to Refactor. This is when you refine variable names and remove duplication.
The key is never adding new functionality during Refactor. You only improve the structure while keeping the tests passing.
What if the light turns red while cleaning things up? Just undo what you changed. The tests guarantee that it worked moments ago.
Thanks to this safety net, refactoring became much more fearless.
Does TDD Slow Development Down? 🤔
It’s the question I hear most often. After using it myself, my answer is: “It depends.”
I summarized the differences I noticed in a table.
| Category | With TDD | Tests written later |
|---|---|---|
| Initial speed | Somewhat slower | Fast |
| When bugs are found | Immediately after writing | Much later |
| Refactoring burden | Low | High |
| Complex logic | Advantage | Disadvantage |
Honestly, TDD can feel cumbersome when you’re quickly building a single simple screen.
On the other hand, it clearly paid off for logic with intertwined conditions, such as payments, settlements, and discount calculations. Once I locked down each case with tests, I wasn’t afraid to overhaul the code later.
In the end, TDD isn’t a universal solution; it’s closer to a tool for managing complexity.
Wrapping Up
If TDD feels difficult, don’t start grandly. Run Red-Green-Refactor on a single function first.
Once small success cycles become second nature, you’ll begin to understand why people can’t give this method up. I hope you’ll turn on the red light with just one test today.

