契約測試Pact(四)


如何設計契約測試

常見的契約測試工具

    Pact

 python版本pact-python

    Pacto

    Sprint Cloud Contract

 

Pact是最常用的契約測試工具

 

Pact基本工作流程

 基於消費者的業務邏輯,生成契約文件

 

 

 

 

 

 

 

寫代碼主要寫獲取Pact文件(圖一)的代碼

模擬消費者向生產者發請求有相應的工具直接運行

 

Pact-Python安裝

 

進入github官網

https://github.com/pact-foundation/pact-python/

 

 

用命令行安裝

 

如果碰到報錯

那就是在pact\bin目錄下缺少ZIP壓縮文件

解決方案:

進如pact包下載官網,找到對應的ZIP包自行下載,放到pact\bin目錄下,再重新用命令安裝

https://github.com/pact-foundation/pact-ruby-standalone/releases

 

 

 

Pact 設計用例

寫一個例子

創建一個生產者和兩個消費者

 

miku.html

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>消費者 Miku</title>
</head>
<body>

<h1 class = 'cover-heading'>{{result['name']}}</h1>
<p class="lead">郵箱:{{result['contact']['Email']}}</p>
<p class="lead">電話:{{result['contact']['Phone Number']}}</p>
</body>
</html>

 

nanoha.html

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>消費者 Miku</title>
</head>
<body>

<h1 class = 'cover-heading'>{{result['name']}}</h1>
<p class="lead">郵箱:{{result['contact']['Email']}}</p>
<p class="lead">電話:{{result['contact']['Phone Number']}}</p>
</body>
</html>

 

  

用flask寫一個mock接口

用來當做生產者

api_service.py

 

#! usr/bin/env python
# _*_ coding: utf-8 _*_

from flask import Flask,request,jsonify

app = Flask(__name__)
app.config['JSON_SORT_KEYS'] = False

rsp_body = [
    {
        "salary": 45000,
        "name": "Hatsune Miku",
        "nationality":"Japan",
        "contact": {
            "Email": "hatsune.miku@woniuxy.com",
            "Phone Number": "13900110001"
        }
    },{
         "salary": 80000,
        "name": "Takamachi Nanoha",
        "nationality":"Japan",
        "contact": {
            "Email": "takamachi.nanoha@woniuxy.com",
            "Phone Number": "18800880008"
        }
    }
]

@app.route('/information',methods=['GET'])
def test():
    get_name = request.args.get("name","").lower()
    if get_name == 'miku':
        rsp = jsonify(rsp_body[0])
    elif get_name == 'nanoha':
        rsp = jsonify(rsp_body[1])
    else:
        rsp = jsonify({'status': '404 not found.'})
    return rsp


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

 

  

同樣用flask寫兩個消費者consumer_miku.py  和 consumer_nanoha.py

consumer_miku.py

 

from flask import Flask,request,jsonify,render_template
import urllib3
import json


app = Flask(__name__)


@app.route('/miku',methods=['GET'])
def miku_html():
    params = {"name": "miku"}
    http = urllib3.PoolManager()
    resp = http.request('GET', 'http://localhost:8080/information', params)
    result = json.loads(resp.data.decode())
    return  render_template("miku.html", result = result)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8081)

 

  

consumer_nanoha.py

 

from flask import Flask,request,jsonify,render_template
import urllib3
import json


app = Flask(__name__)


@app.route('/nanoha',methods=['GET'])
def nanoha_html():
    params = {"name": "nanoha"}
    http = urllib3.PoolManager()
    resp = http.request('GET', 'http://localhost:8080/information', params)
    result = json.loads(resp.data.decode())
    return  render_template("nanoha.html", result = result)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8082)

 

  

運行生產者和消費者,然后打開URL

 

 

pact-verifier --provider-base-url=http://localhost:8080 --pact-url=consumer_miku-provider.json

 

 

創建第一個Pact契約測試用例

先做一個公共方法

作用:用來實現我們一個發請求的方法

query.py

 

#! usr/bin/env python
# -*- coding: utf-8 -*-

import requests


def get_cartoon_characters(name):
    # pact作為模擬生產者時,其端口默認為1234
    resp = requests.get('http://localhost:1234/information',{'name':name})
    return resp

 

  

我們做契約測試,首先是模擬生產者,'1234'是pact默認的端口號

 

寫一個契約測試用例

contract.py

#! usr/bin/env python
# -*- coding: utf-8 -*-

import atexit
import unittest
from pact import Consumer,Provider
from microservice.Contract_test.query import get_cartoon_characters


# 構造pact對象,定義消費者服務的名字並給它一個生產者服務
pact = Consumer('Consumer Miku').has_pact_with(Provider('Provider'))
pact.start_service()
# 注冊退出的時候關閉pact服務
atexit.register(pact.stop_service)

class GetMikuInfoContract(unittest.TestCase):

    def test_miku(self):
        # 定義響應期望的結果
        expected = {
            "salary": 45000,
            "name": "Hatsune Miku",
            "nationality": "Japan",
            "contact": {
                "Email": "hatsune.miku@woniuxy.com",
                "Phone Number": "13900110001"
            }
        }
        # 定義響應頭
        headers = {
            "Content-Type":"application/json"
        }
        # 定義模擬生產者提供者接受請求以及響應的方式
        (pact
         .upon_receiving('a request for Miku')
         .with_request(
            method='GET',
            path='/information',
            query={'name':'miku'}
         ).will_respond_with(200,headers,expected))
        # 定義消費者服務向模擬生產者發出請求並活得響應
        with pact:
            result = get_cartoon_characters('miku')
        # 做最后的斷言
        self.assertEqual(result.json(),expected)


if __name__ == '__main__':
    unittest.main(verbosity=2)

 

 

運行

先運行生成一個契約文件(.json文件)

 

 

先運行生產者api_service.py

 

 

打開終端,進入契約腳本目錄,運行命令

pact-verifier --provider-base-url=http://localhost:8080 --pact-url=consumer_miku-provider.json

pact-verifier --provider-base-url=http://localhost:8080 --pact-url=consumer_miku-provider.json

 

測試結果通過,如下圖:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM