The “ ” is a metaphor that tells us to group software
tests into buckets of different granularity. It also gives an idea
of how many tests we should have in each of these groups. Although
the concept of the Test Pyramid has been around for a while, teams
still struggle to put it into practice properly. This
revisits the original concept of the Test Pyramid and shows how
you can put this into practice. It shows which kinds of tests you
should be looking for in the different levels of the pyramid and
gives examples on how these can be implemented.

Production-ready software requires testing before it goes into production. As
the discipline of software development matured, software testing approaches have
matured too. Instead of having myriads of manual software testers development
teams have moved towards automating the biggest portion of their testing
efforts. Automating your test efforts allows teams to know whether their
software is broken in a matter of seconds and minutes instead of days and

The drastically shortened feedback loop fueled by tests goes hand
in hand with agile development practices, continuous delivery and DevOps
culture. Having an effective software testing approach allows your team to move
fast and confidently.

This article explores how a well-rounded test portfolio should look like to
be responsive, reliable and maintainable – regardless of whether you’re building
a microservices architecture, apps or IoT ecosystems. We’ll also get into
the details of building effective and readable automated tests.

The Importance of (Test) Automation

Software has become an essential part of the world we live in. It has
outgrown its early sole purpose of making businesses more efficient. Today
companies try to find ways to become first-class digital companies. As users
everyone of us interacts with an ever-increasing amount of software every
. The wheels of innovation are turning faster.

If you want to keep pace you’ll have to look into ways to deliver your
software faster without sacrificing its quality. Continuous delivery, a
practice where you automatically ensure that your software can be released
into production any time, can help you with that. With continuous delivery
you use a build pipeline to automatically test your software and deploy
it to your testing and production environments.

Building, testing and deploying an ever-increasing amount of software
manually soon becomes impossible — unless you want to spend all your time
with manual, repetitive work instead of delivering working software.
Automating everything — from build to tests, deployment and infrastructure —
is your only way forward.

- buildPipeline - The Practical Test Pyramid

Figure 1: Use build pipelines to automatically and
reliably get your software into production

Traditionally software testing was overly manual work done by deploying your
application to a test environment and then performing some black-box style
testing e.g. by clicking through your user interface to see if anything’s
Often these tests would be specified by test scripts to ensure the
testers would do consistent checking.

It’s obvious that testing all changes manually is time-consuming, repetitive
and tedious. Repetitive is boring, boring leads to mistakes and makes you look
for a different job by the end of the week.

Luckily there’s a remedy for repetitive tasks: automation.

Automating your repetitive tests can be a big game changer in your life as a software
developer. Automate these tests and you no longer have to mindlessly follow click
protocols in order to check if your software still works correctly. Automate
your tests and you can change your codebase without batting an eye. If you’ve
ever tried doing a large-scale refactoring without a proper test suite I bet you
know what a terrifying experience this can be. How would you know if you
accidentally broke stuff along the way? Well, you click through all your manual
test cases, that’s how. But let’s be honest: do you really enjoy that? How about
making even large-scale changes and knowing whether you broke stuff within
seconds while taking a nice sip of coffee? Sounds more enjoyable if you ask

The Test Pyramid

If you want to get serious about automated tests for your software there
is one key concept you should know about: the test pyramid. Mike
Cohn came up with this concept in his book Succeeding with Agile.
It’s a great visual metaphor telling you to think about different layers
of testing. It also tells you how much testing to do on each layer.

- testPyramid - The Practical Test Pyramid

Figure 2: The Test Pyramid

Mike Cohn’s original test pyramid consists of three layers that your
test suite should consist of (bottom to top):

  1. Unit Tests
  2. Service Tests
  3. User Interface Tests

Unfortunately the concept of the test pyramid falls a little short if
you take a closer look.
Some argue
that either the naming or some conceptual aspects of Mike
Cohn’s test pyramid are not ideal, and I have to agree. From a modern point
of view the test pyramid seems overly simplistic and can therefore be a bit

Still, due to it’s simplicity the essence of the test pyramid serves as
a good rule of thumb when it comes to establishing your own test suite.
Your best bet is to remember two things from Cohn’s original test pyramid:

  1. Write tests with different granularity
  2. The more high-level you get the fewer tests you should have

Stick to the pyramid shape to come up with a healthy, fast and
maintainable test suite: Write lots of small and fast unit
. Write some more coarse-grained tests and very few
high-level tests that test your application from end to end. Watch out that
you don’t end up with a
test ice-cream cone
that will be a nightmare to maintain and takes
way too long to run.

Don’t become too attached to the names of the individual layers in Cohn’s
test pyramid. In fact they can be quite misleading: service test is a
term that is hard to grasp (Cohn himself talks about the observation that

a lot of developers completely ignore this layer
). In the days of
single page application frameworks like react, angular, ember.js and others
it becomes apparent that UI tests don’t have to be on the highest
level of your pyramid – you’re perfectly able to unit test your UI in all
of these frameworks.

Given the shortcomings of the original names it’s totally okay to come
up with other names for your test layers, as long as you keep it consistent
within your codebase and your team’s discussions.

The Sample Application

I’ve written a simple
including a test
suite with tests for the different layers of the test pyramid.

The sample application shows traits of a typical microservice. It
provides a REST interface, talks to a database and fetches information from
a third-party REST service. It’s implemented in Spring Boot
and should be understandable even
if you’ve never worked with Spring Boot before.

Make sure to check
out the code on Github. The
readme contains instructions you need to run the application and its
automated tests on your machine.


The application’s functionality is simple. It
provides a REST interface with three endpoints:

GET /hello Returns “Hello World”. Always.
GET /hello/{lastname} Looks up the person with the provided last name. If the person
is known, returns “Hello {Firstname} {Lastname}”.
GET /weather Returns the current weather conditions for Hamburg,

High-level Structure

On a high-level the system has the
following structure:

- testService - The Practical Test Pyramid

Figure 3: the high level structure of our microservice system

Our microservice provides a REST interface that can be called via HTTP.
For some endpoints the service will fetch information from a database. In
other cases the service will call an external weather
via HTTP to fetch and display current weather

Internal Architecture

Internally, the Spring Service has a Spring-typical architecture:

- testArchitecture - The Practical Test Pyramid

Figure 4: the internal structure of our microservice

  • Controller classes provide REST endpoints and deal with HTTP
    requests and responses
  • Repository classes interface with the database and take care of
    writing and reading to/from persistent storage
  • Client classes talk to other APIs, in our case it fetches JSON
    via HTTPS from the weather API
  • Domain classes capture our domain model including
    the domain logic (which, to be fair, is quite trivial in our case).

Experienced Spring developers might notice that a frequently used layer
is missing here: Inspired by Domain-Driven
a lot of developers build a service layer consisting of
service classes. I decided not to include a service layer in this
application. One reason is that our application is simple enough, a
service layer would have been an unnecessary level of indirection. The
other one is that I think people overdo it with service layers. I often
encounter codebases where the entire business logic is captured within
service classes. The domain model becomes merely a layer for data, not for
behaviour (an
Anemic Domain Model
). For every non-trivial application this wastes a lot of
potential to keep your code well-structured and testable and does not
fully utilize the of object orientation.

Our repositories are straightforward and provide simple
functionality. To keep the
code simple I used Spring Data.
Spring Data gives us a simple and generic CRUD repository implementation
that we can use instead of rolling our own. It also takes care of spinning
up an in-memory database for our tests instead of using a real PostgreSQL
database as it would in production.

Take a look at the codebase and make yourself familiar with the
internal structure. It will be useful for our next step: Testing the

We’re releasing this article in installments. Future installments will look at
the different kinds of tests you need, starting with unit tests..

To find out when we publish the next installment subscribe to the
site’s RSS feed, Ham’s twitter stream, or Martin’s twitter stream


Thanks to Clare Sudbery, Chris Ford, Martha Rohte, Andrew Jones-Weiss David Swallow, Aiko Klostermann, Bastian Stein and Sebastian Roidl for providing feedback and suggestions to early drafts of this article. Thanks to Martin Fowler for his advice, insights and support.

For articles on similar topics…

…take a look at the tag: testing

Source link


Please enter your comment!
Please enter your name here