Contract Testing with Pact: A Different Approach - - PDF document

contract testing with pact a different approach
SMART_READER_LITE
LIVE PREVIEW

Contract Testing with Pact: A Different Approach - - PDF document

AT28 Agile and Continuous Testing Thursday, November 7th, 2019 4:45 PM Contract Testing with Pact: A Different Approach Presented by:


slide-1
SLIDE 1

¡ ¡ AT28 ¡

Agile ¡and ¡Continuous ¡Testing ¡ Thursday, ¡November ¡7th, ¡2019 ¡4:45 ¡PM ¡ ¡ ¡ ¡ ¡

Contract ¡Testing ¡with ¡Pact: ¡A ¡Different ¡ Approach ¡ ¡

Presented ¡by: ¡ ¡ ¡

¡ Mihail ¡Mikulaninec ¡

¡ MOO ¡ ¡

Brought ¡to ¡you ¡by: ¡ ¡ ¡ ¡

¡

¡

¡ ¡ ¡

888-­‑-­‑-­‑268-­‑-­‑-­‑8770 ¡·√·√ ¡904-­‑-­‑-­‑278-­‑-­‑-­‑0524 ¡-­‑ ¡info@techwell.com ¡ ¡

https://agiledevopseast.techwell.com/ ¡

¡ ¡

slide-2
SLIDE 2

¡ ¡ ¡

¡

Mihail ¡Mikulaninec ¡

¡ Mihail ¡Mikulaninec ¡is ¡a ¡physicist ¡that ¡evolved ¡from ¡a ¡developer ¡at ¡a ¡medical ¡ company ¡to ¡an ¡automation ¡QA ¡engineer. ¡He ¡has ¡worked ¡with ¡various ¡businesses ¡ (fintech, ¡medicine, ¡design, ¡printing) ¡and ¡tech ¡stacks ¡(C++, ¡C#, ¡Ruby, ¡Python, ¡React, ¡ Java). ¡Mihail ¡is ¡passionate ¡about ¡microservices ¡architecture ¡and ¡CI/CD ¡with ¡a ¡focus ¡

  • n ¡quality. ¡He ¡has ¡been ¡involved ¡in ¡the ¡decoupling ¡strategy ¡for ¡a ¡number ¡of ¡

companies ¡in ¡order ¡to ¡move ¡toward ¡a ¡microservices ¡world. ¡He ¡currently ¡serves ¡as ¡ the ¡senior ¡automation ¡QA ¡engineer ¡at ¡MOO, ¡in ¡London, ¡UK. ¡ ¡

slide-3
SLIDE 3

10/29/19 ¡ 1 ¡

1

CON ONTRACT T TESTING W G WITH P PACT︎ A D DIFFERENT A APPROA OACH︎

BY M MICHAEL M MIKULANINEC︎

2

ABOUT MICROSERVICES

slide-4
SLIDE 4

10/29/19 ¡ 2 ¡

3

MICROS OSERVICES A ARCHITECTURE︎ 
 ︎

The idea is to split your application into a set of smaller, interconnected services instead of building a single monolithic

  • application. Each microservice is a small application that has its own

architecture consisting of business logic along with various adapters.︎

4

MICROS OSERVICES D DIAGR GRAM︎

WOR ORLD︎

API S SERVER C CON ONTAINER︎

API S SERVER︎ DATA A AGGR GGREGA GATOR OR︎

DATA A AGGR GGREGA GATOR OR C CON ONTAINER︎ INVENTOR ORY C CON ONTAINER︎ ACCOU OUNT C CON ONTAINER︎ SHIPPING C G CON ONTAINER︎

INVENTOR ORY︎ SE SERVICE RVICE︎ ACCOU OUNT︎ SE SERVICE RVICE︎ SHIPPING︎ SE SERVICE RVICE︎ DB DB︎ DB DB︎ DB DB︎

slide-5
SLIDE 5

10/29/19 ¡ 3 ¡

5

BENEFITS OF OF M MICROS OSERVICES A ARCHITECTURE︎ 
 ︎

It t tackle les t the p proble lem o

  • f

comple lexit ity b by decomposin ing a applic licatio ion in into a a s set o

  • f m

manageable le servic ices︎ whic ich a are m much f faster t to develo lop, a and m much e easie ier to u understand a and main intain in.︎ It e enable les e each s servic ice to b be d develo loped in independently ly︎ by a a t team t that is is focused o

  • n t

that s servic ice.︎ whatever t technolo logie ies make s sense f for t their ir servic ice a and n not b bound t to the c choic ices m made a at t the start o

  • f t

the p project.︎ As a a r result lt, it it m makes contin inuous d deplo loyment possib ible le f for c comple lex applic licatio ions.︎ to b be s scale led in independently ly.︎ It r reduces b barrie ier o

  • f

adoptin ing n new technolo logie ies s sin ince t the develo lopers a are f free t to choose choose︎ Mic icroservic ice archit itecture e enable les each m mic icroservic ice t to b be deplo loyed in independently

  • ly. ︎

Mic icroservic ice archit itecture e enable les each s servic ice︎

6

DRAWBACKS OF OF M MICROS OSERVICES ARCHIT ARCHITECT ECTURE URE︎ 
 ︎

Microservices architecture is adding complexity to the project just by the fact that a microservices application is a distributed system.︎ Microservices has the partitioned database architecture.︎ Testing a microservices application is also much more complex than in case of monolithic web application.︎ It is more difficult to implement changes that span multiple services. ︎ Deploying a microservices-based application is also more complex. ︎

slide-6
SLIDE 6

10/29/19 ¡ 4 ¡

7

ABOUT PACT

8


 ︎

CON ONTRACT T TESTING︎ 
 ︎ WITH P PACT︎

Pact is a contract testing tool. Contract testing is a way to ensure that services (such as an API provider and a client) can communicate with each other. Without contract testing, the only way to know that services can communicate is by using expensive and brittle integration tests.︎ 
 ︎ Contract testing is immediately applicable anywhere where you have two services that need to communicate - such as an API client and a web front-end. ︎ In general, a contract is between a consumer (for example, a client that wants to receive some data) and a provider (for example, an API on a server that provides the data the client needs).︎

CON ONSUMER︎ PROV OVIDER︎

A client that wants to receive some data ︎ A service or server that provides the data︎

MICROS OSERVICE︎ ARCHIT ARCHITECT ECTURE URE︎

slide-7
SLIDE 7

10/29/19 ¡ 5 ¡

9

A c contract b between a a c consumer and p provid ider is is c calle lled a a P PACT. Each p pact is is a a c colle llectio ion o

  • f

in interactio

  • ions. E

Each in interactio ion describ ibes:︎ 
 ︎

An EXPECTED R REQU QUEST - describing what the consumer is expected to send to the provider


A MINIMA MINIMAL expected response - describing the parts of the response the consumer wants the provider to return.︎

10

Consumer Pact tests operate on each interaction to say “assuming the provider returns the expected response for this request, does the consumer code correctly generate the request and handle the expected response?”.︎ 
 ︎

CONSUMER TESTING

slide-8
SLIDE 8

10/29/19 ¡ 6 ¡

11

DIAGR GRAM W WITH C CON ONSUMER T TESTING︎


 ︎

Configure pact server for the API to be like

Check whether the result makes me happy︎ TEST RUNNER︎

Pact Mock Server︎

ACCOUNT︎ SERVICE︎

Data Aggregator Container︎

Controllers︎ Inventory︎

Hit the service you work with and get me the result︎

Web Server︎ Controllers︎ Services︎ External︎ Request/︎ Response︎ Handler︎ ︎ Account︎ Shipping︎

Pact The consumer ”Data Aggregator” Expects the provider “Inventory Service to be Pact The consumer ”Data Aggregator” Expects the provider “Account Service to be Pact The consumer ”Data Aggregator” Expects the provider “Shipping Service to be

PACT︎ BROKER︎

12

Get availability Get product ID Get product price

Get product price

Inventory Service Inventory Mock Service

Mock service can be different from the real service

slide-9
SLIDE 9

10/29/19 ¡ 7 ¡

13

PACT B BROK OKER︎

is an application for sharing for consumer driven contracts and verification results. It is optimised for use with "pacts" (contracts created by the Pact framework), but can be used for any type of contract that can be serialized to JSON.︎

Allo llows y you t to r rele lease ︎ customer v valu lue q quic ickly ly ︎ and c confid idently ly︎ Solv lves t the p proble lem o

  • f h

how ︎ to s share c contracts a and ︎ verif ific icatio ion r result lts b between ︎ consumer a and p provid ider p projects︎ Tells lls y you w whic ich v versio ions

  • f y

your a applic licatio ions c can be d deplo loyed s safely ly together together︎ Automatic ically lly v versio ions ︎ your c contracts︎ Allo llows y you t to e ensure ︎ backwards c compatib ibilit ility ︎ between m mult ltip iple le c consumer ︎ and p provid ider v versio ions︎ Provid ides A API d documentatio ion ︎

  • f y

your a applic licatio ions t that is is ︎ guaranteed t to b be u up-t

  • to d

date︎ Shows y you r real e l example les

  • f h

how y your s servic ices in interact︎ Allo llows y you t to v vis isualis lise t the rela latio ionship ips b between y your servic ices︎

1︎ 2︎ 3︎ 4︎

14

slide-10
SLIDE 10

10/29/19 ¡ 8 ¡

15 16

Data Aggregator Container︎

Web Server︎ Controllers︎ Services︎ Account︎ Shipping︎ Controllers︎ Inventory︎

Pact The consumer ”API Server” Expects the provider “Data Aggregator” to be

PROV OVIDER V VERIFICATION ON︎

PACT BROKER︎ PACT PROVIDER︎ VERIFIER︎

External︎ Request/︎ Response︎ Handler︎ ︎

slide-11
SLIDE 11

10/29/19 ¡ 9 ¡

17

ABOUT SPECIAL WAY OF IMPLEMENTATION

18

CON ONVENTION ONAL I IMPLEMENTATION ON︎

import atexit import unittest from pact import Consumer, Provider pact = Consumer('Consumer').has_pact_with(Provider('Provider' )) pact.start_service() atexit.register(pact.stop_service) class GetUserInfoContract(unittest.TestCase): def test_get_user(self): expected = { 'username': 'UserA', 'id': 123, 'groups': ['Editors'] } (pact .given('UserA exists and is not an administrator') .upon_receiving('a request for UserA') .with_request('get', '/users/UserA') .will_respond_with(200, body=expected)) with pact: result = user('UserA') self.assertEqual(result, expected)

Consumer Tests

slide-12
SLIDE 12

10/29/19 ¡ 10 ¡

19

Comparison of conventional ways of implementation of provider verification︎ 
 ︎

PROV OVIDER V VERIFICATION ON︎ 
 ︎

20

Data Aggregator Container︎

Web Server︎ Controllers︎ Services︎ Account︎ Shipping︎ Controllers︎ Inventory︎

Pact The consumer ”API Server” Expects the provider “Data Aggregator” to be

Provider verification with stubbed handler (conventional way)︎

PACT BROKER︎ PACT PROVIDER︎ VERIFIER︎

External︎ Request/︎ Response︎ Handler︎ ︎

slide-13
SLIDE 13

10/29/19 ¡ 11 ¡

21

Data Aggregator Container︎

Web Server︎ Controllers︎ Services︎ Shipping︎

Pact The consumer ”API Server” Expects the provider “Data Aggregator” to be

PROV OVIDER V VERIFICATION ON P PROV OVIDER V VERIFICATION ON WITH 3 3-D

  • D P

PARTY M MOC OCK S SERVICES︎

PACT BROKER︎ PACT PROVIDER︎ VERIFIER︎

Wiremock︎ Wiremock︎ Wiremock︎

External︎ Request/︎ Response︎ Handler︎ ︎ Controllers︎ ACCOUNT︎ INVENTORY︎ SHIPPING︎ INVENTORY︎ SERVICE︎ ACCOUNT︎ SERVICE︎ SHIPPING︎ SERVICE︎

22

MOC OCK S SERVICE C CON ONFIGS GS C CAN GO OU GO OUT OF OF S SYNC 


Wiremock︎ Wiremock︎ Wiremock︎

INVENTORY︎ SERVICE︎ ACCOUNT︎ SERVICE︎ SHIPPING︎ SERVICE︎ INVENTORY︎ SERVICE︎ ACCOUNT︎ SERVICE︎ SHIPPING︎ SERVICE︎

slide-14
SLIDE 14

10/29/19 ¡ 12 ¡

23

It w will s ill save u us f from t the p potentia ial h l huge c code r repetit itio ion ( (we n need t to config igure t the m mock s servers in in c consumer t tests a and in in 3 3-d

  • d p

party m mocks f for provid ider v verif ific icatio ion). T They b both s should ld b be m main intain ined a and c can e eventually lly go o

  • ut o
  • f s
  • sync. W

We s should ld k keep in in m min ind t that c config iguratio ions c can b be MA MASSIV IVE︎ 
 
 ︎

WHAT I IF W WE C CAN U USE P PACT M MOC OCK S SERVICES F FOR OR T THE P PROV OVIDER V VERIFICATION ON?︎


 ︎

24

Data Aggregator Container︎

Web Server︎ Controllers︎ Services︎ Shipping︎

Pact The consumer ”API Server” Expects the provider “Data Aggregator” to be

NEW V VERIFICATION ON D DIAGR GRAM


PACT BROKER︎ PACT PROVIDER︎ VERIFIER︎

Pact Mock Server︎

External︎ Request/︎ Response︎ Handler︎ ︎ Controllers︎ ACCOUNT︎ INVENTORY︎ SHIPPING︎ INVENTORY︎ SERVICE︎ ACCOUNT︎ SERVICE︎ SHIPPING︎ SERVICE︎

Pact Mock Server︎ Pact Mock Server︎

slide-15
SLIDE 15

10/29/19 ¡ 13 ¡

25

COD ODE S SNIPPET F FOR OR M MOC OCK S SERVER C CON ONFIGU GURATION ONS︎ 
 ︎

'Inventory': {

'port': 1111, 'interactions': [ { 'GIVEN': 'Provided we have the correct project_id and data to edit', 'UPON_RECEIVING': 'the correct paper URL should be provided', 'REQUEST': { 'method': 'get', 'path': '/' }, 'RESPONSE': { 'status': 200, 'body': EachLike({ "id": Like(1), "name": Like("Pants"), "quantity": Like(15) }) } } ] } from pact import EachLike, Like BASE_CONFIG = { 'host': '127.0.0.1', # path to the dir where the pact files will be stored. Eventually should be centralised int the Pact Broker 'path_to_pacts': 'pacts/python/', 'consumer': 'python-data-aggregator' } # each service should contain name and the following keys (case sensitive): # 'GIVEN' - a description string about the initial data needed for using of tht API, # 'UPON_RECEIVING' - a string description of the expected

  • utcomes,

# 'REQUEST' - the expected request to the API (see pact.io for details), # 'RESPONSE' the expected response from the API (see pact.io for the details) SERVICES = {

26

COD ODE S SNIPPET F FOR OR M MOC OCK S SERVICE M MANAGE GER︎


 
 ︎

def stop(self):

self.pact.stop_service() return self def start(self): self.pact.start_service() self.pact.setup() return self def safe_start(self): self.start() atexit.register(self.stop) return self.pact from pact import Consumer, Provider import atexit from tests.mock_servers_configurations import BASE_CONFIG, SERVICES class MockApiServer: def __init__(self, service, log_dir='contract_logs/consumer'): config = SERVICES[service] self.pact=Consumer(BASE_CONFIG['consumer’]) .has_pact_with(Provider(service), host_name=BASE_CONFIG['host'], port=config['port'], pact_dir=BASE_CONFIG['path_to_pacts'], log_dir=log_dir) for interaction in config['interactions']: (self.pact.given(interaction['GIVEN']) .upon_receiving(interaction['UPON_RECEIVING']) .with_request(**interaction['REQUEST']) .will_respond_with(**interaction['RESPONSE']))

@staticmethod def safe_start_all_services(): for service in SERVICES.keys(): MockApiServer(service).safe_start()

slide-16
SLIDE 16

10/29/19 ¡ 14 ¡

27

from tests.mock_server import MockApiServer from services.inventory import Inventory from services.shipping import Shipping from services.account import Account // Start the inventory server and stop it afterwards inventory_pact_server = MockApiServer("Inventory").safe_start() inventory_api = Inventory("http://localhost: {}".format(inventory_pact_server.port)) def test_inventory_main(): response = inventory_api.get_data() assert response == [{'id': 1, 'name': 'Pants’, 'quantity': 15}] def test_inventory_get_product_name(): response = inventory_api.get_product_name(1) assert response == "Pants"

28

COD ODE S SNIPPET F FOR OR A ACCOU OUNT S SERVICE︎


 ︎

from services.base import Base class Account(Base): def get_data(self): return self.get("/") def get_account(self, ac_id): return [el for el in self.get_data() if el["id"] == ac_id] [0]

slide-17
SLIDE 17

10/29/19 ¡ 15 ¡

29

SUMMARY

1︎ 2︎ 3︎

Mic icroservic ices a are h here t to s stay!︎

Ge Get w wit ith p program a and a adapt y your t test a approach.︎

PACT is is a a g great t tool︎

that s solv lves a a n new p proble lem in in t the ︎ mic icroservic ices s space.︎

There a are m mult ltip iple le a approaches︎

to im imple lementin ing P PACT t testin ing – t this is is is o

  • nly

ly o

  • ne. ︎

Go Go p pla lay a and f fin ind y your o

  • wn!︎
slide-18
SLIDE 18

10/29/19 ¡ 16 ¡

31

THANK YOU FOR YOUR ATTENTION

32

1) h https://www.mule lesoft.com/resources/api/ i/mic icroservic ices-v

  • vs-m
  • monolit

lithic ic︎ 2) h https://artic icle les.mic icroservic ices.com/monolit lithic ic-v

  • vs-m
  • mic

icroservic ices-a

  • archit

itecture-5

  • 5c4848858f59︎

3) h https://mic icroservic ices.io io/patterns/monolit lithic ic.html︎ 4) h https://la labs.spotif ify.com/2018/01/11/testin ing-o

  • of-m
  • mic

icroservic ices/︎ 5) h https://git ithub.com/dj-n

  • nio

iobiu ium/pact-t

  • testin

ing︎

REFERENC ES