前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于mitmproxy的录制回放接口测试工具

基于mitmproxy的录制回放接口测试工具

作者头像
测试加
发布2022-06-21 16:25:39
1.2K0
发布2022-06-21 16:25:39
举报

背景

在微服务架构下,进行核心接口质量保障是非常重要的,当下比较流行的方式是契约测试,会使我们的测试效率变得更高。

另外一种方式,也可以通过解析Nginx网关日志日志拿到里面关于接口调用的信息。

最后一种极端但是常见的情况,在没有文档的情况下,可以利用mitmproxy的录制功能去解决快速的接口录制和与其他工具集成的回放。

本文仅提供一个公共解决思路,可以根据业务特性去进行进一步的定制,源码会放到结尾。

思路

  • 基于mitmproxy的mitmdump工具的扩展脚本功能作为录制端。
  • 基于requests作为回放端并且生成报告。

录制生成接口用例

我们在本地编写一个cli_replay.py的脚本,使用CSV文件地址的地址作为入参

主要思路,在response方法处拦截请求地址、请求状态码、请求头等字段,收集完这次字段后,就可以进行回放接口测试。

录制代码:

代码语言:javascript
复制
def response(flow: http.HTTPFlow):
    # 加上过滤条件
    if "igetcool-gateway.igetcool.com" in str(flow.request.pretty_url) and 'GET' in str(flow.request.method):
        # 打开保存在本地的数据文件
        #print(flow.request.get_text())
        requestInfo = {}
        requestInfo['request_url'] = str(flow.request.pretty_url)
        data = json.loads(flow.response.content)
        requestInfo['request_headers'] = create_headers(flow.request.headers)
        requestInfo['request_method'] = flow.request.method
        requestInfo['status_code'] = flow.response.status_code
        requestInfo['reason'] = flow.response.reason
        requestInfo['response_data'] = data
        requestInfo['response_headers'] = create_headers(flow.response.headers)
        requestInfo['request_time_start'] = flow.request.timestamp_start
        requestInfo['request_time_end'] = flow.request.timestamp_end
        requestInfo['response_time_start'] = flow.response.timestamp_start
        requestInfo['response_time_end'] = flow.response.timestamp_end
        requestInfo['response_time'] = requestInfo['response_time_end'] - requestInfo['request_time_start'] # 响应时间

然后保存到本地csv文件中,为了保障每次执行录制脚步的cvs文件名字是唯一的。每次启动 脚本使用当前时间戳(%Y%m%d%H%M%S)创建CSV文件。

因为CSV文件是用过,行、列保存的,所以需要把字段放到列表中。

代码语言:javascript
复制
print(requestInfo)
with open(savePath, 'a+') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerows(
        [[requestInfo['request_url'], requestInfo['request_headers'], requestInfo['request_method'],
          requestInfo['status_code'], requestInfo['response_data'], requestInfo['response_time']]])

录制命令:

代码语言:javascript
复制
mitmdump -s cli_record.py

操作app后,在控制台看到日志标记说明写入文件成功。

录制完成并且结束终端,会在本地生成20220525213209-case.csv这种文件,然后打开以后,就是刚才发送接口请求的数据。

回放生成接口用例

主要思路是解析刚才录制的CSV文件中数据,然后循环发送请求。使用requests网路库,简单封装了一个base_requests方法进行接口请求。因为一些POST接口有幂等性逻辑,所以本次只考虑GET接口请求。

我们在本地编写一个cli_replay.py的脚本,使用CSV文件地址的地址作为入参

回放执行命令:

代码语言:javascript
复制
python3 cli_replay.py /Users/xinxi/Documents/zhihu/mitmproxyRecode/20220524230852-case.csv

base_requests代码如下:

代码语言:javascript
复制
def base_requests():
    """
    基础请求
    :return:
    """
    caseList = read_case()
    apiNameList = []
    apiTimeList = []
    successes = 0
    failures = 0
    skipped = 0
    if len(caseList) > 0:
        for case in caseList:
            request_url = case[0]
            request_headers = eval(case[1])
            request_method = case[2]
            old_response_data = case[4]
            if request_method == 'GET':
                r = requests.request(method=request_method, url=request_url, headers=request_headers)

对于请求结果验证使用diff方式验证,录制的接口返回数据作为预期结果,回放生成的接口返回数据作为实际结果。

diff代码如下:

代码语言:javascript
复制
now_response_data = r.json()

print('********************* Requests URL: {} *********************'.format(r.url))
diff_data = DeepDiff(now_response_data, eval(old_response_data), ignore_order=True)  # diff 返回数据
case.append(json.dumps(eval(old_response_data), indent=4, ensure_ascii=False))
case.append(json.dumps(r.json(), indent=4, ensure_ascii=False))
case.append(json.dumps(diff_data, indent=4, ensure_ascii=False))
apiNameList.append(r.url)

生成报告

使用jinja2库生成测试报告,首先需要本地准备一个html报告模版,放到/resources/templates/目录下。这里需要懂一点前端html + css + js的知识,然后通过jinja2来给html报告模版放数据,最终生成html报告。

jinja2先从本地使用loader方法加载一个模版,然后调用render方法,渲染成最终的html报告。

生成代码方法:

代码语言:javascript
复制
def create_report(records, apiNameList, apiTimeList, successes, failures, skipped):
    """
    生成测试报告
    :return:
    """
    reportFolder = os.path.join(currentPath, 'reports')
    if not os.path.exists(reportFolder):
        os.makedirs(reportFolder)
    report_path = os.path.join(reportFolder, "CaseReport{}.html".format(time.strftime("%Y%m%d%H%M%S")))
    try:
        env = Environment(loader=PackageLoader('resources', 'templates'))
        template = env.get_template("template.html")
        html_content = template.render(html_report_name="接口测试报告", records=records, apiNameList=apiNameList,
                                       apiTimeList=apiTimeList,successes=successes,failures=failures,skipped=skipped)
        with open(report_path, "wb") as f:
            f.write(html_content.encode("utf-8"))
            print('报告地址: {}'.format(report_path))
    except Exception as e:
        print(e)

报告设计从四部分组成:

  • 通过率: 判断接口状态是200为成功,否则认识不通过,当然这里只是演示而已,可以根据实际业务逻辑自行判断。
  • 接口响应时间: 记录每个接口的响应时间,使用柱状图表示结果。
  • 接口列表: 按照请求的顺序展示,包含字段: 请求地址、请求方法、状态码。
  • diff结果

在接口列表中,点击Detail按钮,可以看到三段结构。在对比结果展示的数据是预期结果和实际数据进行对比。

如果出现diff差异说明,存在一定的差异性。但是不一定是有问题,比如下面的diff的差异在参与过学习的人数,本来就是动态变化的,所以diff出现不一样是符合业务需要的。

diff结果如下:

代码语言:javascript
复制
{
    "values_changed": {
        "root['data']['studyNum']": {
            "new_value": 202223,
            "old_value": 202337
        },
        "root['data']['studyNumCopy']": {
            "new_value": "202223人参与过学习",
            "old_value": "202337人参与过学习"
        }
    }

结语

本文就简单介绍了,基于mitmproxy的录制回放接口测试工具。在实际工作中,也可以快速开发一些小工具提高工作效率和快速验证结果。

工具地址:

https://github.com/xinxi1990/mitmproxyRecode

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 测试加 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 思路
    • 录制生成接口用例
      • 回放生成接口用例
        • 生成报告
        • 结语
        相关产品与服务
        文件存储
        文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档