Consumer Driven Contracts (DDD Perth 2016)

Preview:

Citation preview

Consumer Driven ContractsSay what you mean and mean what you say

@robdcrowley

robdcrowley

Session Goals

Learn how consumer driven contracts facilitate a low friction approach to service evolution

Explore how Pact enables service providers to know if a change would break consumers before deploying

Consumer driven contracts as a catalyst for cultural change

Empower you with innovative ideas to bring back to your organisation!

Digital disruption is driving change across established industries

The agility to respond to rapidly changing customer needs is vital for remaining competitive

Software architecture must also become more agile

Modern Architectures are Complex

Service

Service

Service

Service Service

Service

Service Service

Service

Service

Service

Client

Client

Client

Service

Service

Service

Service

Some people, when confronted with a problem, think “I know, I'll use system integration tests.” Now their

problems scale combinatorially.

Combinatorial Scaling2 code paths: 26 = 64

4 code paths: 46 = 4096

6 code paths: 66 = 46656

8 code paths: 86 = 262144

Service

Service

Service

Service Service

Service

Service

Service

Service

Service

Service

Service

Client

Client

Client

“Reliability problems largely occur at module boundaries, and most result from inconsistencies in both sides expectations”

- Bertrand Meyer, Object Success

Implicit InterfacesNo explicit interface between collaborators enforced by type system or compiler checks

Service

Service

Service

Service Service

Service

Service

Service

Service

Service

Service

Service

Client

Client

Client

Implicit InterfacesNo explicit interface between collaborators enforced by type system or compiler checks

Let’s change and deploy a service

Service

Service

Service

Service Service

Service

Service

Service

Service

Service

Service

Service

Client

Client

Client

Implicit InterfacesNo explicit interface between collaborators enforced by type system or compiler checks

Let’s change and deploy a service

Hope we don’t break existing collaborators

Service

Service

Service

Service Service

Service

Service

Service

Service

Service

Service

Service

Client

Client

Client

Integration Tests

Slow (longer feedback cycle)

Brittle

Difficult to manage

Finding the actual issue requires triage

Scale combinatorially

Written after the code rather than before

So if integration tests are not the solution then what is?

So if integration tests are not the solution then what is?

Test Symmetry

symmetrys m tri/ˈ ɪ ɪnoun

The correspondence of the form and arrangement of elements or parts on opposite

sides of a dividing line.

Test Symmetry

A B

A B

Mock

Test Symmetry

A B

MockTrivial

Test Symmetry

A B

MockTrivial Tricky

Test Symmetry

Symmetrical tests have the exact opposite properties

Pactwww.pact.io

Know when you break a consumer before deploying the change

Specification by Example

Pact – Define Expectations

Consumer Provider

PACT

HTTP Request

HTTP Response

Record

Pact – Verify Expectations

Consumer Provider

PACT

HTTP Request

HTTP Response

Replay

Fast (rapid feedback cycle)

Reliable

Low ramp up cost

Straightforward to debug

Scale linearly

Contract Tests

Given ”products exists”Upon receiving ”a GET request for product catalogue”

With “an Accept header of application/hal+json”Will respond with ”200 OK”

And “a Content-Type header of application/hal+json”And ”the product catalogue details in the entity body”

Given ”products exists”Upon receiving ”a GET request for product catalogue”

With “an Accept header of text/plain”Will respond with ”406 Not Acceptable”

Given ”Widget product does not exist”Upon receiving ”a GET request for Widget product”

Will respond with ”404 Not Found”

Examples

Joining the dots...

ProductSales

Service

ProductCatalogue

Service

ProductStock

Service

PactBroker

git clone https://github.com/robcrowley/microservices-pact-demo.git

JUnit for pact generation

Gradle pact plugin for provider verification

Pact Broker for pact repository

Docker integration

Start with the consumer

Then move onto the provider

“Be liberal in what you accept, and conservative in what you send”

- Jon Postel, The Robustness Principle

Implications of Postel’s Law

An expectation may not be made for a field to be absent from a response

Exception: Request headers that change the behaviour of the provider must be specified in expectations

Sharing Pacts

Pact Broker

Consumer Provider

Pact Broker

Pact Broker

Consumer Provider

Pact BrokerPublish

PUT /pacts/provider/{provider}/consumer/{consumer}/versions/{version} HTTP/1.1

Pact Broker

Consumer Provider

Pact BrokerPublish

PUT /pacts/provider/{provider}/consumer/{consumer}/versions/{version} HTTP/1.1

Pull

GET /pacts/provider/{provider}/consumer/{consumer}/latest HTTP/1.1

Facilitates the sharing of pacts between consumer and provider projects

Enables service release cycles to be decoupled

Example driven API documentation

Visualisations of relationships between services

Web Hooks to provide integration with CI Builds

Pact Broker

Backwards Compatibility TestingUse Tags to ensure provider is compatible with latest and released versions of consumers

PUT /participants/{consumer}/versions/{version}/tags/{tag} HTTP/1.1

GET /pacts/provider/{provider}/consumer/{consumer}/latest/{tag} HTTP/1.1

Consumer Head (Pact Broker)

Consumer Production(Pact Broker)

Provider Head(Source Control)

Contract TestsContract Tests

Producer backwards compatibility

Provider Production(Source Control)

Contract TestsConsumer backwards

compatibilityAlready Tested

So once contract tests are in place I can throw all of my integration tests away?

It depends on the criticality of the business capability the service supports and your risk appetite

Make production monitoring and alerting a priority

Other Benefits

Higher quality services

“Quality comes from deliberate thought”

- Michael Feathers, Testing Patience

Reduced waste in delivery process

The business value realized by a service is defined by the parts of it’s provider contract being leveraged

by consumers

“The biggest cause of failure in software-intensive systems is not technical failure; it’s

building the wrong thing.”

- Mary Poppendieck

Focusing on delivering the capabilities as defined in consumer contracts drives building the right thing

TakeawaysConsumer Driven Contracts enable services to evolve gracefully

Pact combines isolated unit testing with contract testing

Pact enables delivery at speed by providing rapid feedback on potential breakages

Pact allows test driven development principles to be applied to services

Consumer Driven Contracts can be a catalyst for cultural change by fostering collaboration between delivery teams and reducing waste

“Deploying to production quickly is easy; doing so quickly and responsibly

however is non trivial”

- Rob Crowley

Adopting a consumer driven contract testing approach can help

Questions

More Info

Gitbook: docs.pact.io

Github: realestate-com-au/pact and DiUS/pact-jvm

User group: https://groups.google.com/forum/#!forum/pact-support

Twitter: pact_up

Pact to the Rescue!: http://www.slideshare.net/bethesque/pact-44565612

Deploy with Confidence using Pact Go!: https://www.youtube.com/watch?v=SMadH_ALLII

Consumer Driven Contracts – A Service Evolution Pattern: http://martinfowler.com/articles/consumerDrivenContracts.html

Appendices

Contracts 101

Provider Consumer DrivenConsumer

Closed & Complete

Singular & Authoritive

Bounded Stability &Immutability

Open & Incomplete

Mutable & Non-Authoritive

Bounded Stability &Immutability

Closed & Complete

Singular & Non-Authoritive

Bounded Stability &Immutability

Recommended