Contract Testing Fundamentals

Anshul Mathur
TestVagrant
Published in
5 min readMay 22, 2020
source: https://www.google.com

Me — “Hey! I need a table to keep my laptop. The size shall be 4x4 and I must receive it within next 3 days. I’ll make the complete payment only when my table needs are satisfied”

My Carpenter — “Sure. I will construct the table accordingly and deliver it on time.”

Simple conversation, right? Well, let’s understand what just happened!

What we read is an agreement happening between me and my carpenter. While consumer(me) had an expectation of using a table to place laptop within a 3 day timeline, producer(carpenter) needs to manufacture the table while abiding by the agreed clauses. This verbal agreement, if given a formal shape & significance, can be referred to as a contract.

Defining a Contract

Contract, in general, is a mutually agreed set of clauses between 2 or more parties for sharing of resources — one(or more) party provides the resource while one(or more) party consumes it.

Considering the above definition, let’s understand contracts from a technical perspective.

Imagine a system having 2 components — a service that returns some information from an underlying datasource (known as provider) and another service that process it based on certain business rules(knowns as consumer). The consumer, evidently, is dependent on provider to return information in a certain format which it understands and can process. This implies that unless the provider is ready with the APIs to return back the data, consumer have to keep waiting to start its own development. This would make development a lot slower.

The best way to solve the above dependency is by creating and sharing a contract between both service teams. The contract would define rules for creating requests and accepting responses that can be used by teams for development — making them independent.

The teams would benchmark information structure & exchange mechanism upfront, share them with each other through a contract and abide by it throughout the development lifespans. This contract would be a rule based document that defines possible requests from a consumer and potential response formats from a provider, hence restricting any team from adding code that may break the contract.

With advent of contract comes in the testing aspect. So, let’s unfold the concept of contract testing.

Contract Testing

  • Validating whether a provider & a consumer abides by the contract during their development activities
  • Focus on the structure of messages that flow between the parties
  • Provides quick & early feedback on critical points that may obstruct integration between consumer and provider

Contract Testing vs Functional Testing

Note: The above differences are put up in the context of services that exposes and utilises data through APIs. However, same differences may largely be relevant to all kinds of components.

When to do Contract Testing?

  1. When multiple dependent components are developed in parallel
  2. When a clear contract definition can be created and agreed upon before development starts

Where does Contract Testing Fit?

With almost every software release being managed in a devOps mode today, it becomes crucial to invoke contract testing early and continuously in the cycle(just like other forms of testing).

Contract testing would be placed right after the unit testing stage and should notify breaking changes before testing the service functionality. This way, teams would save a lot of effort & time on doing functional testing for API versions that aren’t even consumable!

Now that we’re good with the concept of contract testing, let’s move the focus to a flavour of it that has become an industry standard and is widely used across software product teams — known as Consumer driven contract testing.

Consumer Driven Contract Testing (CDCT)

  • Consumers lay down expectations from a provider in form of a contract file
  • Consumer emphasises only on the entities(and their structure) it would consume from the provider API
  • Providers needs to validate the contract with every new code push from either side
  • Consumers get notified on any breaking change introduced at any point in the API
source: https://www.google.com

Workflow for a CDCT strategy

  1. Consumer would publish the contracts based on their expectation by using a mock provider and running tests against it
  2. Provider replays contract against the real service and publishes results to inform consumer on the status
  3. Consumer would deploy only when the latest contract version is successfully verified by the available provider

Benefits of a CDCT strategy

  • Gives confidence to service consumers for going ahead with their deployments after successful verification of the contract they own
  • Gives confidence to service providers to go ahead with their deployments after successful verification of the contract and that their changes doesn’t break any dependent clients
  • Catch breaking contract changes very early in the cycle — even before testing the behaviours
  • Ensures that evolving versions of different components of a system can consistently interact with each other
  • Allows provider to take informed decisions w.r.t. making code changes on their end
  • Since consumers drive this strategy, it frees up provider from maintaining multiple contracts together(as it would, usually, be serving multiple consumers) and reduces friction that otherwise would creep in due to duplicate/repeated efforts from provider end

Conclusion & Next Steps

Contract testing makes teams go independent & faster in developing new features while keeping their core interactions intact. Agile teams do realise that consumer driven contract testing is very handy & valuable in multi-component architectures. With an ever-evolving role of a QA having reached to the levels of development, it is important for QA folks to start(kudos! if already started) contributing at this layer of testing and raise the quality bar.

Next, I’ll share a blog post with details on PACT, a tool that helps imbibe consumer driven contract testing within the product development cycle and provides an easy way of writing & running contract tests. Stay tuned!

Happy Testing!!!

--

--