Try free
10 min read Guide 832 of 877

Test-Driven Development Workflow

Tests drive design. GitScrum helps teams track TDD adoption and measure the impact of test-first practices on quality and velocity.

TDD Fundamentals

The Red-Green-Refactor Cycle

TDD CYCLE:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ THE CYCLE:                                                  │
│ ──────────                                                  │
│                                                             │
│       ┌─────────────────────────────────────┐              │
│       │                                     │              │
│       │    ┌────────┐                       │              │
│       │    │  RED   │ Write failing test    │              │
│       │    └───┬────┘                       │              │
│       │        │                            │              │
│       │        ▼                            │              │
│       │    ┌────────┐                       │              │
│       │    │ GREEN  │ Make it pass          │              │
│       │    └───┬────┘ (minimal code)        │              │
│       │        │                            │              │
│       │        ▼                            │              │
│       │    ┌────────┐                       │              │
│       └────┤REFACTOR│ Improve design        │              │
│            └────────┘ (tests still pass)    │              │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ STEP 1 - RED:                                               │
│ Write a test for behavior that doesn't exist yet          │
│ Run it → It fails (proves test works)                     │
│                                                             │
│ STEP 2 - GREEN:                                             │
│ Write just enough code to pass the test                   │
│ Don't over-engineer, don't optimize                       │
│ Just make it work                                          │
│                                                             │
│ STEP 3 - REFACTOR:                                          │
│ Now improve the code                                       │
│ Remove duplication, clarify names, improve design         │
│ Tests ensure you didn't break anything                    │
│                                                             │
│ REPEAT for each small piece of behavior                   │
└─────────────────────────────────────────────────────────────┘

Example Workflow

TDD in Practice

TDD EXAMPLE:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ FEATURE: Calculate order total with discount               │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ STEP 1 - RED (Write failing test):                         │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ test('calculates total with 10% discount', () => {     ││
│ │   const order = new Order([                            ││
│ │     { price: 100 },                                    ││
│ │     { price: 50 }                                      ││
│ │   ]);                                                  ││
│ │   order.applyDiscount(0.1);                            ││
│ │   expect(order.total()).toBe(135);                     ││
│ │ });                                                     ││
│ │                                                         ││
│ │ RUN → ❌ FAIL (Order doesn't exist)                    ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ STEP 2 - GREEN (Make it pass):                             │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ class Order {                                          ││
│ │   constructor(items) {                                 ││
│ │     this.items = items;                                ││
│ │     this.discount = 0;                                 ││
│ │   }                                                     ││
│ │                                                         ││
│ │   applyDiscount(rate) {                                ││
│ │     this.discount = rate;                              ││
│ │   }                                                     ││
│ │                                                         ││
│ │   total() {                                            ││
│ │     const subtotal = this.items.reduce(               ││
│ │       (sum, item) => sum + item.price, 0              ││
│ │     );                                                 ││
│ │     return subtotal * (1 - this.discount);            ││
│ │   }                                                     ││
│ │ }                                                       ││
│ │                                                         ││
│ │ RUN → ✅ PASS                                           ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ STEP 3 - REFACTOR (Improve):                               │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ • Extract subtotal calculation                         ││
│ │ • Add validation                                       ││
│ │ • Improve naming                                       ││
│ │ • Run tests → Still passing ✅                         ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ NEXT: Write another test for next behavior               │
│ (e.g., maximum discount, negative prices, etc.)          │
└─────────────────────────────────────────────────────────────┘

Benefits

Why TDD Works

TDD BENEFITS:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ BETTER DESIGN:                                              │
│ ──────────────                                              │
│ Writing tests first forces you to think about:            │
│ • How code will be used (API design)                      │
│ • What the code should do (requirements)                  │
│ • How to make it testable (loose coupling)                │
│                                                             │
│ Result: Cleaner, more modular code                        │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ CONFIDENCE:                                                 │
│ ───────────                                                 │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ WITHOUT TESTS:                                          ││
│ │ "Does this change break something?"                    ││
│ │ → Manual testing, uncertainty, fear                    ││
│ │                                                         ││
│ │ WITH TDD:                                                ││
│ │ "Does this change break something?"                    ││
│ │ → Run tests → Know in seconds                          ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ DOCUMENTATION:                                              │
│ ──────────────                                              │
│ Tests document what code should do                        │
│ Executable documentation that can't go stale              │
│ New developers read tests to understand behavior          │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ LESS DEBUGGING:                                             │
│ ───────────────                                             │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ WRITE CODE FIRST:                                       ││
│ │ Write → Test manually → Find bugs → Debug → Fix       ││
│ │ Time: 2 hours coding + 3 hours debugging = 5 hours    ││
│ │                                                         ││
│ │ TDD:                                                     ││
│ │ Test → Code → Pass → Repeat                            ││
│ │ Time: 3 hours (includes tests) + 30 min debug         ││
│ │                                                         ││
│ │ Bugs caught immediately, not hours later              ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘

Test Types

What to Test

TESTING PYRAMID WITH TDD:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│           /\                                                │
│          /  \      E2E Tests                               │
│         / UI \     (Few, slow, broad)                      │
│        /──────\                                             │
│       /        \   Integration Tests                       │
│      / Service  \  (Some, medium speed)                    │
│     /────────────\                                          │
│    /              \  Unit Tests                            │
│   /     Unit       \ (Many, fast, focused)                 │
│  /──────────────────\                                       │
│                                                             │
│ TDD FOCUS:                                                  │
│ ──────────                                                  │
│ Primarily unit tests                                       │
│ Fast feedback loop                                         │
│ Test one thing at a time                                  │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ WHAT TO TEST IN TDD:                                       │
│ ┌─────────────────────────────────────────────────────────┐│
│ │                                                         ││
│ │ ✅ BUSINESS LOGIC:                                       ││
│ │ • Calculations                                         ││
│ │ • Validation rules                                     ││
│ │ • State transitions                                    ││
│ │ • Domain behavior                                      ││
│ │                                                         ││
│ │ ⚠️ INTEGRATION POINTS:                                  ││
│ │ • API contracts                                        ││
│ │ • Database queries (integration tests)                ││
│ │ • External service calls (mocked in unit tests)       ││
│ │                                                         ││
│ │ ❌ DON'T TDD:                                            ││
│ │ • Framework code (already tested)                     ││
│ │ • Simple getters/setters                              ││
│ │ • UI layout (use other testing)                       ││
│ │ • Throwaway prototypes                                ││
│ │                                                         ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘

Team Adoption

Implementing TDD

ADOPTING TDD:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ PHASE 1: LEARN (Week 1-2)                                  │
│ ─────────────────────────                                   │
│ • TDD kata/workshop                                       │
│ • Practice on toy problems                                │
│ • Pair with experienced TDD practitioner                  │
│ • Read/watch TDD resources                                │
│                                                             │
│ PHASE 2: NEW CODE (Week 3-4)                               │
│ ────────────────────────────                                │
│ • Apply TDD to new features                               │
│ • Start with simple stories                               │
│ • Pair programming recommended                            │
│ • Expect slower at first                                  │
│                                                             │
│ PHASE 3: EXPAND (Month 2+)                                 │
│ ──────────────────────────                                  │
│ • More complex features                                   │
│ • Add tests when modifying existing code                  │
│ • Develop team testing patterns                           │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ COMMON CHALLENGES:                                          │
│ ┌─────────────────────────────────────────────────────────┐│
│ │                                                         ││
│ │ "It's slower!"                                          ││
│ │ → Initially yes. Track time saved in debugging.       ││
│ │   Long-term velocity increases.                       ││
│ │                                                         ││
│ │ "I don't know what test to write"                      ││
│ │ → Start with the simplest behavior.                   ││
│ │   What's the most basic thing it should do?           ││
│ │                                                         ││
│ │ "How do I test this complex thing?"                    ││
│ │ → If it's hard to test, design might need work.       ││
│ │   TDD pushes you toward better design.                ││
│ │                                                         ││
│ │ "We have too much legacy code"                         ││
│ │ → TDD new code. Add tests when touching old code.     ││
│ │   Gradual improvement over time.                      ││
│ │                                                         ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘

Best Practices

TDD Guidelines

TDD BEST PRACTICES:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ TEST NAMING:                                                │
│ ────────────                                                │
│ ❌ test1(), testCalculate()                                │
│                                                             │
│ ✅ 'should calculate total with tax'                       │
│ ✅ 'returns error when email invalid'                      │
│ ✅ 'applies discount only to eligible items'               │
│                                                             │
│ Name describes expected behavior                          │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ ONE ASSERTION PER TEST:                                    │
│ ────────────────────────                                    │
│ ❌                                                          │
│ test('order works', () => {                               │
│   expect(order.total()).toBe(100);                        │
│   expect(order.itemCount()).toBe(5);                      │
│   expect(order.isValid()).toBe(true);                     │
│ });                                                        │
│                                                             │
│ ✅                                                          │
│ test('calculates correct total', () => {...});            │
│ test('counts items correctly', () => {...});              │
│ test('validates order', () => {...});                     │
│                                                             │
│ Easier to identify failures                               │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ SMALL STEPS:                                                │
│ ────────────                                                │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ DON'T: Write complex test requiring 100 lines of code ││
│ │ DO: Write test requiring 5-10 lines of code           ││
│ │                                                         ││
│ │ Smaller steps = faster feedback = fewer bugs          ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ DON'T SKIP REFACTOR:                                       │
│ ────────────────────                                        │
│ Green is not done!                                        │
│ Refactor before moving to next test                       │
│ Technical debt accumulates if you skip this               │
└─────────────────────────────────────────────────────────────┘

Measuring TDD

Tracking Adoption

TDD METRICS:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ ADOPTION METRICS:                                           │
│ ─────────────────                                           │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ TDD ADOPTION - Q1 2025                                  ││
│ │                                                         ││
│ │ Stories using TDD:                                      ││
│ │ Jan:  20%  ████                                        ││
│ │ Feb:  45%  █████████                                   ││
│ │ Mar:  68%  █████████████                               ││
│ │                                                         ││
│ │ Test coverage trend:                                    ││
│ │ Jan:  45%                                              ││
│ │ Feb:  58%                                              ││
│ │ Mar:  72%                                              ││
│ │                                                         ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ QUALITY IMPACT:                                             │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ BUGS IN PRODUCTION:                                     ││
│ │                                                         ││
│ │ Before TDD (2024):  8 bugs/sprint average             ││
│ │ After TDD (2025):   3 bugs/sprint average  (-63%)     ││
│ │                                                         ││
│ │ REWORK TIME:                                            ││
│ │                                                         ││
│ │ Before: 25% of sprint on bug fixes                    ││
│ │ After:  10% of sprint on bug fixes  (-60%)            ││
│ │                                                         ││
│ └─────────────────────────────────────────────────────────┘│
│                                                             │
│ VELOCITY:                                                   │
│ ─────────                                                   │
│ Short-term: May dip 10-20% during learning               │
│ Long-term: Often increases as debugging decreases         │
│                                                             │
│ Track both to show the investment pays off               │
└─────────────────────────────────────────────────────────────┘