契约测试Pact

Posted zibinchen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了契约测试Pact相关的知识,希望对你有一定的参考价值。

设计契约测试

1、如何设计契约测试

 

1、常见的契约测试工具

    Pact

 python版本pact-python

    Pacto

    Sprint Cloud Contract

 

Pact是最常用的契约测试工具

 

 

2、Pact基本工作流程

 基于消费者的业务逻辑,生成契约文件

 

 

 

 

 

写代码主要写获取Pact文件(图一)的代码

模拟消费者向生产者发请求有相应的工具直接运行

 

 

3、Pact-Python安装

 

进入github官网

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

 

 

 

用命令行安装

 

 

如果碰到报错

那就是在pactin目录下缺少ZIP压缩文件

解决方案:

进如pact包下载官网,找到对应的ZIP包自行下载,放到pactin目录下,再重新用命令安装

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

 

 

2、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>消费者 Nanoha</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> <p class="lead">国家:{{result[‘nationality‘]}}</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

 

 

1、创建第一个Pact契约测试用例

 

1>先做一个公共方法

作用:用来实现我们一个发请求的方法

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默认的端口号

 

2>写一个契约测试用例

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)

 

 2、运行

1>先运行生成一个契约文件(.json文件)

 

2>先运行生产者api_service.py

 

 

3>打开终端,进入契约脚本目录,运行命令

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

 

 

测试结果通过,如下图:

 

 

 

 

 

以上是关于契约测试Pact的主要内容,如果未能解决你的问题,请参考以下文章

契约测试(Pact)

微服务契约测试-Pact

未检测到契约测试PactProviderRule

在语义发布中处理 nextRelease 版本

契约测试的必要性

带有 PACT 的 XCUITest 不返回模拟网络响应