Testing Pyramid: Where the API Layer Fits

The testing pyramid explained: what unit, integration and end-to-end tests each do best, where API tests sit, and how many of each to write.

Mustafa BayramogluMustafa BayramogluAbstract illustration of a three-layer pyramid of connected nodes, wide at the base and narrow at the top

The testing pyramid says to write many small, fast unit tests, fewer integration tests and only a few end-to-end tests. The API layer sits in the middle: an API flow test checks routes, auth and data shapes over HTTP, without driving a browser. This guide covers what each layer does best, where API tests fit, and how many tests to write at each level.

What the testing pyramid says

Ham Vocke’s The Practical Test Pyramid, on Martin Fowler’s site, defines it: “The ‘Test Pyramid’ is a metaphor that tells us to group software tests into buckets of different granularity.” Picture three layers. The base holds many small tests, and the top holds a few broad ones. The higher a test sits, the fewer of them you write.

Our guide to unit tests vs integration tests covers the bottom two layers in depth. This post takes up the question that guide leaves open: where do tests that call your API over HTTP belong?

The three layers and what each does best

Unit tests (base). A unit test checks one function, class or module on its own. When it fails, it names the exact line. That makes unit tests the best tool for logic: edge cases, math, parsing and validation rules.

Integration tests (middle). An integration test checks that parts built separately still work once you connect them: routes, middleware, auth, config and the database. They need the app running, so they are slower than unit tests. They find the bugs that live between the parts.

End-to-end tests (top). An end-to-end test checks a whole user journey. It often drives a browser or a mobile app. It covers the most ground, which is why the pyramid keeps these tests few.

Unit tests carry a cost the pyramid rarely mentions. In our experiment, the big unit suite went red on three of four refactors that changed nothing a user or client sees. Tests that pin how the app is wired fail when the wiring changes for a good reason. Count those false alarms along with run time.

Where the API layer sits

API tests belong in the middle layer. A flow is more than one request: it logs in, takes the token from the response, and uses it on the next call. That chaining is what makes it an integration test. It checks the connection between steps, which a single-endpoint check misses.

The difference from an end-to-end test is the entry point. An API flow test starts at the HTTP layer, which skips the UI. It can run the same journey, such as log in, add to cart, check out, without clicking anything. It will not catch a button that moved or a page that draws wrong, so keep a small set of browser tests for that. The end-to-end testing guide covers both layers.

You can write API flows by hand with any HTTP test library. You can also record them. Stresseur records how an API is really used during development, turns those flows into YAML tests, and runs them in CI on every pull request. Run npx stresseur record to capture a flow. The flows live in your repo under api-tests/. The page on API integration tests from real traffic shows how it works. The Free plan covers 1 private repo plus public repos.

What 8 real bugs showed about the layers

We ran a unit suite and one API flow test against the same 8 ordinary bugs. The unit tests caught 5. The flow caught 6. Each caught bugs the other missed, and one bug got past both. The unit suite had 2,189 tests, all passing, covering 99% of the lines in the app’s source.

The rename is the middle layer’s case. The commit renamed the login token and updated the unit tests that read it. All 2,189 tests passed. The web app still read the old name, so nobody could log in. The flow read the token from the real response, sent its next request without one, and got a 401.

The tags bug is the base layer’s case. The unit tests caught a bug the flow could not, because the flow always sent tags.

The result does not say that unit tests are weak or that flows are strong. Each layer sees what the other cannot. The full method and every row are in our unit test experiment.

How many tests belong in each layer

Google’s testing blog, in Just Say No to More End-to-End Tests, gives a 70/20/10 split as a first guess: 70% unit, 20% integration and 10% end-to-end.

Treat the split as a starting point. What matters more is what each layer covers. If your API is the product, or several clients depend on it, give the middle layer more weight. A few API flows that cover your main journeys can catch wiring bugs that a large unit suite misses.

Is the testing pyramid outdated?

Some engineers say so, as in a Reddit discussion of the idea. Martin Fowler names the weak point himself in his TestPyramid note: the pyramid “is based on the assumption that broad-stack tests are expensive, slow, and brittle compared to more focused tests”.

That assumption is worth checking against your own suite. If a broad API test runs fast and rarely breaks, it earns more weight than the pyramid gives it. If your unit suite fails on every refactor, as ours did on three of four, it earns less. The shape is a default, and your bug history decides how far to bend it.

Putting the API layer in the pyramid

Keep the pyramid and put the API layer in its middle. Unit tests give precise failures on logic. API flow tests catch the wiring bugs between parts. A few browser tests cover what only a browser can see. In our experiment each of the first two caught bugs the other missed, so run both on every pull request. Start with the one journey your users cannot live without, such as sign-up or login, and record it as an API flow.

Frequently asked questions

What is the testing pyramid?

A model for the shape of a test suite: many small, fast unit tests at the base, fewer integration tests in the middle and a few end-to-end tests at the top.

What is the Google testing pyramid?

Google's testing blog gives a 70/20/10 split: 70% unit tests, 20% integration tests and 10% end-to-end tests. Treat it as a good first guess, then adjust it to what your own bugs look like.

Where do API tests go on the testing pyramid?

In the middle layer, with the integration tests. They call your routes over HTTP, so they check auth, wiring and data without driving a browser.

Is the testing pyramid outdated?

Critics say it assumes broad tests are slow, costly and fragile. If your API tests are fast and stable, give them more weight. Check that assumption against your own suite before you drop the shape.

Do you still need unit tests if you have API tests?

Yes. In our experiment the unit tests caught a bug that the API flow could not, because the flow always sent tags.

All posts