9 min read • Guide 744 of 877
Test-Driven Development with GitScrum
TDD isn't just about testing - it's about design and confidence. GitScrum supports TDD workflows with task tracking that reflects the red-green-refactor cycle.
TDD Fundamentals
The TDD Cycle
RED-GREEN-REFACTOR CYCLE:
┌─────────────────────────────────────────────────────────────┐
│ │
│ ┌────────────┐ │
│ │ RED │ ← Write failing test │
│ │ (Failing │ "What should the code do?" │
│ │ Test) │ │
│ └─────┬──────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ │
│ │ GREEN │ ← Write minimum code to pass │
│ │ (Passing │ "Make it work, nothing more" │
│ │ Test) │ │
│ └─────┬──────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ │
│ │ REFACTOR │ ← Improve without breaking tests │
│ │ (Clean │ "Make it clean" │
│ │ Code) │ │
│ └─────┬──────┘ │
│ │ │
│ └──────────→ Repeat │
│ │
│ CYCLE TIME: Minutes, not hours │
│ │
│ KEY RULES: │
│ • Never write code without a failing test │
│ • Write the minimum code to pass │
│ • Refactor only when tests are green │
│ • Run tests frequently │
└─────────────────────────────────────────────────────────────┘
TDD Benefits
WHY TDD WORKS:
┌─────────────────────────────────────────────────────────────┐
│ │
│ DESIGN BENEFITS: │
│ • Forces you to think about interface first │
│ • Leads to modular, testable code │
│ • Catches design problems early │
│ • Results in simpler designs │
│ │
│ QUALITY BENEFITS: │
│ • Bugs caught immediately │
│ • High test coverage naturally │
│ • Regression protection │
│ • Confidence to refactor │
│ │
│ PRODUCTIVITY BENEFITS: │
│ • Less time debugging │
│ • Faster feedback │
│ • Documentation through tests │
│ • Easier onboarding │
│ │
│ PSYCHOLOGICAL BENEFITS: │
│ • Small wins (green tests) │
│ • Confidence in code │
│ • Safe to change │
│ • Clear progress │
│ │
│ WITHOUT TDD: │
│ Write code → Test later → Find bugs → Debug → Fix → Repeat│
│ │
│ WITH TDD: │
│ Write test → Write code → Test passes → Refactor → Done │
└─────────────────────────────────────────────────────────────┘
TDD in Practice
Example Workflow
TDD EXAMPLE - ADD TO CART:
┌─────────────────────────────────────────────────────────────┐
│ │
│ STORY: "As a user, I can add items to my cart" │
│ │
│ TDD CYCLE 1: │
│ │
│ RED: Write test │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ test('adds item to empty cart', () => { ││
│ │ const cart = new Cart(); ││
│ │ cart.add(item); ││
│ │ expect(cart.items.length).toBe(1); ││
│ │ }); ││
│ │ // Result: ❌ FAILS - Cart doesn't exist ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ GREEN: Write minimum code │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ class Cart { ││
│ │ items = []; ││
│ │ add(item) { this.items.push(item); } ││
│ │ } ││
│ │ // Result: ✅ PASSES ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ REFACTOR: (Nothing to refactor yet) │
│ │
│ TDD CYCLE 2: │
│ │
│ RED: Next test │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ test('increases quantity if item exists', () => { ││
│ │ const cart = new Cart(); ││
│ │ cart.add(item); ││
│ │ cart.add(item); ││
│ │ expect(cart.items.length).toBe(1); ││
│ │ expect(cart.items[0].quantity).toBe(2); ││
│ │ }); ││
│ │ // Result: ❌ FAILS - no quantity handling ││
│ └─────────────────────────────────────────────────────────┘│
│ │
│ GREEN: Add quantity logic │
│ REFACTOR: Extract findItem method │
│ │
│ Continue until all requirements covered... │
└─────────────────────────────────────────────────────────────┘
Test Types
TDD TEST PYRAMID:
┌─────────────────────────────────────────────────────────────┐
│ │
│ /\ │
│ / \ │
│ / E2E\ Few, slow, expensive │
│ /──────\ │
│ / \ │
│ /Integration\ Some, medium speed │
│ /──────────────\ │
│ / \ │
│ / Unit Tests \ Many, fast, cheap │
│ /────────────────────\ │
│ │
│ UNIT TESTS (TDD Focus): │
│ • Test single functions/methods │
│ • No external dependencies │
│ • Milliseconds to run │
│ • Write many of these │
│ │
│ INTEGRATION TESTS: │
│ • Test components together │
│ • May use database, API │
│ • Seconds to run │
│ • Write fewer of these │
│ │
│ E2E TESTS: │
│ • Test full user flows │
│ • Real browser, real services │
│ • Minutes to run │
│ • Write few, critical paths only │
│ │
│ TDD PRIMARILY: Unit tests │
│ ALSO USEFUL: Integration tests for key flows │
└─────────────────────────────────────────────────────────────┘
TDD in GitScrum Workflow
Story with TDD
TDD INTEGRATED IN STORY FLOW:
┌─────────────────────────────────────────────────────────────┐
│ │
│ STORY: Add to Cart Functionality │
│ │
│ STATUS: In Progress │
│ │
│ DEFINITION OF DONE: │
│ ☐ All acceptance criteria met │
│ ☑ Unit tests written and passing │
│ ☐ Code reviewed │
│ ☐ Integrated and deployed │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ SUBTASKS (TDD Approach): │
│ │
│ ☑ Write tests for add to empty cart │
│ ☑ Implement add to empty cart │
│ ☑ Write tests for quantity increment │
│ ☑ Implement quantity increment │
│ ☐ Write tests for max quantity │
│ ☐ Implement max quantity │
│ ☐ Write tests for out of stock │
│ ☐ Implement out of stock │
│ ☐ Refactor and cleanup │
│ │
│ TEST COVERAGE: │
│ Cart module: 94% coverage │
│ All tests: ✅ 47 passing │
│ │
│ NOTE: Each test-implement pair is a mini red-green cycle │
└─────────────────────────────────────────────────────────────┘
Tracking TDD Work
TDD IN TASK TRACKING:
┌─────────────────────────────────────────────────────────────┐
│ │
│ OPTION 1: Tests as part of story │
│ │
│ Story: Add to cart │
│ └── Subtasks: │
│ ├── Tests for happy path │
│ ├── Implementation │
│ ├── Tests for edge cases │
│ └── Refactoring │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ OPTION 2: Tests implicit in definition of done │
│ │
│ Story: Add to cart │
│ Definition of Done: │
│ • Unit tests with 80%+ coverage │
│ • All tests passing │
│ • Edge cases tested │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ DO NOT: │
│ │
│ ❌ "Testing" as separate story after development │
│ ❌ "Write tests" as a sprint task after code │
│ ❌ Skip tests when under time pressure │
│ │
│ Tests are PART of development, not separate │
└─────────────────────────────────────────────────────────────┘
Common Challenges
Starting with TDD
TDD ADOPTION TIPS:
┌─────────────────────────────────────────────────────────────┐
│ │
│ START SMALL: │
│ • Start with new code, not legacy │
│ • Start with simple features │
│ • Pair with experienced TDD developer │
│ │
│ LEARN THE RHYTHM: │
│ • Resist urge to write more code than needed │
│ • Keep cycles short (minutes) │
│ • Celebrate green tests │
│ │
│ COMMON MISTAKES: │
│ │
│ ❌ Tests too big │
│ → Break into smaller tests │
│ │
│ ❌ Writing implementation first │
│ → Stop, delete, write test first │
│ │
│ ❌ Not refactoring │
│ → Schedule refactor time, it's essential │
│ │
│ ❌ Skipping when rushed │
│ → Rushing without tests creates more rush later │
│ │
│ TEAM ADOPTION: │
│ │
│ • Include in definition of done │
│ • Review tests in code review │
│ • Share testing patterns │
│ • Celebrate test-first culture │
│ • Pair on complex features │
└─────────────────────────────────────────────────────────────┘
When TDD Is Hard
CHALLENGING TDD SCENARIOS:
┌─────────────────────────────────────────────────────────────┐
│ │
│ UI COMPONENTS: │
│ Challenge: Testing DOM, visuals │
│ Approach: Test behavior, not appearance │
│ Tools: Testing Library, Jest │
│ Tip: Separate logic from rendering │
│ │
│ DATABASE/EXTERNAL SERVICES: │
│ Challenge: Slow, stateful tests │
│ Approach: Mock external dependencies │
│ Tools: Mock libraries, test doubles │
│ Tip: Test integration separately │
│ │
│ LEGACY CODE: │
│ Challenge: Code not designed for testing │
│ Approach: Characterization tests first │
│ Tools: Approval tests │
│ Tip: Refactor to testable design gradually │
│ │
│ UNCERTAIN REQUIREMENTS: │
│ Challenge: Don't know what to test │
│ Approach: Spike first, then TDD │
│ Tip: Throw away spike code, rewrite with tests │
│ │
│ PERFORMANCE-CRITICAL: │
│ Challenge: Need to optimize │
│ Approach: TDD for correctness, then optimize │
│ Tip: Tests protect while optimizing │
│ │
│ "If it's hard to test, the design might need work" │
└─────────────────────────────────────────────────────────────┘