The Shape of Tests — Pyramid, Ice-Cream Cone, Trophy, Honeycomb
Since the mid-2000s, the software industry has produced one diagram after another to answer the question of which kinds of tests to write, and how many: Mike Cohn's test pyramid, Alister Scott's ice-cream cone, Kent C. Dodds's testing trophy, and Spotify's testing honeycomb. We trace each model's proponents and arguments to see why the debate still isn't settled.
Since the mid-2000s, the software industry has produced one diagram after another — pyramid, ice-cream cone, trophy, honeycomb — in answer to the question of which kinds of tests to write, and how many. These aren’t mere metaphors; each reflects the development structures, architectures, and tooling constraints of its era, arguing for the most cost-effective test distribution given the state of the art at that moment. This article traces how the debate began, how it branched, and why it still hasn’t been settled, organized around the proponents of each model and where their arguments diverge.
Test strategy is a real problem precisely because you can’t write an infinite number of tests. For tests verifying the same behavior, finer granularity means faster, more stable, and easier to pinpoint the cause of failure; coarser granularity gets closer to “value as the user experiences it” at the cost of speed and stability. Each model gives a different answer to how to allocate against that tradeoff.
The Origin of the Test Pyramid — Mike Cohn
The concept of the test pyramid traces back to agile coach Mike Cohn. Cohn sketched the diagram around 2003–2004 in conversation with Lisa Crispin, and put it into words as the “Test Automation Pyramid” in his 2009 book Succeeding with Agile: Software Development Using Scrum. Cohn’s original three-layer model was:
- Unit Tests (bottom layer, most numerous) — verify individual functions and classes; fast
- Service Tests (middle layer) — verify APIs and service boundaries
- UI Tests (top layer, fewest) — end-to-end verification through the GUI; slow and brittle
The core of Cohn’s argument was a guideline for allocation: “UI-driven tests are costly to automate and brittle, so keep that layer as thin as possible and verify most of the logic in the layers below.” What matters is that this was presented not as a mere taxonomy but as a resource-allocation strategy.
Popularization and Formalization by Martin Fowler
Cohn’s model was originally a discussion within the agile community, but it became widely known across the industry when Martin Fowler wrote a short article titled “TestPyramid” on his bliki in 2012. Fowler reformulated the pyramid in a more generalized form — “many unit tests, a moderate number of integration tests, few E2E tests” — and, alongside it, sounded a warning about the inverted “ice-cream cone” pattern.
Then in 2018, Fowler’s site published a long-form article by Ham Vocke (Thoughtworks) titled “The Practical Test Pyramid,” which fleshed out the previously abstract pyramid metaphor into a practical guide backed by actual code examples. The article was written to answer a complaint: the pyramid was conceptually sound, but lacked the resolution to show how to implement it in the field.
The Ice-Cream Cone — A Cautionary Inverted Pyramid
Widely cited as the cautionary counterpart to the pyramid is the “Ice-Cream Cone.” Alister Scott, a core contributor to the Watir community, coined the term in a 2012 blog post, “Testing Pyramids & Ice-Cream Cones.” It describes an inverted distribution often seen in real organizations:
- Manual testing occupies the largest share
- UI automation tests come next
- Integration tests are a middling amount
- Unit tests are the fewest
In this shape, the test suite takes a long time to run, pinpointing the cause of failures becomes difficult, and distrust of flaky tests leads to a vicious cycle where testing becomes a formality. The ice-cream cone isn’t usually a “deliberately chosen strategy” but arises naturally as the result of bolting tests on after the fact — which is exactly the contrast with the pyramid: was this designed, or is it the product of neglect?
The Rise of the Testing Trophy — Kent C. Dodds
Around 2017, as component-oriented frontend development with frameworks like React became mainstream in the JavaScript community, Kent C. Dodds proposed the Testing Trophy in a talk and blog post titled “Write tests. Not too many. Mostly integration.,” followed by “The Testing Trophy and Testing Classifications.” Testing Library, which we covered in the previous article, is a design from the same Dodds.
The trophy is made up of four layers, from bottom to top:
- Static — type checking and linting; the foundation
- Unit
- Integration — the widest layer of the trophy, meaning the one deserving the most investment
- E2E — the top, few in number
Dodds’s argument rests on a premise that had changed since 2012: modern testing tools (Jest, React Testing Library, and later Playwright) had made tests covering a broader scope no longer as slow, expensive, or brittle as before. His slogan — “The more your tests resemble the way your software is used, the more confidence they can give you.” — succinctly captures the value that tests should verify behavior visible to the user, not implementation details. Rather than rejecting the pyramid outright, this is a re-weighting that shifts the emphasis of “which layer deserves the most investment” from unit to integration.
The Honeycomb Model — A Microservices Perspective
In a separate context from the frontend, Spotify’s engineering team presented the “Testing Honeycomb” in a 2018 blog post, “Testing of Microservices.” Based on the observation that, in a microservices architecture, the complexity of the connection points between services tends to dominate over the complexity of any single service’s internal logic, they proposed inflating the pyramid’s middle layer (integration tests) into the largest layer, with both unit tests and UI/E2E tests relatively thinned out at either end. The idea is close in spirit to the trophy, but differs in where the focus lands: not the frontend’s “integration of components,” but the “integration of APIs between services.”
The Structural Shift Behind the Debate Over Shape
Why did the 2012 pyramid draw challenges in quick succession during 2017–2018? Behind it lie environmental shifts like these:
- Microservice adoption — logic that a monolith could protect at the “unit” level moved, after service decomposition, into “the connections between services,” increasing the relative importance of the integration layer
- Frontend componentization — since React/Vue, it became more valuable to test the UI as “rendered behavior” rather than as “individual functions”
- Faster, more stable testing tools — with Cypress (released 2015) and later Playwright (released 2020), the speed and determinism of browser tests improved dramatically compared to 2012
- Parallelized CI environments — cloud CI drove down the cost of running tests in parallel that had previously been “too slow to bother with”
In other words, none of these models are universal physical law — each is an argument about economic rationality: what’s worth investing in, given the constraints of its era. The accurate way to understand the disagreement is that it shares the premise that the optimal allocation can shift as the tools change.
Google’s “Test Size” — An Alternative Axis of Classification
Where pyramid-family models all divide layers by scope — unit/integration/E2E — Google, in its book Software Engineering at Google (edited by Titus Winters, Tom Manshreck, and Hyrum Wright; O’Reilly, 2020), proposes an axis called test size, which classifies tests not by scope but by the resource constraints permitted at runtime.
| Size | Runtime constraints | Typical characteristics |
|---|---|---|
| Small | Confined to a single process; no network, disk, or separate-process access | Fast and deterministic; roughly corresponds to unit tests |
| Medium | Confined to a single machine; localhost communication and disk access allowed | Often corresponds to integration tests using a DB or local service |
| Large | Access to multiple machines and external networks allowed | Close to E2E, but defined by “looseness of constraint” rather than “scope” |
The advantage of this classification is that it sidesteps the endless “is this a unit test or an integration test?” argument, and lets CI mechanically check operational constraints instead — questions like “is this test allowed to touch the network?” or “will it fight other tests for resources when run in parallel?” Classification by scope and classification by resource constraint aren’t mutually exclusive; they’re often used together as two different cuts on the same test suite.
The Tradeoffs of Cost, Speed, Reliability, and Determinism
| Dimension | Unit | Integration/Contract | E2E |
|---|---|---|---|
| Execution speed | Very fast (ms) | Medium (seconds) | Slow (seconds to minutes) |
| Determinism (returns the same result) | High | Moderate (depends on external dependencies) | Tends to be low (environment- and timing-dependent) |
| Cost to write | Low | Moderate | High (selectors, waits, data setup) |
| Cost to maintain | Low (if written implementation-independently) | Moderate | High (brittle under UI changes) |
| Confidence gained | Per-unit logic | Integration points | The entire chain of user-facing value |
| Ease of diagnosing failure | Easy | Fairly easy | Hard (requires searching for where it broke) |
As this table shows, no single metric determines which layer is “better.” Strategy is itself a value judgment about which of these several metrics to prioritize.
Model Comparison Table
| Model | Proponent/source | Intended context | Emphasis |
|---|---|---|---|
| Test Pyramid | Mike Cohn (2009 book, conceived around 2003–2004) / Martin Fowler (2012 bliki) | Agile development in general | Maximize units, minimize UI |
| Ice-Cream Cone | Alister Scott (2012) | Organizations that bolted tests on after the fact | Presented as an anti-pattern to avoid |
| Testing Trophy | Kent C. Dodds (around 2017) | Modern JS/frontend | Heavy investment in integration tests |
| Testing Honeycomb | Spotify Engineering blog (2018) | Microservices | Maximize verification of inter-service integration |
What the Debate Teaches Us
The practical lesson to draw from the clash between these models comes down to this: there is no single right shape. When building a strategy, the questions worth asking are:
- In our own architecture, where is complexity concentrated — inside the logic, at integration points, or in the UI?
- What layer can our current tooling execute quickly and stably?
- Does the team actually trust test failures? (An accumulation of flaky tests will break any strategy, regardless of layer)
- Which features change frequently and carry high risk? (Invest more heavily there)
The greatest practical value to draw from this debate isn’t reading the pyramid literally as “just write fewer UI tests,” but understanding the economic rationale behind why each shape was proposed, and choosing — or re-choosing — a shape that fits your own architecture.
From This Article to the Next
We’ve traced the debate over how tests should be distributed. The next article shifts the focus to the contents of individual tests — unit test design and contracts, design principles that sit even further inside than the “granularity” of a test.