The testing pyramid allocates verification by feedback speed and maintenance cost. It favors many narrow tests near the code and fewer broad tests across deployed boundaries. The shape is a heuristic, not a fixed ratio: the useful mix follows the system’s risks, architecture, and cost of a missed defect.

Testing Pyramid

Link to original

LayerPurposeRelative quantitySpeedCost and failure diagnosis
UnitVerify branching rules and small behaviors without real I/OManyFastest; normally millisecondsCheapest to run and maintain; failures usually identify one behavior
Integration / serviceVerify components and real boundaries such as persistence, serialization, messaging, or an in-process APIFewerSlower; setup and I/O dominateMore environment and data management; failures can span several components
End-to-end / UIVerify a critical user journey through the assembled systemFewSlowestHighest setup, runtime, and maintenance cost; failures have the widest diagnostic surface

Push an assertion downward only when the lower layer can expose the same risk. A price rule belongs in unit tests; a database constraint needs an integration test; checkout routing through browser, API, identity, and payment needs a small number of end-to-end checks. A service dominated by SQL or protocol adapters may rationally contain more integration tests than unit tests without “breaking” the pyramid.

The common failure is an inverted suite: broad UI tests cover every branch, run slowly, and fail for unrelated environmental reasons. Keep a thin end-to-end layer for critical journeys, put boundary behavior at the integration layer, and retain fast local feedback for logic. Measure duration, flakiness, maintenance effort, and escaped defects instead of enforcing percentages.

Questions

References