Magic of Consumer Driven Testing
Today’s world is changing rapidly. Companies are trying to adopt more and more digital channels to cater to consumer. Which encourage them to release products as soon as they can.
Competition is high and to ‘be first’ in the market is always the prime objective with less compromises. This ambition promoted the adoption of microservices. The changes were drastic, not only in the digital world but also the mindset of companies who were very traditional in their approach and have a very big gap between releases, now turning their approach and getting lean when it comes to delivery.
Microservices a revolution?
Since 2016, developers have become more productive by focusing on one service at a time. What’s a “service”? Roughly, it’s the smallest useful piece of software that can be defined simply and deployed independently. Think of a notification service, a login service, or a persistent key-value storage service. A well-built service does just one thing, and it does it well. Developers now move faster because they don’t worry about virtual machines or other low-level infrastructure: services raise the level of abstraction. (Yet another buzzword: this was called serverless computing for a while.) And because the connections between services are explicit, developers are also freed from thinking about the application as a whole and can instead concentrate on their own features and on the services they depend on.
A new approach to micro-“services”
Services are now an everyday, every-developer way of thinking, in part because of this toolkit. But the revolution really happened when developers started thinking about services first and foremost while building their software. Just as test-driven development meant that developers started thinking about testing before writing their first lines of code, service-driven development meant that service dependencies, performance instrumentation, and RPC contexts became day-one concerns (and not just issues to be papered over later).
Overall, services (“micro” or otherwise) have been a good thing. (We don’t need to say “microservices” anymore since, in retrospect, it was never the size of the services that mattered: it was the connections and the relationships between them.) Services have re-centered the conversation of software development around features and enabled developers to work more quickly and more independently to do what really matters: delivering value to users.
What is the best way to Test microservice?
With time, testing services has changed a lot, “Contract testing” a new consumer driven contract testing is way of looking at developing a reliable service-oriented architecture.
As an application evolves, code changes often result in side effects. These could be schema change of core application models, change in values in each respective fields, or changes that resulting in a different side effect for your application. In a monolithic application, good unit tests and integration tests would catch breaking modifications. However, unit tests and integration tests simply aren’t enough for microservices. Often, services are maintained by different teams. The more teams there are the more changes that can occur on any data schema i.e. events sent between services, and the higher the chance that breaking changes can happen. This is where contract tests shine.
Contract testing first and foremost is a design pattern for testing that does NOT require frameworks to create! A lot of the time developers would look for frameworks or tools to create tests, but contract tests are not restricted to a particular language and do not require additional tools or frameworks.
Recommended by LinkedIn
Contract tests can be thought of as integration tests between services that depend on each other. These tests ensure the link between a service providing some functionality (producer) and the service (consumer) which depends on these functions is not broken. This can be an HTTP endpoint for which consumers call on or producers produce an event that the consumer consumes. In this article, we are focusing on contract testing for “asynchronous” flows (producers produce an event that the consumers later consume). By no means are contract tests end-to-end testing of your entire application. Instead, they will test and guarantee parts of your application are working correctly by probing parts of your application, and they are meant to be faster than end-to-end testing!
Pillars of Contract Testing!
A major advantage of this process being Consumer driven is that only the parts of the communication actually being used by the Consumer get tested. This therefore means that any Provider behaviour not being used by a Consumer can be changed without causing test failures. The picture below is a visual representation of Consumer Driven Contract Testing.
As part of the Consumer pipeline, a test is run using a mock Provider and asserts against a mock response. (The mock provider can either be configured using tools like Pact if that’s your CDCT of choice, or just whatever mocking library you might already use for your other tests). Through this, the Consumer is essentially defining the contract they expect the Provider to fulfil. On the Provider side, a test is also executed as part of the pipeline which verifies the contract defined by the Consumer against the real response — any differences will indicate a broken contract, which should prompt both teams to investigate the failure.
It’s important to remember that these tests should not replace functional tests of the Provider or the Consumer, and should not be looking to test functionality of either service in any way. It is purely designed to test for broken contracts.
One clear benefit of Consumer Driven Contract Testing is the collaborative nature and behaviours that are instilled. It is at the very least, a great excuse for teams to be communicating in this way about the contracts that exist between their services. It can form a really valuable part of initial design conversations between teams, and can be seen to add value before tests have already started running.
There are a few recommendations I’d offer to anyone looking to use Pact or any similar CDCT framework:
demonstrate the framework and the benefits will be critical in getting the go-ahead for implementing.
As with any new testing tools, find a way to prove the concept and show others a working example!