tep整合mitmproxy錄製流量自動生成用例

測試開發剛哥發表於2022-02-19

使用

操作過程非常簡單,流程如下:

image-20220219091400872

配置過濾域名

必須配置,不然會有很多無效流量造成資料冗餘。

image-20220219091435056

啟動代理

「示例」使用了反向代理,tep自帶FastApi啟動Mock服務:

image-20220219090328752

實際」使用正向代理,並手動配置代理。命令說明在utils/mitm.py檔案中有:image-20220219091648039

錄製流量

「示例」通過Postman發起請求:

image-20220219090605499

實際」在網頁上點點點。

image-20220219092021797

自動生成用例

用例就在tests/mitm實時生成好了,用例檔名為當前時間:

image-20220219091131224

每錄製一個請求,就能在測試用例中看到實時新增了一條測試步驟:

    # 介面描述
    # 資料
    # 請求
    response = request(
        "{method}",
        url="{url}",
        headers={headers},
        {body_grammar}
    )
    # 資料提取
    # var = response.jmespath("expression")
    # 斷言
    assert response.status_code < 400

錄製完成以後,就可以再次編輯測試用例完善它。

原理

utils/mitm.py原始碼如下:

#!/usr/bin/python
# encoding=utf-8

# mitmproxy錄製流量自動生成用例

import os
import time

from mitmproxy import ctx

project_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
tests_dir = os.path.join(project_dir, "tests")
# tests/mitm
mitm_dir = os.path.join(tests_dir, "mitm")
if not os.path.exists(mitm_dir):
    os.mkdir(mitm_dir)
# 當前時間作為檔名
filename = time.strftime("%Y%m%d_%H_%M_%S", time.localtime()) + ".py"
case_file = os.path.join(mitm_dir, filename)
# 生成用例檔案
template = """from tep.client import request


def test():
"""
if not os.path.exists(case_file):
    with open(case_file, "w", encoding="utf8") as fw:
        fw.write(template)


class Record:
    def __init__(self, domains):
        self.domains = domains

    def response(self, flow):
        if self.match(flow.request.url):
            # method
            method = flow.request.method.lower()
            ctx.log.error(method)
            # url
            url = flow.request.url
            ctx.log.error(url)
            # headers
            headers = dict(flow.request.headers)
            ctx.log.error(headers)
            # body
            body = flow.request.text or {}
            ctx.log.error(body)
            with open(case_file, "a", encoding="utf8") as fa:
                fa.write(self.step(method, url, headers, body))

    def match(self, url):
        if not self.domains:
            ctx.log.error("必須配置過濾域名")
            exit(-1)
        for domain in self.domains:
            if domain in url:
                return True
        return False

    def step(self, method, url, headers, body):
        if method == "get":
            body_grammar = f"params={body}"
        else:
            body_grammar = f"json={body}"
        return f"""
    # 介面描述
    # 資料
    # 請求
    response = request(
        "{method}",
        url="{url}",
        headers={headers},
        {body_grammar}
    )
    # 資料提取
    # var = response.jmespath("expression")
    # 斷言
    assert response.status_code < 400
"""


# ==================================配置開始==================================
addons = [
    Record(
        # 過濾域名
        [
            "http://www.httpbin.org",
            "http://127.0.0.1:5000"
        ],
    )
]
# ==================================配置結束==================================

"""
==================================命令說明開始==================================
# 正向代理
mitmdump -s mitm.py
# 反向代理
mitmdump -s mitm.py --mode reverse:http://127.0.0.1:5000 --listen-host 127.0.0.1 --listen-port 8000
==================================命令說明結束==================================
"""

通過mitmproxy命令啟動代理後,獲取當前時間作為檔名在tests/mitm下生成用例檔案,給addons新增外掛Record類,通過response鉤子捕獲請求資訊,對請求進行域名過濾,域名匹配成功的請求就使用測試步驟程式碼模板,填充method、url、headers、body資料,追加到測試用例檔案中。

自動生成的用例只支援tep風格。我也考慮過同時相容tep、mvc、httprunner,但是實際編寫過程式碼後,我仍然堅持認為tep風格是我最喜歡的編寫方式,儘量貼近原生,可以減少出錯風險,同時獲得更多程式碼自由。

想體驗的大佬可以升級或安裝tep的0.9.7版本,使用tep startproject demo建立專案即可。

參考資料:

基於mitmproxy實現介面錄製 https://testerhome.com/topics/29457

mitmproxy生成httprunner指令碼 https://testerhome.com/topics/30204

相關文章