apiAutoTest
先軟文介紹下:apiAutoTest是個人和眾多測試同行參與(提供新的需求)的一個介面測試工具專案.
目前功能
- [x] 測試前後資料庫備份操作,個人理解算資料清洗
- [x] 各介面之間的測試資料依賴
- [x] 自定義擴充套件函式定義,解決部分加密演算法
- [x] 後置sql,結果用於依賴或者斷言(select 語句只能查出第一條)1. * *
- [x] 實際結果可動態提取,與預期結果絕對
==
- [x] 可選用例失敗重跑機制
- [x] 基於mitmproxy錄製介面生成用例檔案
重大更新(個人認為)
在之前的一篇自定義函式簡單實現方式時,有提醒到語法可能出現衝突,所以在前兩天更新時已經統一了語法${}
無論是使用依賴引數還是自定義方法都使用${}
, 為了避免每次使用其他介面返回提取jsonpath
表示式在用例中的冗餘(或許也提高了些效能,之前版本是會儲存整個響應內容的),用例中增加了提取引數
來實現形式如下
{
// key -> id 為其他介面使用時的引數變數 用法 ${id}
"id": "$.data.id" // $.data.id 實則為jsonpath表示式 從當前響應中提取id值
}
相關使用文件: 可到原始碼Readme.md 檔案中前往 線上文件檢視
本次更新
**本次更新內容使用演示視訊: 點選訪問B站 **
契機
有同志,希望有個錄製功能來減少手寫引數的時間
根本
基於mitmproxy, 抓包微信小程式 使用其提供的擴充套件API, 通過mitmproxy 實現代理之後捕獲到HTTP/HTTPS請求,並把請求已追加的形式新增到excel中,當錄製完成務必使用ctrl + c 關閉錄製,將生成一個完成的用例資料檔案
可指定錄製包含請求地址的介面
如何錄製
-
開啟本機代理
-
修改
tools\recording.py
中配置抓包請求地址, 用例生成路徑 -
apiAutoTest
根目錄下執行mitmweb -s tools\recording.py
-
正常去使用就行了,當不需要錄製的時候 在上面這個視窗
Ctrl + C
停止錄製,然後關閉本機代理
錄製的用例
因為預設錄製的url是完整的url,所以如果直接用這個檔案,請把config/config.yaml
中的serve
dev 基準地址換成""
, 因為條件有限沒法覆蓋測試很多內容這快功能可能會有Bug
, 目前個人測試了Graphql
規範介面的錄製,RestFul
規範介面錄製, 不排除其他的無法完整的生成用例檔案
需要注意Excel 單元格字元數限制問題, Graphql規範介面非常容易出現不可寫入的情況, 單從業務介面來說應該不容易出現此類問題
執行錄製的用例
config/config.yaml
修改基準地址dev
為""
,指定使用錄製的用例檔案
server:
# 本地介面服務
test: http://127.0.0.1:8888/
# https://space.bilibili.com/283273603 演示專案後端服務來自
# dev: http://www.ysqorz.top:8888/api/private/v1/
dev: ''
# 基準的請求頭資訊
request_headers: {}
file_path:
test_case: data/case_data1.xls # 指定使用那個用例,這裡使用了錄製的用例
report: report/
log: log/run{time}.log
....
執行結果
實現原始碼
#!/usr/bin/env/ python3
# -*- coding:utf-8 -*-
"""
@Project: apiAutoTest
@File :recording.py
@Author:zy7y
@Date :2021/5/21 22:07
@Desc : 錄製介面,生成用例檔案
基於mitmproxy實現
參考資料:
https://blog.wolfogre.com/posts/usage-of-mitmproxy/
https://www.cnblogs.com/liuwanqiu/p/10697373.html
"""
import json
import mitmproxy.http
import xlwt
# 上傳檔案介面不能錄入檔案引數 , excel單元格限制: Exception: String longer than 32767 characters
from mitmproxy import ctx
class Counter:
def __init__(self, filter_url: str, filename: str = "data/case_data1.xls"):
"""
基於mitmproxy抓包生成用例資料
:param filter_url: 需要過濾的url
:param filename: 生成用例檔案路徑
"""
self.url = filter_url
self.excel_row = [
'編號',
'用例標題',
'請求頭',
'介面地址',
'是否執行',
'請求方式',
'入參關鍵字',
'上傳檔案',
'請求資料',
'提取引數',
'後置sql',
'預期結果']
self.cases = [self.excel_row]
self.counter = 1
self.file = filename
def response(self, flow: mitmproxy.http.HTTPFlow):
"""
mitmproxy抓包處理響應,在這裡彙總需要資料
:param flow:
:return:
"""
if self.url in flow.request.url:
# 編號
number = "C" + str(self.counter)
# 標題
title = "mitmproxy錄製介面" + str(self.counter)
try:
token = flow.request.headers["Authorization"]
except KeyError:
token = ''
header = json.dumps({"Authorization": token})
data = flow.request.text
# 請求地址,config.yaml 裡面基準環境地址 寫 空字串
method = flow.request.method.lower()
url = flow.request.url
try:
content_type = flow.request.headers['Content-Type']
except KeyError:
content_type = ''
if 'form' in content_type:
data_type = "data"
elif 'json' in content_type:
data_type = 'json'
else:
data_type = 'params'
if '?' in url:
data = url.split('?')[1]
data = self.handle_form(data)
# 預期結果
expect = json.dumps(
{".": json.loads(flow.response.text)}, ensure_ascii=False)
# 日誌
ctx.log.info(url)
ctx.log.info(header)
ctx.log.info(content_type)
ctx.log.info(method)
ctx.log.info(data)
ctx.log.info(flow.response.text)
case = [
number,
title,
header,
url.split('?')[0],
"是",
method,
data_type,
"",
data,
"",
"",
expect]
self.cases.append(case)
self.counter += 1
# 檔案末尾追加
self.excel_cases()
def excel_cases(self):
"""
對二維列表cases進行迴圈並將內容寫入單元格中
:return:
"""
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('用例資料')
for x in range(len(self.cases)):
for y in range(len(self.cases[x])):
worksheet.write(x, y, self.cases[x][y])
try:
workbook.save(self.file)
except Exception as e:
print(e)
def handle_form(self, data: str):
"""
處理 Content-Type: application/x-www-form-urlencoded
預設生成的資料 username=admin&password=123456
:param data: 獲取的data 類似這樣 username=admin&password=123456
:return:
"""
data_dict = {}
if data.startswith('{') and data.endswith('}'):
return data
try:
for i in data.split('&'):
data_dict[i.split('=')[0]] = i.split('=')[1]
return json.dumps(data_dict)
except IndexError:
return ''
addons = [
Counter("http://www.ysqorz.top:8888/api/private/v1/")
]
"""
mitmweb -s tools\recording.py 啟動
ctrl + C 停止 並生成完整用例
"""
參考資料
https://docs.mitmproxy.org/stable/
https://blog.wolfogre.com/posts/usage-of-mitmproxy/
https://www.cnblogs.com/liuwanqiu/p/10697373.html