Contract Tests
Tags: tdd, unittests, testing, softwaredesign
Published: 2023-02-01 09:54:49

One of my favorite [awesome talks](https://github.com/JanVanRyswyck/awesome-talks) of all time is [Integrated Tests Are a Scam](https://vimeo.com/80533536)  by J.B. Rainsberger. I must admit that the title has a clickbait vibe to it. However, I very much recommend watching the video.

So what’s the deal with integrated tests? Why should they be considered as a scam? First of all, let’s clarify what an integrated test actually is. An integrated test is a high-level test that exercises multiple different behaviours of the system all together in one go. At first glance this doesn’t sound like a huge problem. We need tests like that, don’t we? Well, it kind of depends on the audience of the integrated test.

Remember from my previous post about the [Testing Quadrant](https://principal-it.eu/2022/06/testing-quadrant/), that there are two quadrants of tests that support the team:

- Developer tests: this is the quadrant where the [Test Pyramid](https://principal-it.eu/2019/11/test-pyramid/) resides.
- Functional tests: these are the kind of tests, as described by Behaviour-Driven Development (BDD) or Acceptance Test-Driven Development (ATDD), that prove to business stakeholders that certain features are available in the system.

![The testing quadrant and the testing pyramid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/faj1817um0wggp73eudb.png)

When it comes to using integrated “functional” tests for providing the necessary confidence to business stakeholders, there’s not much of a problem there. Such tests often do require different parts of the system working together to provide the requested capabilities.

However, an issue arises when software developers start using integrated “developer” tests for proving the correctness of the system. So why do such integrated tests become an issue in this situation? For all the same reasons as when having too much Sociable tests:

- They can be grudgingly slow.
- They are quite often very non-deterministic. This undermines trust and confidence.
- They are overly verbose as they require a lot of code to set up the system under test. This requires a serious investment when it comes to time and effort.
- They don’t provide useful feedback about the design of the system.
- They are highly susceptible to [cascading failures](https://principal-it.eu/2020/03/cascading-failures/).

Therefore, my advice, ad nauseam, is to adhere to the Test Pyramid as it’s still a highly valuable model to think about when it comes to the developer tests quadrant.

What about integration tests? Are those a scam as well? It kind of depends on how you use them. An integration test, as opposed to an integrated test, only verifies whether the different components for a single path running through the system correctly work together. If a sociable test is used for that purpose alone, then things are just fine. However, troubles usually start appearing the moment software developers decide to start using Sociable tests, or even worse integrated tests, as the sole means to verify correctness of the system at the expense of Solitary tests.

> “ Strong integration tests, consisting of collaboration tests (clients using test doubles in place of collaborating services) and contract tests (showing that service implementations correctly behave the way clients expect) can provide the same level of confidence as integrated tests at a lower total cost of maintenance.

 _— J.B. Rainsberger - [Clearing Up the Integrated Tests Scam](https://blog.thecodewhisperer.com/permalink/clearing-up-the-integrated-tests-scam)_

What J.B. suggests here is the use of contract tests for exercising those parts of the application that cross the process boundary to communicate with other parts of the system like a database, a queue, the file system, etc. … The purpose of a [contract test](https://martinfowler.com/bliki/ContractTest.html) is to verify whether an adapter for a collaborating service correctly implements a particular interface. This implies that the same suite of tests verifies the outside-observable behaviour of both the real implementation and a fake implementation.

![A general overview of the concept of contract tests](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pjkp1akr3aq22k6f7bgz.png)

In the context of an [hexagonal architecture](https://alistair.cockburn.us/hexagonal-architecture/), this suite of contract tests ensures that the fake adapter behaves exactly the same as the real adapter. We can then use this fake implementation for Sociable “integration” tests that verify whether the different components of the application correctly work together.


In [the next post](https://principal-it.eu/2023/04/contract-tests-abstract-test-cases/) we’ll discuss how to approach contract tests from a practical point of view. In the meantime, you can check out the [Integrated Tests Are a Scam blog series](https://blog.thecodewhisperer.com/series#integrated-tests-are-a-scam) to learn more first-hand.