Why do I hate the testing pyramid?

August 17, 2026

Every book you'll read or talk you'll watch will tell you that your tests should follow the testing pyramid. If it's not a pyramid, it's a honeycomb, a trophy, or some other shape. It's not that I don't like shapes per se. But I think that all these shapes reverse the cause and consequence.

Complete Python Testing Guide

Most test suites break every time you refactor, take forever to write, and still miss the bugs that matter. Learn how to write pytest tests that survive change, go fast, and actually catch regressions.

Take Course

Why do we test?

Before we talk about shapes, let's take a step back. All software companies out there want to make as much money as possible. But to actually make a profit, they need products that bring value to customers - so that they are willing to pay for them. For products to continuously bring value, they need to work as expected. Testing, in whatever form, is how we verify that expectations are met. But expectations change, and they change fast. We need to adapt quickly without breaking things that already work. What we really want is an environment where changing things imposes low risk and low cost. And that's exactly what aiming for a shape gets backwards.

Types of tests

Since I'm on the subject of things I don't like, here's another one - the classic separation of tests: - Unit tests - Integration tests - End-to-end tests

While there might be some common agreement around what end-to-end tests are, there are always heated discussions about what a unit/integration test is. "Is a test a unit test if component A uses component B?" If you ask 10 developers what an integration test is and what a unit test is, you'll get 10 different answers. And that's exactly the problem. How can we work on the same thing if we can't even agree on what certain types of tests mean?

That's why I'd rather separate tests into three types: - Unit tests - they need only the computer's memory and CPU to run. I might as well run them in the middle of the Pacific. - I/O tests - they need some external dependency like Postgres, Redis, DynamoDB, an ML model served over an API, an LLM, ... - End-to-end tests - they need the application deployed to a real environment accessible at some URL or similar (depends on the app type).

From there, one should focus on making each test valuable. If a test is more valuable when component B is mocked, go for it. If it's less valuable for you when component B is mocked, then don't mock. It's that simple.

What should we do instead?

Aiming for a testing pyramid is not a testing strategy. A testing strategy should focus on the outcomes and not on the number of tests of certain types. You can start with these four:

  • Issues are caught as early in the process as possible.
  • Passed tests mean it's safe to release to production.
  • Failed tests mean we need to fix something before releasing.
  • Tests are executed fast to provide quick feedback.

If you follow that, you might end up with any "shape." Be it a pyramid, a square, a bird, a trophy, a baseball bat, or none of these. It highly depends on the project's domain, maturity, and so on. And it might change over time. But following these rules will actually make tests work for you. One should never add a unit test because "We should have lots of unit tests." The same way, one should never skip an end-to-end test because "We already have many end-to-end tests. Let's just add an integration test instead." Just write the test that makes you sleep better and the product team happy. Write a test that's of high value - as described in the article Why most Python tests are a waste of time?. And make sure to adapt them over time. If you see that you can make the test suite faster by moving some end-to-end tests to I/O tests while keeping the same level of protection, don't hesitate to do that.

And that's really it. No shapes! Just a fast and reliable test suite that works for you!

Become a better engineer, one article at a time.

Practices, mindsets, and habits that actually move the needle. Delivered weekly to your inbox.

Conclusion

Testing software is far too often presented with some made-up goals like code coverage or the shape of tests. What counts is that you can deliver your software fast and reliably - to deliver the most value possible to your users. Anything else is just a masquerade. So do I actually hate the testing pyramid? Maybe not hate, but I certainly don't like it. At least not as any kind of goal. On complex and long projects, you'll naturally gravitate towards it, but it won't happen on every project. And that's fine.

If you'd like to deep dive into writing tests as described here - no shapes, no masquerade - I cover it all in the Complete Python Testing Guide.

Share