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
Member discussion: