Contract testing is a method for verifying system integration by individually examining each application to ensure that contracts and interfaces adhere to the agreed-upon alignment. A mock integration point enables the validation of a component’s expected behavior without reliance on that component.
In the case of a large and intricate application, it may be necessary to establish an integration point trusted by multiple applications. This trusted integration point’s behaviors are validated by all dependent applications, preventing inadvertent or malicious changes from impacting the entire system.
Thus, a system can be constructed in which each component performs a specific task, safeguarding the system against accidental or malicious alterations to any of its components.
Contract testing is a method for verifying system integration by individually examining each application to ensure that contracts and interfaces adhere to the agreed-upon alignment. A mock integration point enables the validation of a component’s expected behavior without reliance on that component.
In the case of a large and intricate application, it may be necessary to establish an integration point trusted by multiple applications. This trusted integration point’s behaviors are validated by all dependent applications, preventing inadvertent or malicious changes from impacting the entire system.
Thus, a system can be constructed in which each component performs a specific task, safeguarding the system against accidental or malicious alterations to any of its components.
Why opt for contract testing? What are the advantages of this approach?
Contract testing is an excellent technique for:
Identifying irregularities in consumer workflows and addressing them early on
Detecting service configuration defects that may impact inter-application communication
Ensuring secure connections even when producers make changes to service configurations, providing guarantees to data consumers
Allowing producers to perform their tasks without disrupting the consumer’s workflow, which is also beneficial for regression testing
Giving consumers the flexibility to specify their requirements and consume only what they need
Preventing unexpected API communication failures due to local or mock implementations, resulting in more stable, faster, and reliable testing of the application
Rapidly detecting and resolving issues
When is contract testing not the best choice?
It’s important to consider both sides of the coin before making a decision.
Here are the main reasons why contract testing may not be suitable:
Contract tests are not a replacement for Unit or Functional (component) tests
Contract tests are not intended to substitute for any other type of testing
If there is little or no communication between teams where contract tests are being set up, this can result in a stale contract that should not be trusted or relied upon
Simply adding contract tests as another layer of test coverage or because it’s a new and trendy technique will not provide any value to your test flows
Before making any decisions, it’s important to evaluate the business value, estimated time of arrival for implementation, and consider the minimum viable product that can be provided and presented. It’s also worth noting that integrating new features or tools requires workshops to onboard teams and users.
Where do contract tests fit within the testing pyramid?
To gain a better understanding, let’s examine the following table:
Aspec
Unit
Contract
API
Way to execute
local
local
environment
Feedback time
fast
medium
slow
Setup complexity
low
medium
high
Cross-team collaboration
no
yes
yes
What tools are available for contract testing? What are my options?
There are a limited number of battle-tested and production-ready tools available for implementing contract testing.
Here is a brief overview of what each tool offers to help you make an informed decision:
Aspect
Pact
Spring Cloud Contract
Deployment / Administration / Hosting
- Pactflow - paid - Broker - free and open source but you need to host it and maintain it
- uses artifactory
Supported languages
- JS, JVM, Net, Go, Python, Swift, Scala, PHP, Ruby, Rust, C++ - Keep in mind that there are some limitations for specific languages. Meaning that some languages have more features than others
- By default only JVM based languages - To support other languages you need to use docker image that will download the required contracts from artifactory and expose the endpoints from the image to your service
Supported languages for writing contracts
- It is optimized for use with "pacts" (contracts created by the Pact framework) but can be used for any type of contract that can be serialized to JSON
- Groovy - Kotlin DSL - Java - YAML
Message types support
- REST API contracts - Async communication - Pact v3 (no offical support for Python)
- REST API contracts - Async communication via Wiremock
What are the default approaches or workflows used by each tool and how do they differ?
Let’s examine how producer-driven contract testing is implemented:
In a producer-driven approach, the producer generates contracts and shares them with consumers.
Now, let’s delve deeper into how the Spring Cloud Contract tool operates and what happens behind the scenes:
Now, let’s examine the workflow for consumer-driven contract testing:
The following image provides a visual representation of how Pact operates:
What are the steps involved in creating a new contract?
Add new contract
Add new contract to repository
Review contract
Implement consumer-side tests
Implement producer-side tests
Merge contract and tests
Updating an existing contract
Updating the contract in the repository
Reviewing the updated contract
Applying changes to each consumer and producer
Merging updated contract and changes
When should contract tests be executed?
Integration into the development pipeline includes:
Build phase: build code and generate contracts
Test phase: perform unit, integration, contract, and other automated tests in parallel. Consider a backup plan for quick production deployment during incidents.
Deploy to production
Conclusion
This article explains what contract testing is, its advantages and disadvantages, and how to make informed decisions.
Next Steps
Let’s explore building a highly scalable solution using GitHub or GitLab pipelines.