In short
Most people write code, then tests if there's time left. TDD flips it: write a failing test first, then just enough code to pass. It feels slow for a day and pays off for months.
Test-Driven Development — writing a failing test before writing the implementation, then writing just enough code to make it pass, then refactoring.

Think of it like this
The tailor measures first
A good tailor doesn't cut cloth and then hope it fits. He takes measurements, notes them down, and only then cuts and stitches until it matches. In TDD, the test is your measurement. You write down what 'fits' first, then make the code match it.
Watch it happen
Red, green, refactor
1/6Red: write a test for isValidPhone("9876543210") expecting true. It fails, since the function doesn't exist.
The big ideas
What you need to know
Watch it fail first
A test you've never seen fail might not test anything. Red proves it can catch a missing feature.
Tiny steps
One small behaviour per cycle. Short cycles keep you moving and out of long debugging sessions.
Refactor with a safety net
Because tests cover each behaviour, you can clean up code without fear of breaking it.
Tests become the spec
The test names tell anyone what the function must do, often better than comments.
See it in code
Walk through the code
1// 1. RED: written first, fails because isValidPhone doesn't exist yet2test("accepts a 10-digit Indian mobile number", () => {3 assert.equal(isValidPhone("9876543210"), true);4});5test("accepts +91 with spaces", () => {6 assert.equal(isValidPhone("+91 98765 43210"), true);7});8test("rejects numbers starting with 0 to 5", () => {9 assert.equal(isValidPhone("1234567890"), false);10});11 12// 2. GREEN: just enough code to pass all three13export function isValidPhone(input: string) {14 const digits = input.replace(/\s+/g, "").replace(/^\+91/, "");15 return /^[6-9]\d{9}$/.test(digits);16}1/3Red: describe the first behaviour as a test, run it, and watch it fail.
In real TDD you'd add these tests one per cycle; they're shown together to save space. The node:test and assert imports are left out.
Save yourself the pain
Common mistakes
Oops
Writing all the tests at once, then all the code.
Do this instead
Go one test at a time: red, green, refactor. Small loops are the whole point.
Oops
Skipping the refactor step because the tests are green.
Do this instead
Green is exactly when it's safe to clean up. Skip it and TDD code gets as messy as any other.
Your mission
TDD a validator
Quick check
In TDD, why should you see a new test fail before writing the code?
Go deeper
- 1Practice the red-green-refactor cycle on one small function.
- 2Notice how writing the test first changes how you design the function's interface.
- 3Try TDD on a real feature and reflect on whether it helped or slowed you down for that case.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.