Magic of Consumer Driven Testing

No alt text provided for this image

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.

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!

  • Events — Data resulting from an action or activity that is generated by one service and meant to be sent/consumed by other services
  • Producers — Services Emitting events
  • Broker — Intermediate service that holds emitted events and provides them to consumers
  • Consumers — Services Consuming events
  • If you are unfamiliar with the concept of Consumer Driven Contract Testing, then I recommend to read the below article.

https://www.martinfowler.com/articles/consumerDrivenContracts.html

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.

Conceptual diagram of how Consumer Driven Contract Testing works

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:

  • Consider your tests very carefully — think about what sort of breaks in a contract you’d like this to catch, but try very hard not to end up blurring into functional scenarios. These should be covered elsewhere and should not replace functional testing of your service.
  • Keep tests as data-independent as possible — Make use of the Pact DSL and pattern matching as much as possible to avoid brittle tests.
  • Work together on both sides of the test — we found that where the Consumer and Provider were two separate teams, the process was most successful when we paired on both sets of tests and everyone had a full understanding of the expectations. It’s also particularly important to collaborate where introducing these tests could cause a breakage in another team’s pipeline. Good communication is key!
  • Education is really important — this is a very new concept to a lot of people who are used to writing end-to-end tests as a way to feel confident in their integrations. It’s a relatively complex topic for anyone who hasn’t come across it before, and finding the best way to

    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!

To view or add a comment, sign in

More articles by shaibal chakraborty

  • Your AI Is Guessing. RAG Fixes That

    Most AI systems have a dirty secret: when they don't know something, they make it up. It's called hallucination — and…

    1 Comment
  • Short Story - A Journey through Test-Driven Development

    Once upon a time in the bustling world of software development, there was a team that embarked on a unique adventure…

  • Be a "Agile" Tester !

    What is a Agile Tester? Automation is a critical component of software development to maintain agility. Best agile…

    1 Comment

Others also viewed

Explore content categories