[英]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 代表消費者,所以你絕對不要在這里嘲笑提供者(否則,你會有什么信心?)
你應該:
另請參閱有關測試 scope 的此頁面: https://docs.pact.io/getting_started/testing-scope
您可能會發現這些示例很有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.