Slide 1

Slide 1 text

Consumer Driven Contracts Testing “Design your api differently”

Slide 2

Slide 2 text

In a microservices world, how do you deal with testing?

Slide 3

Slide 3 text

How to confirm all services are working together?

Slide 4

Slide 4 text

How to write a test for it ? Client Api Request Response

Slide 5

Slide 5 text

Mocking !!! Client Api Request Response Mock or Stub

Slide 6

Slide 6 text

Problems •What happens if there is a change in the real producer ? •The owner of the mock is the consumer •Not trustworthy

Slide 7

Slide 7 text

Client Mock or Stub Api Test Real world Mocking !!! Request Response The mock has nothing to do with the real API Client Real Service Api Request Response

Slide 8

Slide 8 text

How can we be sure that the mocks are valid?

Slide 9

Slide 9 text

END TO END TESTS Client REAL api Request Response

Slide 10

Slide 10 text

Problems •Slow •All services need to be up before running the tests •Require a clean/dedicated integration environment

Slide 11

Slide 11 text

But it is trustworthy

Slide 12

Slide 12 text

Any alternative ? Could we test apis in a better way ?

Slide 13

Slide 13 text

If no cooperation

Slide 14

Slide 14 text

#Questions It’s the consumer that uses the API. Would it be possible that : ● consumer takes part in the creation of the API of the producer ? ● API changes be driven by consumers ?

Slide 15

Slide 15 text

“An integration test is a test between an API provider and an API consumer that asserts that the provider returns expected responses for a set of pre-defined requests by the consumer. The set of pre-defined requests and expected responses is called a contract.”

Slide 16

Slide 16 text

Consumer Driven Contracts

Slide 17

Slide 17 text

Glossary •Producer Service that exposes an API. •Consumer Service that consumes the API of the producer. •Contract Agreement between producer and consumer on how the API will look like. •Consumer Driven Contracts Approach where the consumer drives the changes of the API of the producer.

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

As a developer I want to confirm that the consumer (client) and the provider (service) can understand each others So that I can check they are compatibles

Slide 20

Slide 20 text

How to ? Define API contract on the consumer side. The contract must be enforced on the service provider.

Slide 21

Slide 21 text

Contract test

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Tools ?

Slide 24

Slide 24 text

https://docs.pact.io/

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

1) Start With Consumer

Slide 27

Slide 27 text

1) Start With Consumer • Write Test(S) • Define interactions / Expectations • In your favorite language

Slide 28

Slide 28 text

1) Start With Consumer • Run Tests • From Expectations TO Contract • Json File

Slide 29

Slide 29 text

2) Contract Driven Development

Slide 30

Slide 30 text

2) Contract Driven Development • Design Your API From The Contract • Write A RED Test

Slide 31

Slide 31 text

2) Contract Driven Development • Make You Test Pass / GREEN

Slide 32

Slide 32 text

• Git ? • Near from the Provider sources ? • Near from the Consumer sources ? • Any better option ? Where Could We Store Our CONTRACTS ?

Slide 33

Slide 33 text

Pact Broker ● A RESTful API for publishing and retrieving pacts. ● An embedded API browser for navigating the API. ● Displays provider verification results so you know if you can deploy safely. ● Auto-generated documentation for each pact. ● Provides a "matrix" of compatible consumer and provider versions, so you know which versions can be safely deployed together. ● Dynamically generated network diagrams so you can visualise your microservice network. ● Provides badges to display pact verification statuses in your READMEs. ● Enables an application version to be tagged (ie. "prod", "feat/customer-preferences") to allow repository-like workflows. ● Provides webhooks to trigger actions when pacts change eg. run provider build, notify a Slack channel. ● View diffs between Pact versions so you can tell what expectations have changed. ● Docker Pact Broker ● A CLI for encorporating the Pact workflow into your continuous integration process. https://github.com/pact-foundation/pact_broker

Slide 34

Slide 34 text

A RESTful API for publishing and retrieving pacts. An embedded API browser for navigating the API. Displays provider verification results so you know if you can deploy safely.

Slide 35

Slide 35 text

Auto-generated documentation for each pact. Provides a "matrix" of compatible consumer and provider versions,

Slide 36

Slide 36 text

Dynamically generated network diagrams so you can visualise your microservice network. sheriff hopper

Slide 37

Slide 37 text

A CLI for encorporating the Pact workflow into your continuous integration process. Docker Pact Broker

Slide 38

Slide 38 text

Provides webhooks to trigger actions when pacts change eg. run provider build, notify a Slack channel. https://github.com/pact-foundation/pact_broker/blob/master/lib/pact_broker/doc/views/webhooks.markdown

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

Strengths Opportunities Threats Weaknesses ● Cross-languages ● Easy integration with a pact broker ● Specification / standardization ● 2 versions of the Specification ○ 3.0 for JVM ○ 2.0 for others ● Api quality depends on the language ● Where to store the Contracts ? (if no broker) ● Yet another format (Not Open Api) ● Start easily A CDC approach ○ Only a few Jar to reference ● Design First approach Wanted ? ● Contract + Integration Tests ? https://github.com/agilepartner/pact-sandbox

Slide 41

Slide 41 text

Spring Cloud Contract Doc Spring Cloud Contract is an umbrella project holding solutions that help users in successfully implementing the Consumer Driven Contracts approach. Currently Spring Cloud Contract consists of the Spring Cloud Contract Verifier project. Spring Cloud Contract Verifier is a tool that enables Consumer Driven Contract (CDC) development of JVM-based applications. It is shipped with Contract Definition Language (DSL) written in Groovy or YAML. Spring Cloud Contract Verifier moves TDD to the level of software architecture. Contract definitions are used to produce following resources: ● by default JSON stub definitions to be used by WireMock (HTTP Server Stub) when doing integration testing on the client code (client tests). Test code must still be written by hand, test data is produced by Spring Cloud Contract Verifier. ● Messaging routes if you’re using one. We’re integrating with Spring Integration, Spring Cloud Stream and Apache Camel. You can however set your own integrations if you want to. ● Acceptance tests (by default in JUnit or Spock) used to verify if server-side implementation of the API is compliant with the contract (server tests). Full test is generated by Spring Cloud Contract Verifier.

Slide 42

Slide 42 text

1) Define The Contract

Slide 43

Slide 43 text

1) Define The Contract • Write contract in Groovy or YML • Define Expectations org.springframework.cloud.contract.spec.Contract.make { description(""" Donuts API """) label("Get all donuts") request { method GET() url '/donuts' headers { contentType(applicationJson()) } } response { status OK() body( sugar: $(regex('[0-9]+')) , flour: $(regex('[0-9]+')) , butter: $(regex('[0-9]+')) ) headers { contentType(applicationJson()) } } }

Slide 44

Slide 44 text

2) Contract Driven Development

Slide 45

Slide 45 text

2) Contract Driven Development • Design Your API From The Contract • Write A RED Test public abstract class ContractVerifierBase { @Before public void setup() { RestAssuredMockMvc.standaloneSetup(new DonutsController()); } } org.springframework.cloud.contract.spec.Contract.ma ke { description(""" Donuts API """) label("Get all donuts") request { method GET() url '/donuts' headers { contentType(applicationJson()) } } response { status OK() body( sugar: $(regex('[0-9]+')) , flour: $(regex('[0-9]+')) , butter: $(regex('[0-9]+')) ) headers { contentType(applicationJson()) } } }

Slide 46

Slide 46 text

2) Contract Driven Development • Make You Test Pass / GREEN @RestController public class DonutsController { @GetMapping(value = "/donuts", produces = "application/json") public ResponseEntity getDonuts() { return ResponseEntity.ok(Arrays.asList(new Donut(120, 150, 140))); }

Slide 47

Slide 47 text

3) Generate a stub from contract • TODO Make You Test Pass / GREEN @RestController public class DonutsController { @GetMapping(value = "/donuts", produces = "application/json") public ResponseEntity getDonuts() { return ResponseEntity.ok(Arrays.asList(new Donut(120, 150, 140))); }

Slide 48

Slide 48 text

Strengths Opportunities Threats Weaknesses ● Tests generated by the framework ● Stub generated ● Contract DSL based ● Not cross-languages ● Dependency on Spring Cloud ● Where to store the Contracts ? centralized jar ? ● Yet another format. Open API is not directly supported ● No dependency visualization ● No central repository for contract ● Start easily A CDC approach ○ Only a few Jar to reference ● Design First approach Wanted ? ● Contract + Integration Tests ? https://github.com/wilvdb/contracts-lab

Slide 49

Slide 49 text

• Git or jar ? • Near from the Provider sources ? • Near from the Consumer sources ? • Any better option ? Where Could We Store Our CONTRACTS ?

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

#Workshop ● There is no more Donuts at Springfiled, and Homer is going to be crazy if he cannot get any donuts for breakfast ● Your mission : restart the donuts factory ● https://github.com/wilvdb/contracts-lab ○ Module docker : docker-compose up ○ Module simpson-client-pact : mvn install → Load contract on pact broker ○ Module donuts-factory-pact : complete DonutsController to validate the contract

Slide 52

Slide 52 text

Apicurio Doc Apicurio Studio, maintained by the Red Hat Developer Program, is a tool for designing APIs that follows the specification without requiring the developer(s) to be intimately familiar with it. It provides a GUI for defining all aspects of the API. Ultimately, Apicurio outputs both human and machine readable documentation which complies with the latest version of the OpenAPI specification. This walkthrough covers the process of designing an API with Apicurio from start to finish, and evaluates the possibility of using Apicurio in production. Features: ● Support of OpenApi and Swagger ● Project code generation (limited support to JAX-RS for the moment ● Storage of contract on GIT ● Microcks integration (mocking and integration testing tool)

Slide 53

Slide 53 text

Microcks Doc Microcks helps providers of API and micro-services to rapidly deliver : ● A comprehensible vision of their API, exposing sample requests and responses as well as base functional rules (cases when API responds A or B or raises exceptions) ● A set of testing environments to allow API consumers or System Under Tests to use API even if implementation is not finished! ● Contract testing plans of their API, allowing them to run, record and compare contract tests run against different environments.

Slide 54

Slide 54 text

Swagger Codegen Swagger Codegen can simplify your build process by generating server stubs and client SDKs for any API, defined with the OpenAPI (formerly known as Swagger) specification, so your team can focus better on your API’s implementation and adoption. io.swagger.codegen.v3 swagger-codegen-maven-plugin generate ${project.basedir}/src/main/resources/api.yml spring ${default.package}.controller ${default.package}.model.dto ${default.package}.handler false false true true @Api(value = "pets", description = "the pets API") public interface PetsApi { @ApiOperation(value = "", nickname = "addPet", notes = "Creates a new pet in the store. Duplicates are allowed", response = Pet.class, tags={ }) @ApiResponses(value = { @ApiResponse(code = 200, message = "pet response", response = Pet.class), @ApiResponse(code = 200, message = "unexpected error", response = Error.class) }) @RequestMapping(value = "/pets", produces = { "application/json" }, consumes = { "application/json" }, method = RequestMethod.POST) default ResponseEntity addPet(@ApiParam(value = "Pet to add to the store" ,required=true ) @Valid @RequestBody NewPet body) {...}

Slide 55

Slide 55 text

NEXT STEPS ?

Slide 56

Slide 56 text

#resources 7 reasons for consumer driven contracts Spring Cloud Contract meet Pact Consumer driven contract testing using pact