Overview
The Testing Pyramid is a guideline for the distribution of different types of automated tests in a software project. It suggests that you should have a large number of low-level tests and a small number of high-level tests to ensure a fast, reliable, and cost-effective test suite.
Core Concepts
- Unit Tests (Base):
- Scope: Test a single function or class in isolation.
- Characteristics: Extremely fast, highly deterministic, easy to write.
- Goal: Verify that a small “unit” of logic works as expected.
- Integration Tests (Middle):
- Scope: Test the interaction between two or more components (e.g., a service and its database).
- Characteristics: Slower than unit tests, may require external dependencies (mocks or real test databases).
- Goal: Ensure that different parts of the system work together correctly.
- End-to-End (E2E) Tests (Top):
- Scope: Test the entire application from the user’s perspective (e.g., using a browser to log in and checkout).
- Characteristics: Slowest, most brittle, most expensive to maintain.
- Goal: Verify that the “critical paths” of the application are functional.
Code Examples
// Unit Test (Jest)
test('add should return sum of two numbers', () => {
expect(add(1, 2)).toBe(3);
});
// Integration Test (Conceptual)
test('UserService.saveUser should persist user to DB', async () => {
const user = { name: "Bob" };
await userService.saveUser(user);
const saved = await db.findUser("Bob");
expect(saved).toEqual(user);
});
// E2E Test (Cypress/Playwright)
it('should allow a user to log in', () => {
cy.visit('/login');
cy.get('#username').type('admin');
cy.get('#password').type('password');
cy.get('#submit').click();
cy.url().should('include', '/dashboard');
});
Use Cases
- Regression Testing: Running the pyramid on every commit to ensure no new bugs were introduced.
- Confidence: Providing developers with the confidence to refactor code without breaking existing functionality.
- Fast Feedback Loop: Unit tests provide instant feedback, while E2E tests provide the final seal of approval.
Gotchas
- The “Ice Cream Cone” Anti-pattern: Having too many E2E tests and not enough unit tests. This leads to a slow, flaky test suite that is hard to debug.
- Over-Mocking: Mocking too much in integration tests can lead to a “green” test suite that fails in production because the real interaction was different.
