背景:
最近接了一个项目,在现有的项目基础上,购买了一个新的数据源,需要将底层的数据进行更换,为了后续能够更好的扩展和维护,在替换的时候,会重新设计表结构
要求:
对外提供的接口要保持原样输出,接口入参格式和请求路径均与原来保持一致,尽可能的做到对下游无感知。设计到的接口改动比较多 ,大概有好几百个的样子吧。如果接口返回结构不一致,需要人工去确认是否对下游造成影响。(对应微服务均支持通过swagger去调用接口)
由于具体改动设计公司业务,在这里不便细说,这里简单介绍下我是怎么去对比的,供大家参考学习。
思路:
由于接口数量比较多,如果自己写脚本去录入用例的话,效率估计也没这么快。swagger上面虽然支持单个接口直接调试调用,但毕竟不支持对比,而且也不好做批量执行,万一开发改了脚本之后,再回归的话,这么多接口要回归,时间上都是个问题。
于是,决定采用postman工具去实现新旧接口的对比功能。
具体实现步骤:
1、将微服务下的所有接口导入postman中
postman是支持导入swagger-ui的json文件的,但是可能存在版本的兼容性问题导致导入报解析错误,可以间接的借助apifox工具,先将swagger的数据导入apifox,再从apifox导出文件,然后再导入postman
2、在postman的前置脚本Pre-request Script中写脚本先调用旧服务的接口发送请求,然后新接口直接在postman中发送请求
Pre request Script中的脚本参考:
var old_request = pm.request.clone(); const host = pm.environment.get("oldHost"); const port = pm.environment.get('oldPort'); old_request.update(old_request.url.host=host); old_request.update(old_request.url.port=port); pm.sendRequest(old_request,function (error, old_response){ if (error) { console.log(error); } else { if(old_response.responseSize==0) { pm.environment.set("old_response",{}); } else { console.log('old_response',old_response.json()) ; pm.environment.set("old_response", old_response.json()); } } });
3、然后在Postman的Tests中加入断言脚本,对比新旧接口的返回结果是否一致。
说明:
由于重构过程中,可能部分接口没办法完全做到数据返回一致,再加上对js的用法不太熟练,这里可以采用Python脚本编写断言的脚本,思路就是:
用python写一个后端服务,启动服务之后,对外提供几个断言的接口,然后在postman中写js发请求调用http请求去请求自己封装的python断言接口即可。
Python服务封装接口如下:
from flask import Flask, redirect, url_for, request import json import deepdiff app = Flask(__name__) @app.route('/assert_json', methods=['POST']) def assert_json(): if request.method == 'POST': # 默认返回内容 return_dict = {'status_code': '200', 'message': '处理成功', 'data': None} # 判断传入的json数据是否为空 if len(request.get_data()) == 0: return_dict['status_code'] = '500' return_dict['message'] = '请求参数为空' return json.dumps(return_dict, ensure_ascii=False) old_response = request.json.get("old_response") new_response = request.json.get("new_response") compare_result = deepdiff.DeepDiff(old_response, new_response, ignore_order=True) return_dict['data'] = compare_result print('compare_result', compare_result) # 对参数进行操作 return json.dumps(return_dict, ensure_ascii=False) @app.route('/assert_array', methods=['POST']) def assert_array(): if request.method == 'POST': # 默认返回内容 return_dict = {'status_code': '200', 'message': '暂不支持该格式断言,后续扩展', 'data': None} return json.dumps(return_dict, ensure_ascii=False) if __name__ == '__main__': app.run(debug=True)
在python中对比接口的话 ,采用的是deepdiff,可以很轻松的对比出返回结果为json格式的两个json的差异。
然后在Postman中的Tests脚本中调用自己的断言方法的脚本如下:
var old_response = pm.environment.get("old_response"); //console.log('old_response',old_response) ; var new_response = pm.response; if(new_response.responseSize==0) { new_response = {} } else { new_response = new_response.json(); } console.log('new_response',new_response) ; url = '' // 判断返回结果是数组还是json,调用不同的方法去断言(转成字符串,判断是以[还是{开头) if (JSON.stringify(new_response).toString().startsWith('{')) { url = 'http://127.0.0.1:5000/assert_json' } else if(JSON.stringify(new_response).toString().startsWith('[')){ url = 'http://127.0.0.1:5000/assert_array' } const compareRequest = { url: url, method: "POST", header: 'Content-Type: application/json', body: { mode: 'raw', // 使用raw(原始)格式 raw: {"old_response": old_response, "new_response": new_response} //要将JSON对象转为文本发送 } }; // 发送请求 pm.sendRequest(compareRequest, function (err, res) { compare_result = res.json().data pm.environment.set("compare_result",compare_result); }); compare_result = pm.environment.get("compare_result") pm.test("对比两个接口返回结果", function () { console.log("对比result:",compare_result); pm.expect(compare_result).to.eql({}); });
以上只是对比的大概思路,可以将这些脚本放置在Collections级别的Pre-requests Script和Tests中,做通用的断言。如果针对不同的接口有不同的断言的话,可以针对Collections下的接口再进行个性化的断言。按照以上的思路,可以在postman中扩展很多原本不支持的功能哟。