We use cookies to enhance your experience on the site
CodeWorlds

Test-Driven Development (TDD)

TDD is a software development methodology where you write tests first and then the production code. In Jurassic Park, it is like first designing all the security systems and only then bringing in the dinosaurs.

The Red-Green-Refactor Cycle

TDD is based on three repeating steps:

1. RED - Write a Test That Fails

1// STEP 1: We write the test BEFORE the production code
2describe('FenceSystem', () => {
3  it('should create a fence with voltage', () => {
4    const fence = createFence('Zone A', 10000);
5
6    expect(fence.zone).toBe('Zone A');
7    expect(fence.voltage).toBe(10000);
8    expect(fence.isActive).toBe(true);
9  });
10});
11// Result: RED - createFence does not exist!

2. GREEN - Write the Minimum Code to Pass the Test

1// STEP 2: We write the simplest code that passes the test
2function createFence(zone, voltage) {
3  return {
4    zone,
5    voltage,
6    isActive: true
7  };
8}
9// Result: GREEN - test passes!

3. REFACTOR - Improve Code While Keeping Tests Green

1// STEP 3: We improve the code (tests still green!)
2class Fence {
3  constructor(zone, voltage) {
4    this.zone = zone;
5    this.voltage = voltage;
6    this.isActive = true;
7  }
8
9  getStatus() {
10    return this.isActive ? 'ACTIVE' : 'OFFLINE';
11  }
12}
13
14function createFence(zone, voltage) {
15  return new Fence(zone, voltage);
16}
17// Result: GREEN - tests still pass after refactoring!

Practical TDD Example

Let's build a dinosaur feeding system step by step:

Iteration 1: Basic Feeding

1// RED: Write the test
2test('carnivore eats meat', () => {
3  const feeder = new DinoFeeder();
4  const result = feeder.feed('T-Rex', 'meat');
5  expect(result.success).toBe(true);
6});
7
8// GREEN: Minimal implementation
9class DinoFeeder {
10  feed(species, food) {
11    return { success: true };
12  }
13}
14// Test passes - but the implementation is too simple!

Iteration 2: Diet Validation

1// RED: Add test for incorrect food
2test('carnivore rejects plants', () => {
3  const feeder = new DinoFeeder();
4  const result = feeder.feed('T-Rex', 'plants');
5  expect(result.success).toBe(false);
6  expect(result.reason).toBe('Wrong diet');
7});
8
9// GREEN: Extend the implementation
10class DinoFeeder {
11  constructor() {
12    this.diets = {
13      'T-Rex': 'carnivore',
14      'Triceratops': 'herbivore',
15      'Velociraptor': 'carnivore',
16    };
17  }
18
19  feed(species, food) {
20    const diet = this.diets[species];
21
22    if (diet === 'carnivore' && food !== 'meat') {
23      return { success: false, reason: 'Wrong diet' };
24    }
25    if (diet === 'herbivore' && food !== 'plants') {
26      return { success: false, reason: 'Wrong diet' };
27    }
28
29    return { success: true };
30  }
31}

Iteration 3: Unknown Species

1// RED: Test for unknown species
2test('unknown species throws error', () => {
3  const feeder = new DinoFeeder();
4  expect(() => feeder.feed('Unknown', 'meat')).toThrow('Unknown species');
5});
6
7// GREEN: Add error handling
8class DinoFeeder {
9  // ... previous code ...
10
11  feed(species, food) {
12    const diet = this.diets[species];
13
14    if (!diet) {
15      throw new Error('Unknown species');
16    }
17
18    if (diet === 'carnivore' && food !== 'meat') {
19      return { success: false, reason: 'Wrong diet' };
20    }
21    if (diet === 'herbivore' && food !== 'plants') {
22      return { success: false, reason: 'Wrong diet' };
23    }
24
25    return { success: true };
26  }
27}

TDD Principles

  1. Don't write production code without a red test - always write the test first
  2. Write the minimum test - just enough to show the failure
  3. Write the minimum code - just enough to pass the test
  4. Refactor often - improve code while tests are green
  5. Small steps - each iteration adds one small piece of functionality

Benefits of TDD

1// TDD leads to:
2const tddBenefits = {
3  betterDesign: 'Code is designed for tests = better design',
4  lessDebugging: 'Bugs caught immediately',
5  documentation: 'Tests document code behavior',
6  confidence: 'Confidence during changes and refactoring',
7  coverage: '100% code coverage by definition'
8};
Go to CodeWorlds