Integration testing has an important role in the test pyramid, it aims to test the integrations of the software products in the integration environments. This means that the software should be built and deployed to an integration test environment and then run the test against the version in the testing environment. If anything wrong occurs as a regression issue then the CI gives feedback about the failures. As a result, the issue should be fixed and built and deployed to the integration test environment. Therefore this process is very expensive and is so late for the modern approach to SDLC, for the shift-left approach. As a solution to this problem, we should consider testing the integration isolatedly within the context of the software itself. Contract testing is an approach to testing the integration depending on the written contract during the build phase. In this post, I want to explain the importance of contract testing.
What is Contract
The contract is a document created by the consumers to list the required functionalities that are used by the consumers. Therefore, the consumer should create a contract for every change in the requirements then, it should be shared with the providers to follow the up-to-date contracts.
What is Contract Testing
Contract testing is testing the integrations of the applications in isolation so is complimentary to integration testing with some extra benefits. Contract testing has a very important role in the software development lifecycle as a good approach to making the integration testing shift left. The contract is a document created by the consumers to list the required functionalities that are used by the consumers. Therefore the contract should be created by the consumer for every change in the requirements then it should be shared with the providers to follow the up-to-date contracts.
There is a misunderstanding about the contract test is rewriting the unit tests against a mock service. But in reality, it is not as simple as this definition since it is bi-directional and it checks the requirement as well as the implementation in build time. The following image also shows where is the contract test in the test matrix. The contract test is basically non-functional testing at the integration level. It is non-functional because we are not aiming to check logic or consumer flows, and also it is checking the integration of the services/APIs so it is an integration level testing.
What is the Problem with Classical Integration Testing
An integration testing project is mostly a project that checks the integration of microservices/services/APIs with some libraries like rest-assured, requests, airbone, etc. Most of the time this project is contributed by the quality team by writing tests for each requirement as soon as the related requirements are turned into functionalities in the product. This is an asynchronous process which means development teams do their jobs and the quality team does their job separately. This causes isolation instead of integration. This is not only done by doing the job but also by running and reporting the results of the tests.
Everyone will be happy until there is a failure in the result of the integration test run. When an error is caught, a hero should be chosen and take responsibility and start investigating the issue. There might have already been changes in the requirement or there is an intermittent issue, so this is most of the time a time-consuming job. Also, there will be job failures until the issue is fixed which will reduce the reliability of the integration test.
Basically, these are the problems of the integration testing:
- Flakiness
- Data management for each MSs and APIs
- Testing different MSs in the same test
- Slow
- Requires network
- Data creation process
- Network calls between MSs
- Independent from Clients
- Tests are not created by clients
- Updates are not made by clients
- Testing more general instead of the client's requirements