Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

[Test bash manchester] contract testing in practice

87 views

Published on

End-to-end integration plays a strong part in testability, unfortunately when an application grows, these kind of tests become a burden: brittleness, slower feedback and overall poor return on investment to improve quality.

Contract testing brings an alternative approach for validating integration points in fast-changing distributed systems. Because contracts don’t need integration environments, they can give very fast feedback to prevent API and messaging breaking changes from being introduced early-on.

Contracts are also a catalyst for inter-team communications. They help interactions between services become a central attribute in designing solutions, as opposed to an emergency concern when they break at a late integration stage.

This workshop covers the core concepts of contracts testing and contracts can play a part in reducing the struggles of integration tests. The attendees will be working on practical examples of defining contracts between teams and services, as well as implement them using the Pact tool-chain.

Published in: Software
  • Be the first to comment

  • Be the first to like this

[Test bash manchester] contract testing in practice

  1. 1. @PierreVincent Contract testing in practice with Pact October 2nd, 2019 – TestBash Manchester @PierreVincent pvincent.io
  2. 2. @PierreVincent Pierre Vincent Infra. & Reliability Manager @PierreVincent pvincent.io
  3. 3. From this... … to this.
  4. 4. Login Service User Service API GET /users/pierre { "user": "pierre", "name": "Pierre Vincent", "role": "publisher" } 200 OK How do we test this?
  5. 5. Running in Prod Tests Pass in Build Implement changes Deployed in Prod User Service Login Service ! ✓ ✓ ✓ ✓ ✓ { ... "role": "editor" } { ... "roles": ["publisher","editor"] } Running in Prod ✓ ✓
  6. 6. Maybe we should have tested before deploying to production…? Tested what though?
  7. 7. Users Service Login Service IP Check Service Token Gen Service Cert/Key Service Login Frontend We only wanted to test this bit!
  8. 8. Contract Login Service User Service API Authentication Team Users Team Consumer Provider
  9. 9. What’s in a contract? Request Headers HTTP MethodAPI Endpoint Query Parameters Request Body Response HeadersStatus Code Response Body e.g. /api/users e.g. POST e.g. ?fields=name e.g. Authorization e.g. Content-Typee.g. 200
  10. 10. Our running example for the workshop Game Service Leaderboard Service APIAPI Play a game Return result & current win-rate Record game result Return updated win-rate Contract
  11. 11. POST /play { "username": "pierre", "game": "headsOrTails", "choice": "heads" } Game Service API 200 OK Content-Type: application/json; charset=UTF-8 { "won": true, "message": "You won!", "totalPlays": 120, "totalWins": 71, "winRate": 59 }
  12. 12. Activity 1 Thinking about API design
  13. 13. Game Service Leaderboard Service API Record game result: Game played, User playing, Won/Lost Return win-rate: Games played, Games won, Win-Loss Ratio “Consumer” Teams - Document what API you need to send game results “Provider” Teams - Document what API you will implement to receive game results
  14. 14. Game Service Leaderboard Service API Record game result: Game played, User playing, Won/Lost Return win-rate: Games played, Games won, Win-Loss Ratio “Consumer” & “Provider” Teams - Meet to compare your API designs - Discuss differences and come to agreement on the API interaction - Have you thought of “unhappy” paths? (API errors)
  15. 15. [docs.pact.io] PACT Specification Verification philosophy: Tolerant Reader Implementation guidelines Implementations
  16. 16. Login Service User Service A P I Pact Mock Server Authentication Team Users Team Pact Consumer Unit Test Define interaction Trigger interaction Generate Pact Pact Provider Test Share Pact Replay interaction Replay & Verify Play & Record
  17. 17. Consumer Provider Provider State Request Expected Response Login Service User Service Given that user 'pierre' exists Method GET Path /users/pierre Headers Accept: application/json Status 200 Headers Content-Type: application/json Body { "user": "pierre", "name": "Pierre Vincent", "role": "publisher" } Interaction
  18. 18. User Service A P I 1. Set Provider State 2. Send Request 3. Verify Response Interaction Verification Test INSERT INTO users [...] GET /users/pierre Accept: application/json { "user": "pierre", ... } { "user": "pierre", ... } ?
  19. 19. Activity 2 Implementing the API Contract
  20. 20. RecordScore API (or write your own) Game Service Leaderboard Service POST /recordScore { “username”: “anna”, “game”: “headOrTails”, “won”: true } { “gamesPlayed”: 123, “gamesWon”: 55 } Request Response
  21. 21. API Implement API client in Consumer - In LeaderboardClient.java: - API endpoint (recordScoreUrl) - Request Body (RecordScoreRequestBody) - Response Body (RecordScoreResponseBody) ./gradlew run Run the service (in game-service dir) curl -X POST -H "Content-Type: application/json" --data '{"username": "pierre", "game":"headsortails", "choice": "tails"}' http://localhost:8080/play Try your API Game Service
  22. 22. API Creating the Pact - In LeaderboardClientPactTest.java: - Complete the PACT definition (RequestResponsePact) - Update expected response (expectedResponse) - Update expected request (client.recordScore) ./gradlew test Run the pact test (in game-service dir) cat build/pacts/game-service-leaderboard-service.json Find the generated PACT Contract
  23. 23. Leaderboard Service API Implement the Provider API - In ScoreController.java: - API endpoint (@PostMapping) - Request Body (RecordScoreRequestBody) - Response Body (RecordScoreResponseBody) ./gradlew run Run the service (in leaderboard-service dir) curl -X POST -H "Content-Type: application/json" --data 'YOUR_JSON_PAYLOAD' http://localhost:8081/your/api/endpoint Try your API
  24. 24. Verifying the pact - Copy the generated PACT file (game/build/pacts/*.json) to the Provider test resources (leaderboard-service/src/test/resources/pacts) - Complete the PACT definition (RequestResponsePact) - Update expected response (expectedResponse) - Update expected request (client.recordScore()) ./gradlew test Run the verification test (in leaderboard-service dir) Contract ✓
  25. 25. Sharing Contracts with PactFlow pactflow.io
  26. 26. Authentication Dev Team Users Dev Team CMS Dev Team Billing Dev Team Pact Broker PACT PACT PACT PACT PACT PACT PACT PACT PACT PACT pactflow.io ✓ ✓ ✓
  27. 27. Dependency Graphs Living documentation by example ✓ Versioning ✓ Tagging ✓ REST Api Build/Deployment Pipeline integration Pact Broker pactflow.io
  28. 28. Bonus content Pacts in CI/CD Pipelines
  29. 29. Provider pipeline Implement changes Get Pacts from Broker Replay & Verify Interactions Deploy Service Build Deploy to EU PROD-EU Get Pacts from Broker Replay & Verify Interactions Stop deployment of incompatible Provider Stop introduction of breaking change PROD-US PROD-EU
  30. 30. Consumer pipeline Implement changes Generate Pacts (Build) Push Pacts to Broker Tag Pacts Each Provider verifies Pacts Deploy Service Tag Pacts Build Deploy to EU HEAD Stop deployment of incompatible Consumer HEAD PROD-EU
  31. 31. @PierreVincent Thank you! Pierre Vincent Infra. & Reliability Manager @PierreVincent pvincent.io

×