Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Consumer Driven Contract Testing workshop

Yoan
August 14, 2019

Consumer Driven Contract Testing workshop

Created with Wilfried Vandenberghe.

Yoan

August 14, 2019
Tweet

More Decks by Yoan

Other Decks in Technology

Transcript

  1. Problems •What happens if there is a change in the

    real producer ? •The owner of the mock is the consumer •Not trustworthy
  2. 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
  3. Problems •Slow •All services need to be up before running

    the tests •Require a clean/dedicated integration environment
  4. #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 ?
  5. “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.”
  6. 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.
  7. 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
  8. How to ? Define API contract on the consumer side.

    The contract must be enforced on the service provider.
  9. 1) Start With Consumer • Write Test(S) • Define interactions

    / Expectations • In your favorite language
  10. • Git ? • Near from the Provider sources ?

    • Near from the Consumer sources ? • Any better option ? Where Could We Store Our CONTRACTS ?
  11. 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
  12. 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.
  13. A CLI for encorporating the Pact workflow into your continuous

    integration process. Docker Pact Broker
  14. 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
  15. 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
  16. 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.
  17. 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()) } } }
  18. 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()) } } }
  19. 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))); }
  20. 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))); }
  21. 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
  22. • Git or jar ? • Near from the Provider

    sources ? • Near from the Consumer sources ? • Any better option ? Where Could We Store Our CONTRACTS ?
  23. #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
  24. 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)
  25. 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.
  26. 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. <plugin> <groupId>io.swagger.codegen.v3</groupId> <artifactId>swagger-codegen-maven-plugin</artifactId> <executions><execution> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec>${project.basedir}/src/main/resources/api.yml</inputSpec> <language>spring</language> <apiPackage>${default.package}.controller</apiPackage> <modelPackage>${default.package}.model.dto</modelPackage> <invokerPackage>${default.package}.handler</invokerPackage> <generateSupportingFiles>false</generateSupportingFiles> <generateApiTests>false</generateApiTests> <configOptions> <java8>true</java8> <interfaceOnly>true</interfaceOnly> </configOptions> </configuration> </execution></executions> </plugin> @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<Pet> addPet(@ApiParam(value = "Pet to add to the store" ,required=true ) @Valid @RequestBody NewPet body) {...}
  27. #resources 7 reasons for consumer driven contracts Spring Cloud Contract

    meet Pact Consumer driven contract testing using pact