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

Consumer Driven Contract Testing workshop

9489b8d6f2dbdc3e7d26b8702143b86e?s=47 Yoan
August 14, 2019

Consumer Driven Contract Testing workshop

Created with Wilfried Vandenberghe.

9489b8d6f2dbdc3e7d26b8702143b86e?s=128

Yoan

August 14, 2019
Tweet

Transcript

  1. Consumer Driven Contracts Testing “Design your api differently”

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

  3. How to confirm all services are working together?

  4. How to write a test for it ? Client Api

    Request Response
  5. Mocking !!! Client Api Request Response Mock or Stub

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

    real producer ? •The owner of the mock is the consumer •Not trustworthy
  7. 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
  8. How can we be sure that the mocks are valid?

  9. END TO END TESTS Client REAL api Request Response

  10. Problems •Slow •All services need to be up before running

    the tests •Require a clean/dedicated integration environment
  11. But it is trustworthy

  12. Any alternative ? Could we test apis in a better

    way ?
  13. If no cooperation

  14. #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 ?
  15. “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.”
  16. Consumer Driven Contracts

  17. 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.
  18. None
  19. 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
  20. How to ? Define API contract on the consumer side.

    The contract must be enforced on the service provider.
  21. Contract test

  22. None
  23. Tools ?

  24. https://docs.pact.io/

  25. None
  26. 1) Start With Consumer

  27. 1) Start With Consumer • Write Test(S) • Define interactions

    / Expectations • In your favorite language
  28. 1) Start With Consumer • Run Tests • From Expectations

    TO Contract • Json File
  29. 2) Contract Driven Development

  30. 2) Contract Driven Development • Design Your API From The

    Contract • Write A RED Test
  31. 2) Contract Driven Development • Make You Test Pass /

    GREEN
  32. • Git ? • Near from the Provider sources ?

    • Near from the Consumer sources ? • Any better option ? Where Could We Store Our CONTRACTS ?
  33. 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
  34. 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.
  35. Auto-generated documentation for each pact. Provides a "matrix" of compatible

    consumer and provider versions,
  36. Dynamically generated network diagrams so you can visualise your microservice

    network. sheriff hopper
  37. A CLI for encorporating the Pact workflow into your continuous

    integration process. Docker Pact Broker
  38. 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
  39. None
  40. 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
  41. 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.
  42. 1) Define The Contract

  43. 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()) } } }
  44. 2) Contract Driven Development

  45. 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()) } } }
  46. 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))); }
  47. 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))); }
  48. 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
  49. • Git or jar ? • Near from the Provider

    sources ? • Near from the Consumer sources ? • Any better option ? Where Could We Store Our CONTRACTS ?
  50. None
  51. #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
  52. 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)
  53. 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.
  54. 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) {...}
  55. NEXT STEPS ?

  56. #resources 7 reasons for consumer driven contracts Spring Cloud Contract

    meet Pact Consumer driven contract testing using pact