4.5.14 · HinglishSoftware Engineering

TDD — Red-Green-Refactor cycle

1,933 words9 min readRead in English

4.5.14 · Coding › Software Engineering


WHAT is TDD?

Teen states:

Phase Color Goal Rule
Red 🔴 Ek test likho jo fail ho Bina failing test ke production code mat likho
Green 🟢 Use jaldi pass karo (chahe ugly ho) Minimum code likho, chahe fake karo
Refactor 🔵 Design improve karo, koi naya behavior nahi Sirf green pe refactor karo; tests passing rehni chahiye
Figure — TDD — Red-Green-Refactor cycle

WHY do it this way?


HOW the cycle runs (step by step)


Worked Example 1 — Scratch se FizzBuzz banana (tests se code ka derivation)

Hum implementation ko purely Red-Green-Refactor follow karke derive karte hain.

Cycle 1 — RED

def test_one_returns_1():
    assert fizzbuzz(1) == "1"

Yeh step kyun? Sabse chhota possible behavior. Run karo to fail karta hai: fizzbuzz exist nahi karta (sahi reason se Red — stub karne ke baad).

Cycle 1 — GREEN

def fizzbuzz(n):
    return "1"      # fake it — hardcoded!

Yeh step kyun? Pass karne ke liye minimum. Hardcoding intentional hai — yeh agli test ko generalization drive karne par majboor karta hai.

Cycle 2 — RED

def test_two_returns_2():
    assert fizzbuzz(2) == "2"

Kyun? Yeh humein "1" hardcode karna band karne par majboor karta hai.

Cycle 2 — GREEN

def fizzbuzz(n):
    return str(n)

Kyun? Ab sirf utna hi generalize kiya jितना chahiye. Dono tests pass hain.

Cycle 3 — RED → GREEN (Fizz rule)

def test_three_returns_Fizz():
    assert fizzbuzz(3) == "Fizz"
def fizzbuzz(n):
    if n % 3 == 0:
        return "Fizz"
    return str(n)

Cycle 4 — Buzz add karo, phir FizzBuzz, har ek apni failing test se driven. Saare tests green hone ke baad:

REFACTOR

def fizzbuzz(n):
    out = ""
    if n % 3 == 0: out += "Fizz"
    if n % 5 == 0: out += "Buzz"
    return out or str(n)

Yeh step kyun? Branchy duplication hata di. Koi naya test nahi chahiye — behavior identical hai; tests abhi bhi pass hain, jo prove karta hai ki refactor safe hai.


Worked Example 2 — Test se bug fix drive karna

Tumne ek bug pakda: divide(10, 0) ungracefully crash karta hai.

RED — bug ko test ki tarah reproduce karo

def test_divide_by_zero_raises_value_error():
    with pytest.raises(ValueError):
        divide(10, 0)

Kyun? Failing test bug ko precisely capture karta hai. Yeh abhi fail hota hai (ZeroDivisionError raise karta hai, ValueError nahi).

GREEN

def divide(a, b):
    if b == 0:
        raise ValueError("cannot divide by zero")
    return a / b

Kyun? Minimal guard. Test pass ho jaata hai — aur yeh suite mein hamesha ke liye regression guard ki tarah rehta hai taaki bug kabhi silently wapas na aa sake.


Economics — Chhote cycles kyun matter karte hain


Flashcards

TDD ke teen phases order mein kya hain?
Red (failing test likho) → Green (pass karne ke liye minimal code) → Refactor (green rehte hue clean up karo).
TDD mein production code likhne se pehle kya karna chahiye?
Ek test likhna jo sahi reason se fail ho.
Test pehle kyun fail hona chahiye (Red step)?
Yeh prove karne ke liye ki test mein actually missing/broken behavior detect karne ki power hai — warna yeh galat reason se pass ho sakta hai aur kabhi bug nahi pakadega.
Green phase mein kitna code likhne ka rule hai?
Pass karne ke liye minimum — hardcoding/faking allowed hai; baad ki tests generalization ko force karti hain.
Refactor phase mein ek constraint kya hai?
Tum structure improve kar sakte ho lekin observable behavior bilkul bhi nahi badlna chahiye; saare tests green rehne chahiye.
Early Green steps mein return value hardcode karna valid kyun hai?
Yeh simplest pass hai; agli failing test (triangulation) tumhe generalize karne par majboor karti hai, to design sirf utna hi grow karta hai jitna zaroorat ho.
TDD mein "triangulation" ka kya matlab hai?
Multiple chhote concrete tests add karna jo code ko fake/hardcoded answer se real algorithm ki taraf generalize hone par majboor kare.
TDD ek bug ko permanent protection mein kaise badalta hai?
Tum ek failing test likhte ho jo bug reproduce karta hai; ek baar green hone par woh test suite mein regression guard ki tarah rehta hai.
Agar test likhna painful ho to iska kya matlab hai?
Yeh design feedback hai — tumhara code shayad bahut tightly coupled hai ya hidden dependencies hain; testability ke liye refactor karo.
Ek behavior per test ya ek test per feature — kaunsa aur kyun?
Ek behavior per test, taaki failure exactly bataye ki kya tuta (failure localization).

Recall Feynman: 12-saal ke bacche ko samjhao

Socho tum LEGO ek checklist ke saath bana rahe ho. Koi bhi brick snap karne se pehle tum likh lete ho: "Jab main done hounga, darwaza khulna chahiye." Abhi darwaza exist hi nahi karta, isliye checklist item red hai (ho nahi gaya). Phir tum LEGO ka sabse chhota piece add karte ho jo darwaza khol de — ab yeh green hai (ho gaya!)। Phir bricks ko tidy karte ho taaki neat lage, lekin check karte rehte ho ki darwaza abhi bhi khulta hai (green raho). Tum yeh ek chhoti si cheez ek baar mein karte ho. Cool part yeh hai: har checklist item hamesha ke liye rehta hai, to agar tum baad mein LEGO se takraao aur darwaza toot jaaye, checklist turant red ho jaati hai aur bata deti hai. Tumhe hamesha pata rehta hai ki kya kaam kar raha hai.


Connections

  • Unit Testing — TDD unit tests pe built hai feedback unit ki tarah.
  • Refactoring — teesra phase; safe tabhi jab tests green hain.
  • Red-Green-Refactor vs BDD - Behavior Driven Development — BDD, TDD ko user-story language tak le jaata hai.
  • Regression Testing — har TDD test ek regression guard ban jaata hai.
  • Code Coverage — TDD ka side effect hai, goal nahi.
  • Continuous Integration — green test suite merge karne ka gate hai.
  • SOLID Principles — testable code naturally loose coupling ki taraf trend karta hai.
  • Test Doubles - Mocks Stubs Fakes — unit under test ko isolate karne ke liye use hote hain.

Concept Map

starts with

then

then

repeat next behavior

acts as

preserves

failing first

minimal slice

painful test signals

only on

TDD Workflow

RED write failing test

GREEN minimal code to pass

REFACTOR improve design

Test as specification

Test as safety net

Proves test can fail

Testable design emerges

Build only what is needed