TDD by Example: Learning from Kent Beck
Introduction
Kent Beck's "Test-Driven Development: By Example" is a seminal work that introduced many developers to TDD. This article explores key concepts and practical examples from the book.
Money Example: A Classic TDD Case Study
One of the most famous examples from the book is the Money class implementation. Let's see how it demonstrates TDD principles:
// First Test: Equality
test('should consider same amount as equal', () => {
    const five = new Dollar(5);
    expect(five.equals(new Dollar(5))).toBe(true);
    expect(five.equals(new Dollar(6))).toBe(false);
});
// First Implementation
class Dollar {
    constructor(amount) {
        this.amount = amount;
    }
    equals(dollar) {
        return this.amount === dollar.amount;
    }
}
// Second Test: Multiplication
test('should multiply amount correctly', () => {
    const five = new Dollar(5);
    let product = five.times(2);
    expect(product.amount).toBe(10);
    product = five.times(3);
    expect(product.amount).toBe(15);
});
// Updated Implementation
class Dollar {
    constructor(amount) {
        this.amount = amount;
    }
    equals(dollar) {
        return this.amount === dollar.amount;
    }
    times(multiplier) {
        return new Dollar(this.amount * multiplier);
    }
}
            Key Lessons from the Book
- Start with the simplest test that could possibly work
- Make the test pass with the simplest implementation
- Refactor to remove duplication
- Repeat the cycle
Test Naming Best Practices
Following Clean Code principles, test names should be:
- Descriptive and self-documenting
- Follow a consistent pattern
- Include the scenario being tested
- Indicate the expected outcome
Example: Improved Test Names
describe('Dollar', () => {
    test('should return true when comparing equal amounts', () => {
        const five = new Dollar(5);
        expect(five.equals(new Dollar(5))).toBe(true);
    });
    test('should return false when comparing different amounts', () => {
        const five = new Dollar(5);
        expect(five.equals(new Dollar(6))).toBe(false);
    });
    test('should create new Dollar instance when multiplying', () => {
        const five = new Dollar(5);
        const product = five.times(2);
        expect(product).toBeInstanceOf(Dollar);
        expect(product.amount).toBe(10);
    });
});
            Conclusion
Kent Beck's approach to TDD emphasizes simplicity, clarity, and incremental development. By following these principles, we can create more maintainable and reliable code.
"The act of writing a unit test is more an act of design than of verification. It is also more an act of documentation than of verification." - Kent Beck