簡體   English   中英

如何在 python 中創建提供商協議驗證

[英]How to create provider pact verification in python

我正在嘗試使用 python 針對消費者合同建立協議驗證。 基本上我正在閱讀經紀人的消費者協議並嘗試驗證它。 提供者 real API 托管在 GCP 上。

如果我需要創建一個提供程序模擬(我以為我們只在消費者端創建它)來運行驗證,或者我必須針對生產 API(托管在 GCP 上)運行它,我真的很困惑?

如果它是本地主機上的提供程序模擬,我應該如何構建它?

實際上,當它在本地運行時,我覺得我要像在user-app.py中那樣對實際響應進行硬編碼。 因此,當生產 API 更改時,我必須在user-app.py上手動反映該更改。 我覺得我錯過了什么。

這是合同

{
  "provider": {
    "name": "recommendations.basket.model"
  },
  "consumer": {
    "name": "recommendations.recommendations-api"
  },
  "interactions": [
    {
      "description": "should handle a basket model response for a valid confidence strategy request",
      "request": {
        "method": "POST",
        "path": "/v1/projects/655160509744/locations/europe-west1/endpoints/1425846678899916800:predict",
        "headers": {
          "Authorization": "珙뭥",
          "Content-Type": "application/json"
        },
        "body": {
          "instances": [
            {
              "products": [],
              "user": "2ff287946d264cab8b24df095286baf6",
              "n_recs": 40,
              "strategy": "confidence",
              "correlation_id": ""
            }
          ],
          "parameters": []
        },
        "matchingRules": {
          "header": {
            "Content-Type": {
              "matchers": [
                {
                  "match": "regex",
                  "regex": "application/json"
                }
              ],
              "combine": "AND"
            },
            "Authorization": {
              "matchers": [
                {
                  "match": "regex",
                  "regex": ".*"
                }
              ],
              "combine": "AND"
            }
          }
        }
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/json"
        },
        "body": {
          "predictions": [
            {
              "strategy": "lift",
              "product_ids": [
                6155964,
                6156017,
                5561627,
                4833065,
                4349044,
                4833064,
                4349045,
                5629727,
                3128937,
                5143281,
                5629707,
                5395670,
                5577628
              ],
              "title": "You might also like",
              "metadata": {
                "correlation_id": "afe50dab-0abc-4230-b906-0cd6b1ac49c4",
                "strategy_requested": "12334jjkj",
                "recommendation_id": "93ac4715-8ed8-419a-9a90-1796d74a4587",
                "outcome": "success",
                "recommendation_time": "2022-08-01-10-14-37",
                "model_training_time": "2022-08-01-07-29-24"
              }
            }
          ],
          "deployedModelId": "6753024495939747840",
          "model": "projects/655160509744/locations/europe-west1/models/5045245443492020224",
          "modelDisplayName": "basket-release-b41f5c19"
        }
      },
      "providerStates": [
        {
          "name": "Shopper Id 2ff287946d264cab8b24df095286baf6 exists and returns recommendations for a valid confidence strategy"
        }
      ]
    },
    {
      "description": "should handle a basket model response for a Empty Recs",
      "request": {
        "method": "POST",
        "path": "/v1/projects/655160509744/locations/europe-west1/endpoints/1425846678899916800:predict",
        "headers": {
          "Authorization": "ꏪ",
          "Content-Type": "application/json"
        },
        "body": {
          "instances": [
            {
              "products": [],
              "user": "2ff287946d264cab8b24df095286baf6",
              "n_recs": 40,
              "strategy": "confidence",
              "correlation_id": ""
            }
          ],
          "parameters": []
        },
        "matchingRules": {
          "header": {
            "Content-Type": {
              "matchers": [
                {
                  "match": "regex",
                  "regex": "application/json"
                }
              ],
              "combine": "AND"
            },
            "Authorization": {
              "matchers": [
                {
                  "match": "regex",
                  "regex": ".*"
                }
              ],
              "combine": "AND"
            }
          }
        }
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/json"
        },
        "body": {
          "predictions": [
            {
              "product_ids": [],
              "title": "there has been a problem",
              "metadata": {
                "recommendation_id": "edb41361-2b03-4bd3-a84d-312901ef61e1",
                "correlation_id": "edb41361-2b03-4bd3-a84d-312901ef61e1",
                "recommendation_time": "2022-03-25-13-50-15",
                "strategy_requested": "confidence",
                "outcome": "failure",
                "model_training_time": "2022-03-22-09-55-37"
              },
              "strategy": "confidence"
            }
          ],
          "deployedModelId": "",
          "model": "",
          "modelDisplayName": ""
        }
      },
      "providerStates": [
        {
          "name": "Shopper Id 2ff287946d264cab8b24df095286baf6 exists and returns Empty recommendations"
        }
      ]
    },
    {
      "description": "should handle a basket model response for a valid lift strategy request",
      "request": {
        "method": "POST",
        "path": "/v1/projects/655160509744/locations/europe-west1/endpoints/1425846678899916800:predict",
        "headers": {
          "Authorization": "淀䉘",
          "Content-Type": "application/json"
        },
        "body": {
          "instances": [
            {
              "products": [],
              "user": "2ff287946d264cab8b24df095286baf6",
              "n_recs": 40,
              "strategy": "lift",
              "correlation_id": ""
            }
          ],
          "parameters": []
        },
        "matchingRules": {
          "header": {
            "Content-Type": {
              "matchers": [
                {
                  "match": "regex",
                  "regex": "application/json"
                }
              ],
              "combine": "AND"
            },
            "Authorization": {
              "matchers": [
                {
                  "match": "regex",
                  "regex": ".*"
                }
              ],
              "combine": "AND"
            }
          }
        }
      },
      "response": {
        "status": 200,
        "headers": {
          "Content-Type": "application/json"
        },
        "body": {
          "predictions": [
            {
              "strategy": "lift",
              "product_ids": [
                6155964,
                6156017,
                5561627,
                4833065,
                4349044,
                4833064,
                4349045,
                5629727,
                3128937,
                5143281,
                5629707,
                5395670,
                5577628
              ],
              "title": "You might also like",
              "metadata": {
                "correlation_id": "afe50dab-0abc-4230-b906-0cd6b1ac49c4",
                "strategy_requested": "12334jjkj",
                "recommendation_id": "93ac4715-8ed8-419a-9a90-1796d74a4587",
                "outcome": "success",
                "recommendation_time": "2022-08-01-10-14-37",
                "model_training_time": "2022-08-01-07-29-24"
              }
            }
          ],
          "deployedModelId": "6753024495939747840",
          "model": "projects/655160509744/locations/europe-west1/models/5045245443492020224",
          "modelDisplayName": "basket-release-b41f5c19"
        }
      },
      "providerStates": [
        {
          "name": "Shopper Id 2ff287946d264cab8b24df095286baf6 exists and returns lift recommendations"
        }
      ]
    }
  ],
  "metadata": {
    "pactSpecification": {
      "version": "3.0.0"
    },
    "pact-jvm": {
      "version": "4.0.10"
    }
  }
}

這是在本地運行驗證的user-app.py (在本例中)。

#!/usr/env/bin python
import datetime
import json
import uuid
import pdb
from flask import Flask, abort, jsonify, request
import pdb


fakedb = {}
app = Flask(__name__)

@app.route('/_pact/provider_states', methods=['POST'])
def provider_states():
    mapping = { "Shopper Id 2ff287946d264cab8b24df095286baf6 exists and returns recommendations for a valid confidence strategy": confidence_response,
                "Shopper Id 2ff287946d264cab8b24df095286baf6 exists and returns lift recommendations": lift_response,
                "Shopper Id 2ff287946d264cab8b24df095286baf6 exists and returns Empty recommendations": empty_response
                }
    mapping[request.json['state']]()
    return jsonify({'result': request.json['state']})

def empty_response():

    empty_response = {
          "predictions": [
            {
              "product_ids": [],
              "title": "there has been a problem",
              "metadata": {
                "recommendation_id": "edb41361-2b03-4bd3-a84d-312901ef61e1",
                "correlation_id": "edb41361-2b03-4bd3-a84d-312901ef61e1",
                "recommendation_time": "2022-03-25-13-50-15",
                "strategy_requested": "confidence",
                "outcome": "failure",
                "model_training_time": "2022-03-22-09-55-37"
              },
              "strategy": "confidence"
            }
          ],
          "deployedModelId": "",
          "model": "",
          "modelDisplayName": ""
        }
    fakedb["response"] = empty_response

def lift_response():
    lift_response = {
          "predictions": [
            {
              "strategy": "lift",
              "product_ids": [
                6155964,
                6156017,
                5561627,
                4833065,
                4349044,
                4833064,
                4349045,
                5629727,
                3128937,
                5143281,
                5629707,
                5395670,
                5577628
              ],
              "title": "You might also like",
              "metadata": {
                "correlation_id": "afe50dab-0abc-4230-b906-0cd6b1ac49c4",
                "strategy_requested": "12334jjkj",
                "recommendation_id": "93ac4715-8ed8-419a-9a90-1796d74a4587",
                "outcome": "success",
                "recommendation_time": "2022-08-01-10-14-37",
                "model_training_time": "2022-08-01-07-29-24"
              }
            }
          ],
          "deployedModelId": "6753024495939747840",
          "model": "projects/655160509744/locations/europe-west1/models/5045245443492020224",
          "modelDisplayName": "basket-release-b41f5c19"
        }
    fakedb["response"] = lift_response
    # return lift_response

def confidence_response():
    confidence_response = {
          "predictions": [
            {
              "strategy": "lift",
              "product_ids": [
                6155964,
                6156017,
                5561627,
                4833065,
                4349044,
                4833064,
                4349045,
                5629727,
                3128937,
                5143281,
                5629707,
                5395670,
                5577628
              ],
              "title": "You might also like",
              "metadata": {
                "correlation_id": "afe50dab-0abc-4230-b906-0cd6b1ac49c4",
                "strategy_requested": "12334jjkj",
                "recommendation_id": "93ac4715-8ed8-419a-9a90-1796d74a4587",
                "outcome": "success",
                "recommendation_time": "2022-08-01-10-14-37",
                "model_training_time": "2022-08-01-07-29-24"
              }
            }
          ],
          "deployedModelId": "6753024495939747840",
          "model": "projects/655160509744/locations/europe-west1/models/5045245443492020224",
          "modelDisplayName": "basket-release-b41f5c19"
        }
    fakedb["response"] = confidence_response

    pdb.set_trace()
    # return confidence_response


@app.route('/v1/projects/655160509744/locations/europe-west1/endpoints/1425846678899916800:predict', methods=["POST"])
def get_basket_recs():
    print("main function")
    pdb.set_trace()
    response = fakedb.get("response")
    response = jsonify(**response)

    return response



if __name__ == '__main__':
    app.run(debug=True, port=5001)

運行代碼: python user-app.py運行服務器

- 運行驗證: pact-verifier --provider-base-url=http://localhost:5001 --pact-url=tests/recommendations.recommendations-api-recommendations.basket.model.json --provider-states-setup-url=http://localhost:5001/_pact/provider_states

使用 Pact,您只能在消費者端模擬提供者,因為您正在對消費者代碼進行單元測試。

當你測試提供者時,Pact 代表消費者,所以你絕對不要在這里嘲笑提供者(否則,你會有什么信心?)

你應該:

  1. 在本地運行提供程序(最好不要在已部署的環境中運行,我們避免並通常幫助用合同測試代替的測試是端到端集成測試)
  2. 模擬任何第三方依賴項以提高可靠性/確定性

另請參閱有關測試 scope 的此頁面: https://docs.pact.io/getting_started/testing-scope

您可能會發現這些示例很有幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM