An example contract repository to facilitate consumer-driven contract testing, also using Specification by Example with Gauge, along with OpenAPI and Prism.
See also the companion consumer web app and provider Java microservice, which this contact repo represents the contract between.
Read the README in the consumer app first, as this gives the all-important consumer-driven perspective. Then come back here and read the description below of the workflow from the contract perspective.
-
After using Specification by Example to drive their specification of a new feature (the ability to show which pets are newly in the petstore, in our notional example), the consumer creates a feature branch in our contract repo and modifies the OpenAPI spec with their proposed change, i.e. adding
new
to the list of defined statuses:enum: - available - pending - sold - new
-
The consumer also adds a specification on this contract repo, e.g.
## Customers can see which pets are new in the pet store * There is a pet named "doggie" new in the pet store
Note that this spec is identical to the spec which the consumer also created in their consumer repo. This is a good thing as it describes the same consistent API contract in both the consumer and the contract repos (it's not a disaster if the specs have slightly different wording due to step implementation differences, but it's a good goal to keep them the same or as close to the same as possible).
The consumer team should go ahead and add the step implementation for this spec. The step implementation on the contract repo is a black-box API test using Prism, so implementing it does not require any knowledge of the internals of the provider application. The contract repo is jointly owned by the consumer and the provider. This is a nice instance of using innersource principles. When the consumer is driving the change (which is the case in our example here and also what we want to happen, normally), then it's natural that the consumer should also update the contract (including the Gauge spec and step implementation as well as the OpenAPI spec).
Have a look at the
new-pets-status
branch and you can see these changes added by the consumer in the most recent commits there.Let's look more closely at how Prism is helping us here. Prism is a mock server that effortlessly serves example responses based just on our OpenAPI spec. All it needs is the OpenAPI spec, nothing more, nothing less. That's very powerful.
-
So the provider can now go ahead and make the necessary changes to their microservice.
- Collaborative - consumers, solution architects, developers, testers, analysts, Product Owner all have a natural interest in being involved. This is a great silo breaker.
- Shift Left - enables testing of APIs before implementation has started
- Speeds up and improves service consumer and provider integration: provides API consumers with a working mocked example of the API that they can integrate straightaway.
- Design-first APIs
- Specification by Example
- Shared understanding between all parties
- Living documentation, providing a single source of truth. This API documentation stays up to date because it is executable, and is only written in one place (rather than analysts, developers and testers all writing their own separate documentation.)
- API black box testing
- provides great test coverage
- decoupled from implementation, so does not get in the way of implementation
- Consumer-Driven-Contract-Testing
- allows service design to be driven by the verified needs of consumers
- ensures that consumer test stubs stay in sync with the implementation
- Enables different languages to be used easily - can choose Python for the contract tests and Java for the API implementation, for instance
prism mock openapi.yaml
gauge run --env mock specs
prism proxy openapi.yaml https://petstore.swagger.io/v2
gauge run --env validation-proxy specs
gauge run specs