接口断言契约校验
Project description
接口断言引入契约校验
目录:
- 一.背景
- 二.校验原则
- 三.快速使用
- 1、python类契约使用
- 2、json契约使用
- 3、python类契约转json契约
- 4、根据响应结果自动生成json契约
- 四.基本匹配规则
- 1、Matcher类 校验规则:值匹配
- 2、Like类 校验规则:类型匹配
- 3、EachLike类 校验规则:数组类型匹配
- 4、Term类校验规则:正则匹配
- 5、Enum类 校验规则:枚举匹配
- 五.复杂数据结构匹配规则
- 1、{{}}格式
- 2、[[]]格式
- 3、{[]}格式
- 六. 异常场景匹配
- 1、null匹配
- 2、{}匹配
- 3、json格式字符串匹配
- 4、key不存在匹配
- 5、多类型匹配
- 6、非强制字段匹配
- 七.unittest+HTMLTestRunner+契约断言示例
- 八.优点总结
一.背景
公司前端吐槽后台接口有时会更改返回的数据结构,返回的字段名与字段类型与接口文档不一致,希望有一个快速检测接口返回数据的所有字段名与字段类型的方法
以下方数据为例,要校验data数组中dict结构中的字段名与字段类型,可以写脚本遍历数据,但是由于每个接口返回的数据结构可能不一致,可能需要针对每个接口做不同的逻辑,所以需要一个比较通用的校验方法
{ "msg": "success", "code": 0, "data": [{ "type_id": 249, "name": "王者荣耀", "order_index": 1, "status": 1, "subtitle": " ", "game_name": "王者荣耀" }, { "type_id": 250, "name": "绝地求生", "order_index": 2, "status": 1, "subtitle": " ", "game_name": "绝地求生" }, { "type_id": 251, "name": "刺激战场", "order_index": 3, "status": 1, "subtitle": " ", "game_name": "刺激战场" } ] }
在研究了契约测试后,抽取pact-python部分代码,实现:自定义接口返回数据格式(【契约定义】)-实际响应数据格式校验(【契约校验】)的功能
备注:这里的【契约】等同于接口响应数据结构
二.校验原则
1.实际返回字段要严格等于或者含契约定义字段(根据不同匹配模式来确定)
2.字段值可以值相等或类型相等
目标:对返回数据进行全量(字段名-值/类型) 校验
契约定义方式:支持python类契约和json契约
三.基本使用
1.python类契约使用
from pactverify.matchers import Matcher, Like, EachLike, Enum, Term, PactVerify # 定义契约格式 expect_format = Matcher({ 'code': 0, # code key存在,值相等,code==0 'msg': 'success', # msg key存在,值相等,msg=='success' # [{}]结构 'data': EachLike({ "type_id": 249, # type_id key存在,值类型相等,type(type_id) == type(249) "name": "王者荣耀", # name key存在,值类型相等,type(name) == type("王者荣耀") }), 'type': Enum([11,22]), 'list': EachLike(11,minimum=2) }) # 实际返回数据 actual_data = { "msg": "success", "code": 1, 'type': 12, "data": [{ # type_id类型不匹配 "type_id": '249', "name": "王者荣耀" }, { # 缺少name "type_id": 250, }, { # 比契约定义多index字段 "type_id": 251, "name": "刺激战场", "index": 111 } ], 'list': [11] } # hard_mode默认为true,hard_mode = True时,实际返回key必须严格等于预期key;hard_mode = False时,实际返回key包含预期key即可 mPactVerify = PactVerify(expect_format, hard_mode=True) # 校验实际返回数据 mPactVerify.verify(actual_data) # 校验结果 False print(mPactVerify.verify_result) ''' 校验错误信息 错误信息输出actual_key路径:root.data.0.name形式 root为根目录,dict类型拼接key,list类型拼接数组下标(从0开始) { # 实际key少于预期key错误 'key_less_than_expect_error': ['root.data.1.name'], # 实际key多与预期key错误,只在hard_mode = True时才报该错误 'key_more_than_expect_error': ['root.data.2.index'], # 值不匹配错误 'value_not_match_error': [{ 'actual_key': 'root.code', 'actual_value': 1, 'expect_value': 0 } ], # 类型不匹配错误 'type_not_match_error': [{ 'actual_key': 'root.data.0.type_id', 'actual_vaule': '249', 'expect_type': 'int' } ], # 数组长度不匹配错误 'list_len_not_match_error': [{ 'actual_key': 'root.list', 'actual_len': 1, 'min_len': 2 } ], # 元祖不匹配错误 'enum_not_match_error': [{ 'actual_key': 'root.type', 'actual_value': 12, 'expect_enum': [11, 22] } ] } ''' print(mPactVerify.verify_info)
2.json契约使用
from pactverify.matchers import PactJsonVerify # 定义json契约格式 expect_format = { '$Matcher': { 'code': 0, # code key存在,值相等,code==0 'msg': 'success', # msg key存在,值相等,msg=='success' # [{}]结构 'data': { '$EachLike': { "type_id": 249, # type_id key存在,值类型相等,type(type_id) == type(249) "name": "王者荣耀", # name key存在,值类型相等,type(name) == type("王者荣耀") }}, 'type': { '$Enum': [11, 22] }, 'list': { '$EachLike': { # $values,$params形式传递额外参数 '$values': 11, '$params': { 'minimum': 2 } } } } } # 实际返回数据 actual_data = { "msg": "success", "code": 1, 'type': 12, "data": [{ # type_id类型不匹配 "type_id": '249', "name": "王者荣耀" }, { # 缺少name "type_id": 250, }, { # 比契约定义多index字段 "type_id": 251, "name": "刺激战场", "index": 111 } ], 'list': [11] } # hard_mode默认为true,hard_mode = True时,实际返回key必须严格等于预期key;hard_mode = False时,实际返回key包含预期key即可 # separator可自定义指定json关键字标识符,默认为$ mPactJsonVerify = PactJsonVerify(expect_format, hard_mode=True, separator='$') # 校验实际返回数据 mPactJsonVerify.verify(actual_data) # 校验结果 False print(mPactJsonVerify.verify_result) ''' 校验错误信息 错误信息输出actual_key路径:root.data.0.name形式 root为根目录,dict类型拼接key,list类型拼接数组下标(从0开始) { # 实际key少于预期key错误 'key_less_than_expect_error': ['root.data.1.name'], # 实际key多与预期key错误,只在hard_mode = True时才报该错误 'key_more_than_expect_error': ['root.data.2.index'], # 值不匹配错误 'value_not_match_error': [{ 'actual_key': 'root.code', 'actual_value': 1, 'expect_value': 0 } ], # 类型不匹配错误 'type_not_match_error': [{ 'actual_key': 'root.data.0.type_id', 'actual_vaule': '249', 'expect_type': 'int' } ], # 数组长度不匹配错误 'list_len_not_match_error': [{ 'actual_key': 'root.list', 'actual_len': 1, 'min_len': 2 } ], # 元祖不匹配错误 'enum_not_match_error': [{ 'actual_key': 'root.type', 'actual_value': 12, 'expect_enum': [11, 22] } ] } ''' print(mPactJsonVerify.verify_info)
3.python类契约转json契约
1、python类契约不带参数 # python类契约 expect_format = Like({'k1': 'v1'}) # json契约 expect_format_json = { '$Like': {'k1': 'v1'} } 2、python类契约带参数 # python类契约 expect_format = Like({'k1': 'v1'}, nullable=True) # json契约 expect_format_json = { '$Like': { # $values为契约类目标参数 '$values': {'k1': 'v1'}, # $params为额外参数的json数据 '$params': {'nullable': True} } }
4.根据响应结果自动生成json契约
from pactverify.utils import generate_pact_json_by_response if __name__ == '__main__': response_json = { "msg": "success", "code": 0, "data": [{ "type_id": 249, "name": "王者荣耀", "order_index": 1, "status": 1, "subtitle": " ", "game_name": "王者荣耀" }, { "type_id": 250, "name": "绝地求生", "order_index": 2, "status": 1, "subtitle": " ", "game_name": "绝地求生" }, { "type_id": 251, "name": "刺激战场", "order_index": 3, "status": 1, "subtitle": " ", "game_name": "刺激战场" } ] } # 参数说明:响应json数据,契约关键字标识符(默认$) pact_json = generate_pact_json_by_response(response_json, separator='$') print(pact_json) ''' # 模板生成只会包含$EachLike、$Like,可以根据具体校验需求更改,数组取第一个元素为模板来生成 { '$Like': { 'msg': 'success', 'code': 0, 'data': { '$EachLike': { 'type_id': 249, 'name': '王者荣耀', 'order_index': 1, 'status': 1, 'subtitle': ' ', 'game_name': '王者荣耀' } } } } '''
说明:
- PactVerify与PactJsonVerify校验类只是契约数据不同,其他逻辑保持一致
- PactJsonVerify关键字标志符可用PactJsonVerify(separator='$')自定义
四.基本匹配规则
1. Matcher类
校验规则:值匹配
# 预期11 python类契约格式 expect_format_1 = Matcher(11) # 预期11 json契约格式 expect_format_json_1 = { '$Matcher': 11 } # 预期1.0 python类契约格式 expect_format_2 = Matcher(1.0) # 预期1.0 json契约格式 expect_format_json_2 = { '$Matcher': 1.0 } # 预期'11' python类契约格式 expect_format_3 = Matcher('11') # 预期'11' json契约格式 expect_format_json_3 = { '$Matcher': '11' } # 预期返回数据actual为dict结构,actual['k1'] == 'v1' python类契约格式 expect_format_4 = Matcher({'k1': 'v1'}) # 预期返回数据actual为dict结构,actual['k1'] == 'v1' json契约格式 expect_format_json_4 = { '$Matcher': {'k1': 'v1'} }
2. Like类
校验规则:类型匹配
# 预期type(11) python类契约 expect_format_1 = Like(11) # 预期type(11) json契约 expect_format_json_1 = { '$Like': 11 } # 预期type(1.0) python类契约 expect_format_2 = Like(1.0) # 预期type(1.0) json契约 expect_format_json_2 = { '$Like': 1.0 } # 预期type('11') python类契约 expect_format_3 = Like('11') # 预期type('11') json契约 expect_format_json_3 = { '$Like': '11' } # 预期返回数据actual为dict结构,actual['k1'] == type('v1') python类契约 expect_format_4 = Like({'k1':'v1'}) # 预期返回数据actual为dict结构,actual['k1'] == type('v1') json契约 expect_format_json_4 = { '$Like': {'k1':'v1'} }
3. EachLike类
校验规则:数组类型匹配
# 预期[type(11)] python类契约 expect_format_1 = EachLike(11) # 预期[type(11)] json契约 expect_format_json_1 = { '$EachLike': 11 } # 预期[type(1.0)] python类契约 expect_format_2 = EachLike(1.0) # 预期[type(1.0)] json契约 expect_format_json_2 = { '$EachLike': 1.0 } # 预期[type('11')] python类契约 expect_format_3 = EachLike('11') # 预期[type('11')] json契约 expect_format_json_3 = { '$EachLike': '11' } # 预期[Like{'k1':'v1'}] python类契约 expect_format_4 = EachLike({'k1': 'v1'}) # 预期[Like{'k1':'v1'}] json契约 expect_format_json_4 = { '$EachLike': {'k1': 'v1'} } # 预期[Like{'k1':'v1'}]或[],minimum为数组最小长度,默认minimum=1 python类契约 expect_format_5 = EachLike({'k1': 'v1'}, minimum=0) # 预期[Like{'k1':'v1'}]或[],minimum为数组最小长度,默认minimum=1 json契约 expect_format_json_5 = { '$EachLike': { # $values,$params结构用于额外传参 '$values': {'k1': 'v1'}, '$params': {'minimum': 0} } }
4. Term类
校验规则:正则匹配
# 预期r'^\d{2}$',并且type(actual_data) == type(example),example也用来测试正则表达式 python类契约 expect_format_1 = Term(r'^\d{2}$', example=11) # 预期r'^\d{2}$',并且type(actual_data) == type(example),example也用来测试正则表达式 json契约 expect_format_json_1 = { '$Term': { '$values': r'^\d{2}$', '$params': {'example': 11} } } # 预期r'^\d{2}$',example用来测试正则表达式,type_strict = False时跳过对example参数类型校验 python类契约 expect_format_2 = Term(r'^\d{2}$', example="11", type_strict=False) # 预期r'^\d{2}$',example用来测试正则表达式,type_strict = False时跳过对example参数类型校验 json契约 expect_format_json_2 = { '$Term': { '$values': r'^\d{2}$', '$params': {'example': 11, 'type_strict': False} } }
5. Enum类
校验规则:枚举匹配
# 预期11或22 python类契约 expected_format_1 = Enum([11, 22]) # 预期11或22 json契约 expected_format_json_1 = { '$Enum': [11, 22] } # iterate_list为true时,当目标数据为数组时,会遍历数组中每个元素是否in [11, 22] python类契约 expected_format_2 = Enum([11, 22], iterate_list=True) # iterate_list为true时,当目标数据为数组时,会遍历数组中每个元素是否in [11, 22] json契约 expected_format_json_2 = { '$Enum': { '$values': [11, 22], '$params': {'iterate_list': True} } }
四.复杂规则匹配
1.{{}}格式
actual_data = { 'code': 0, 'msg': 'success', 'data': { "id": 1, "name": 'lili' } } # python类契约 expect_format = Like({ 'code': 0, 'msg': 'success', 'data': Like({ "id": 1, "name": 'lili' }) }) # json契约 expect_format_json = { '$Like': { 'code': 0, 'msg': 'success', 'data': { '$Like': { "id": 1, "name": 'lili' } } } }
2.[[]]格式
actual_data = [[{ "id": 1, "name": 'lili' }]] # python类契约 expect_format = EachLike(EachLike({ "id": 1, "name": 'lili' })) # json契约 expect_format_json = { '$EachLike': { '$EachLike': { "id": 1, "name": 'lili' } } }
3.{[]}格式
actual_data = { 'code': 0, 'msg': 'success', 'data': [{ "id": 1, "name": 'lili' },{ "id": 2, "name": 'lilei' }] } # python类契约 expect_format = Like({ 'code': 0, 'msg': 'success', 'data': EachLike({ "id": 1, "name": 'lili' }) }) # json契约 expect_format_json = { '$Like': { 'code': 0, 'msg': 'success', 'data': { '$EachLike': { "id": 1, "name": 'lili' } } } }
4.Like-Term嵌套
actual_data = { 'code': 0, 'msg': 'success', 'data': { "id": 1, "name": 'lili' } } # python类契约 expect_format = Like({ 'code': 0, 'msg': 'success', 'data': Like({ "id": 1, "name": Term(r'\w*', example='lili') }) }) # json契约 expect_format = { '$Like': { 'code': 0, 'msg': 'success', 'data': { '$Like': { "id": 1, "name": { '$Term': { '$values': r'\w*', '$params': { 'example': 'lili' } } } } } } }
5.Like-Matcher嵌套
actual_data = { 'name': 'lilei', 'age': 12 } # python类契约 expect_format = Like({ # name字段值类型匹配 'name': 'lilei', # age字段值匹配 'age': Matcher(12), }) # json契约 expect_format_json = { '$Like': { # name字段值类型匹配 'name': 'lilei', # age字段值匹配 'age': { '$Matcher': 12 }, } }
说明:
- Matcher,Like和EachLike类可以不限层级嵌套,Term和Enum则不能嵌套其他规则
- 匹配规则多层嵌套时,内层规则优先生效
五.异常场景匹配
1.null匹配
# nullable为true时允许返回null,预期null和(actual为dict结构,actual['k1'] == 'v1' or null)形式 python类契约 expect_format = Matcher({'k1': 'v1'}, nullable=True) # nullable为true时允许返回null,预期null和(actual为dict结构,actual['k1'] == 'v1' or null)形式 json契约 expect_format_json = { '$Matcher': { '$values': {'k1': 'v1'}, '$params': {'nullable': True} } } # nullable为true时允许返回null,预期null和(actual为dict结构,actual['k1'] == type('v1') or null)形式 python类契约 expect_format = Like({'k1': 'v1'}, nullable=True) # nullable为true时允许返回null,预期null和(actual为dict结构,actual['k1'] == type('v1') or null)形式 json契约 expect_format_json = { '$Like': { '$values': {'k1': 'v1'}, '$params': {'nullable': True} } } # nullable为true时允许返回null,预期null和[null,{'k1':null}]形式 python类契约 expect_format = EachLike({'k1': 'v1'}, nullable=True) # nullable为true时允许返回null,预期null和[null,{'k1':null}]形式 json契约 expect_format_json = { '$EachLike': { '$values': {'k1': 'v1'}, '$params': {'nullable': True} } } # nullable为true时允许返回null,预期null和11形式 python类契约 expect_format = Term(r'^\d{2}$', example=11, nullable=True) # nullable为true时允许返回null,预期null和11形式 json契约 expect_format_json = { '$Term': { '$values': r'^\d{2}$', '$params': {'example': 11, 'nullable': True} } } # nullable为true时允许返回null,预期null和11/22/33形式 python类契约 expect_format = Enum([11, 22, 33], nullable=True) # nullable为true时允许返回null,预期null和11/22/33形式 json契约 expect_format_json = { '$Enum': { '$values': [11, 22, 33], '$params': {'nullable': True} } }
备注:nullable参数在hard_mode = True时也生效
2.{}匹配
# dict_emptiable为true时,允许返回{},预期{}和(actual为dict结构,actual['k1'] == 'v1')形式 python类契约 expect_format = Matcher({'k1': 'v1'}, dict_emptiable=True) # dict_emptiable为true时,允许返回{},预期{}和(actual为dict结构,actual['k1'] == 'v1')形式 json契约 expect_format_json = { '$Matcher': { '$values': {'k1': 'v1'}, '$params': {'dict_emptiable': True} } } # dict_emptiable为true时,允许返回{},预期{}和(actual为dict结构,actual['k1'] == type('v1'))形式 python类契约 expect_format = Like({'k1': 'v1'}, dict_emptiable=True) # dict_emptiable为true时,允许返回{},预期{}和(actual为dict结构,actual['k1'] == type('v1'))形式 json契约 expect_format_json = { '$Like': { '$values': {'k1': 'v1'}, '$params': {'dict_emptiable': True} } }
备注:dict_emptiable在hard_mode = True时也生效
3.json格式字符串匹配
# actual为"{\"k1\":\"v1\"}"json字符串格式时,先进行json.loads再校验 python类契约 expect_format = Matcher({'k1': 'v1'}, jsonloads=True) # actual为"{\"k1\":\"v1\"}"json字符串格式时,先进行json.loads再校验 json契约 expect_format_json = { '$Matcher': { '$values': {'k1': 'v1'}, '$params': {'jsonloads': True} } } # actual为"{\"k1\":\"v1\"}"json字符串格式时,先进行json.loads再校验 python类契约 expect_format = Like({'k1': 'v1'}, jsonloads=True) # actual为"{\"k1\":\"v1\"}"json字符串格式时,先进行json.loads再校验 json契约 expect_format_json = { '$Like': { '$values': {'k1': 'v1'}, '$params': {'jsonloads': True} } } # actual为"[{\"k1\":\"v1\"}]"json字符串格式时,先进行json.loads再校验 python类契约 expect_format = EachLike({'k1': 'v1'}, jsonloads=True) # actual为"[{\"k1\":\"v1\"}]"json字符串格式时,先进行json.loads再校验 json契约 expect_format = { '$EachLike': { '$values': {'k1': 'v1'}, '$params': {'jsonloads': True} } } # actual为"[11,22]"json字符串格式时,先进行json.loads再校验 python类契约 expected_format = Enum([11, 22], jsonloads=True) # actual为"[11,22]"json字符串格式时,先进行json.loads再校验 json契约 expected_format_json = { '$Enum': { '$values': {'k1': 'v1'}, '$params': {'jsonloads': True} } }
4.key不存在匹配
# key_missable为true时,允许key不存在,key存在时走正常校验;Matcher,Like,EachLike,Term和Enum类都可使用该属性 python类契约 expect_format = Matcher({ 'code': Like(0, key_missable=True), 'msg': Matcher('success', key_missable=True), 'data': EachLike(11, key_missable=True), 'age': Term(r'^\d{2}$', example=11, key_missable=True), 'num': Enum([11, 22, 33], key_missable=True) }) # key_missable为true时,允许key不存在,key存在时走正常校验;Matcher,Like,EachLike,Term和Enum类都可使用该属性 json契约 expect_format_json = { '$Matcher': { 'code': { '$Like': { '$values': 0, '$params': {'key_missable': True} } }, 'msg': { '$Matcher': { '$values': 'success', '$params': {'key_missable': True} } }, 'data': { '$EachLike': { '$values': 11, '$params': {'key_missable': True} } }, 'age': { '$Term': { '$values': r'^\d{2}$', '$params': {'example': 11, 'key_missable': True} } }, 'num': { '$Enum': { '$values': [11, 22, 33], '$params': {'key_missable': True} } }, }} # dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验 python类契约 expected_format = Matcher({ 'name': 'lilei', 'age': 12, 'sex': 'man' }, dict_key_missable=True) # dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验 json契约 expected_format_json = { '$Matcher': { '$values': { 'name': 'lilei', 'age': 12, 'sex': 'man' }, '$params': {'dict_key_missable': True} } } # dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验 python类契约 expected_format = Like({ 'name': 'lilei', 'age': 12, 'sex': 'man' }, dict_key_missable=True) # dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验 json契约 expected_format_json = { '$Like': { '$values': { 'name': 'lilei', 'age': 12, 'sex': 'man' }, '$params': {'dict_key_missable': True} } } # dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验 python类契约 expected_format = EachLike({ 'name': 'lilei', 'age': 12, 'sex': 'man' }, dict_key_missable=True) # dict_key_missable为true时,允许dict结构中的key不存在,但key不能多(hard_mode=true时),key存在时正常校验 json契约 expected_format_json = { '$EachLike': { '$values': { 'name': 'lilei', 'age': 12, 'sex': 'man' }, '$params': {'dict_key_missable': True} } }
5.多类型匹配
# actual数据为type(11)或type('11'),extra_types可以添加多个示例数据,对基础数据类型(int,float,boolean,str,None)示例有效,对list dict等类型无效 python类契约 expect_format = Like(11, extra_types=['11']) # actual数据为type(11)或type('11'),extra_types可以添加多个示例数据,对基础数据类型(int,float,boolean,str,None)示例有效,对list dict等类型无效 json契约 expect_format_json = { '$Like': { '$values': 11, '$params': {'extra_types': ['11']} } } # actual数据为[type(11)]或[type('11')],extra_types可以添加多个示例数据,对基础数据类型示例(int,float,boolean,str,None)有效,对list dict等类型无效 python类契约 expect_format = EachLike(11, extra_types=['11']) # actual数据为[type(11)]或[type('11')],extra_types可以添加多个示例数据,对基础数据类型示例(int,float,boolean,str,None)有效,对list dict等类型无效 json契约 expect_format_json = { '$EachLike': { '$values': 11, '$params': {'extra_types': ['11']} } }
备注:
1. key_missable在hard_mode = True时也生效
2. key_missable针对actual_data本身的key,dict_key_missable针对actual_data字典中的key,可以同时生效
注意:异常匹配场景越多,代表接口数据格式越不规范
七.配合unittest+requests使用
import unittest, requests, HtmlTestRunner, os from pactverify.matchers import Matcher, Like, EachLike, Term, Enum, PactVerify class PactTest(unittest.TestCase): def test_config_2(self): url = 'http://127.0.0.1:8080/configV2' config_rsp = requests.get(url) config_contract_format = Matcher({ "msg": "success", "code": 200, 'name': Enum(['lili', 'xiaohei']), 'addr': Term(r'深圳*', example='深圳宝安'), "data": EachLike({ "type_id": 249, "name": "王者荣耀", "order_index": 1, "status": 1, "subtitle": " ", "game_name": "王者荣耀" }), 'data_2': EachLike({ "type_id": 249, "name": "王者荣耀", "order_index": 1, "status": 1, "subtitle": " ", "game_name": "王者荣耀" }, minimum=1) }) mPactVerify = PactVerify(config_contract_format) try: actual_rsp_json = config_rsp.json() mPactVerify.verify(actual_rsp_json) assert mPactVerify.verify_result == True except Exception: # 自定义错误信息,输出到HTMLTestRunner中 err_msg = 'PactVerify_fail,verify_result:{},verify_info:{}'.format(mPactVerify.verify_result, mPactVerify.verify_info) self.fail(err_msg) if __name__ == '__main__': current_path = os.path.abspath(__file__) current_dir = os.path.abspath(os.path.dirname(current_path) + os.path.sep + ".") suite = unittest.defaultTestLoader.discover(current_dir, pattern="test_*.py") runner = HtmlTestRunner.HTMLTestRunner(combine_reports=True, report_name="MyReport", add_timestamp=False) runner.run(suite)
八.优点总结
1.显式定义接口断言格式,接口断言更加直观
2.可复用接口实际响应数据来定义契约
3.能根据响应数据生成json契约
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size pactverify-2.0.1-py3-none-any.whl (16.6 kB) | File type Wheel | Python version py3 | Upload date | Hashes View |
Filename, size pactverify-2.0.1.tar.gz (24.4 kB) | File type Source | Python version None | Upload date | Hashes View |
Close
Hashes for pactverify-2.0.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 770324583670cced36d62829d191f7ed0a09673fa4a3cdd1ae7bdcda16fcbc99 |
|
MD5 | d8067697eaa19d6bf996cd4c487fb252 |
|
BLAKE2-256 | 792c01fee221e3a75a833d6aae081d381558db0ccb4ce8db6463257c686b0232 |