
DeepSeek结合HAR包提升测试差异代码覆盖率
通过 HAR 包解析与差异代码分析相结合,测试工程师可以高效生成接口测试用例并快速覆盖差异代码。本方案依托阿里百炼 API 和 pytest 框架,具有极强的落地实践性,是测试工程师提升效率、解决差异覆盖的利器。如果你正在为覆盖率发愁,不妨试试这个方法!
在测试交付的紧张节奏下,差异代码覆盖率成为测试工程师绕不开的难题。而“DeepSeek”这种差异代码分析技术与 HAR 包结合的方式,则为高效生成接口测试用例提供了新思路。通过解析 HAR 包并结合差异代码分析工具(如阿里百炼 API),可以快速生成接口测试用例并结合 pytest 框架执行,覆盖绝大部分差异代码。
本文将从HAR 包解析、接口用例生成到pytest 执行,为测试工程师提供一套完整、可落地的解决方案,并附带实战代码!想获取完整的接口测试框架源码?记得关注文末公众号获取哦!
背景与问题
测试工程师的日常难题:
- 差异代码覆盖率低:新版本交付时,差异代码无法快速覆盖,存在漏测风险。
- 测试用例编写耗时:从零设计接口用例效率低,尤其在时间紧迫的交付场景下。
- 缺乏工具支撑:缺少自动化工具,无法快速生成用例覆盖差异代码。
解决方案思路:
- 利用 HAR 包(HTTP Archive)记录接口调用数据,快速生成基础接口测试用例。
- 结合 阿里百炼 API 提取差异代码对应的接口列表,补充未覆盖的接口测试用例。
- 使用 pytest 框架 执行用例,验证差异代码的功能,实现快速覆盖交付。
解决方案分步实现
1. HAR 包解析并生成基础接口用例
1.1 不使用接口测试框架
HAR 包是浏览器或抓包工具(如 Chrome DevTools、Fiddler、Postman)生成的 HTTP 请求记录文件,包含完整的接口调用信息,包括 URL、请求方法、Header、Body 等。
示例代码:解析 HAR 并生成 pytest 用例
以下代码解析 HAR 文件,将接口请求信息转化为 pytest 可执行的测试用例。这样就可以直接执行这些用例,只需更换请求头里的鉴权信息。在无接口用例框架的情况下也不失为一种好的方法。
import json
from typing import List
def parse_har_to_pytest(har_file: str) -> List[dict]:
"""
解析 HAR 文件并生成 pytest 测试用例
"""
with open(har_file, "r", encoding="utf-8") as f:
har_data = json.load(f)
test_cases = []
for entry in har_data["log"]["entries"]:
request = entry["request"]
method = request["method"]
url = request["url"]
headers = {header["name"]: header["value"] for header in request["headers"]}
body = request.get("postData", {}).get("text", None)
test_cases.append({
"method": method,
"url": url,
"headers": headers,
"body": body
})
return test_cases
def generate_pytest_file(test_cases: List[dict], output_file: str):
"""
根据解析的测试用例生成 pytest 文件
"""
with open(output_file, "w", encoding="utf-8") as f:
f.write("import pytest\nimport requests\n\n")
for i, case in enumerate(test_cases):
f.write(f"def test_case_{i}():\n")
f.write(f" url = '{case['url']}'\n")
f.write(f" method = '{case['method']}'\n")
f.write(f" headers = {case['headers']}\n")
f.write(f" body = {repr(case['body'])}\n")
f.write(f" response = requests.request(method, url, headers=headers, data=body)\n")
f.write(f" assert response.status_code == 200\n\n")
# 示例调用
har_file = "example.har" # HAR 文件路径
pytest_file = "test_generated.py" # 输出的 pytest 测试文件路径
test_cases = parse_har_to_pytest(har_file)
generate_pytest_file(test_cases, pytest_file)
print(f"pytest 测试文件生成成功:{pytest_file}")
功能解析:
parse_har_to_pytest
:解析 HAR 文件,提取接口的 URL、方法、Headers 和 Body,生成标准化的用例数据结构。generate_pytest_file
:将用例数据结构转化为 pytest 测试文件,每个接口生成一个测试函数。
执行结果:
生成的 test_generated.py
文件可直接使用 pytest 执行:
pytest test_generated.py
1.2 使用接口测试框架
使用接口测试框架,则可将har解析为兼容接口用例框架的yml文件。
示例代码:解析 HAR 并生成兼容接口测试框架的yml文件
import json
from utils.yml_utils import YamlUtil
from urllib.parse import urlparse, unquote
import re
get_case_list = []
post_case_list = []
with open('har包路径.har', encoding='utf-8') as f:
content = json.loads(f.read())
log_content = content['log']
entries_content = log_content['entries']
# 这里是要过滤掉的api
filter_url_keyword = [
'/shopping/cart/num',
'/instances/count',
'.css',
'.js',
]
for entries in entries_content:
case_info = {}
filter_flag = False # 过滤标志位
request_content = entries['request']
method = request_content['method'].upper()
url_ = request_content['url']
for keyword in filter_url_keyword:
if keyword in url_:
filter_flag = True
break
if filter_flag:
continue
if method == 'GET':
url_ = url_.split('?')[0]
# case_info['headers'] = request_content['headers']
query_string = request_content['queryString']
params = {}
for query_param in query_string:
new_key = None
new_value = None
for key, value in query_param.items():
if key == 'name':
new_key = value
elif key == 'value':
value = unquote(value)
new_value = value
params[new_key] = new_value
case_info['params'] = params
elif method == 'POST':
headers = request_content['headers']
for header in headers:
if header['name'] == 'Content-Type':
case_info['Content-Type'] = header['value']
request_data = request_content.get('postData', None)
if request_data:
request_data = request_data.get('text', '')
if not request_data:
params = {}
else:
try:
if 'application/json' in request_data:
request_data = json.loads(request_data)
if isinstance(request_data, dict):
params = request_data.get('text', '')
elif 'form-data' in request_data:
# 利用正则表达式提取参数及其值
pattern = r'Content-Disposition: form-data; name="([^"]+)"\s+([^------]+)'
matches = re.findall(pattern, request_data, re.DOTALL)
# 创建字典以存储参数
params_dict = {key: value.strip() for key, value in matches}
# 转换为 JSON 字符串
json_result = json.dumps(params_dict, ensure_ascii=False)
params = json.loads(json_result)
except Exception as e:
print(type(request_data))
print(request_data)
else:
params = {}
case_info['params'] = params
response_content = entries['response']
# print(response_content)
response_content_dict = response_content.get('content', None)
if response_content_dict:
response_text = json.loads(response_content_dict.get('text', None))
if response_text:
response_keys = list(response_text.keys())
if 'message' in response_keys:
case_info['validator_key'] = 'message'
case_info['validator_value'] = response_text['message']
else:
case_info['validator_key'] = None
case_info['validator_value'] = None
case_info['can_failed'] = True
case_info['needed_save_data'] = False
case_info['needed_replace_data'] = False
case_info['marks'] = ['regression']
url_ = url_.replace('http://xxx', '') # 因接口测试框架中已配置了host,这里手动去掉
case_info['url'] = url_
case_info['method'] = method
case_info['case_title'] = url_
case_info['needed_save_data_key'] = None
case_info['needed_save_data_order'] = None
case_info['tmp_data_file_name'] = None
case_info['feature'] = url_
case_info['sub_dir'] = None
if method == 'GET':
get_case_list.append(case_info)
elif method == 'POST':
post_case_list.append(case_info)
print(get_case_list)
print(post_case_list)
get_case_file_name = 'case_Har包生成的get请求用例.yml'
post_case_file_name = 'case_Har包生成的post请求用例.yml'
YamlUtil(get_case_file_name).write_yaml_1(get_case_list) # 这里是框架的写入yml文件
YamlUtil(post_case_file_name).write_yaml_1(post_case_list)
功能解析:
parse_har_to_pytest
:解析 HAR 文件,提取接口的 URL、方法、Headers 和 Body,生成适配接口测试框架的yml文件。效果如下图所示。
2. 差异代码分析并补充用例
借助 阿里百炼 API 对比两个版本的代码,获取差异文件和对应的接口列表,补充未覆盖的接口测试用例。这里因每个公司的情况不同,具体如何获取需自行处理。
示例代码:调用阿里百炼 API 结合har包生成接口用例
import requests
ALI_BAILIAN_API_URL = "https://api.bailian.aliyun.com/diff"
API_KEY = "your_api_key" # 替换为实际的 API Key
def get_diff_interfaces(old_version: str, new_version: str):
"""
获取差异代码对应的接口列表
"""
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
}
payload = {
"old_version": old_version,
"new_version": new_version
}
response = requests.post(ALI_BAILIAN_API_URL, headers=headers, json=payload)
if response.status_code == 200:
diff_data = response.json()
print("差异代码分析成功!")
return diff_data.get("interfaces", [])
else:
print(f"差异代码分析失败,状态码:{response.status_code}")
print(response.text)
return []
# 示例调用
diff_interfaces = get_diff_interfaces("v1.0.0", "v1.1.0")
print(f"差异接口列表:{diff_interfaces}")
功能解析:
- 调用阿里百炼 API 获取差异接口列表,可进一步结合 HAR 包解析的基础用例,补充未覆盖的接口。
要通过调用阿里百炼 DeepSeek-R1 提供的推理 API 来解析 HAR 文件中的接口信息,并将这些信息存储在 YML 文件中,接着进行参数化推理以生成全面的接口测试用例,您可以按照以下步骤进行操作:
步骤一:解析 HAR 文件
-
获取 HAR 文件:
- 确保您已抓取并保存了 HAR 文件,包含了需要测试的接口请求信息。
-
解析 HAR 文件:
使用 Python 中的haralyzer
库解析 HAR 文件:from haralyzer import HarParser, HarPage # 加载 HAR 文件 with open('your_file.har', 'r') as har_file: har_data = har_file.read() # 解析 HAR 文件 har_parser = HarParser(har_data) entries = har_parser.har_data['log']['entries'] # 提取接口信息 api_info = [] for entry in entries: request = entry['request'] api_info.append({ 'url': request['url'], 'method': request['method'], 'headers': request['headers'], 'postData': request.get('postData', {}) })
步骤二:存储到 YML 文件
- 将接口信息存储为 YML:
使用PyYAML
库将提取的信息写入 YML 文件:import yaml # 存储到 YML 文件 with open('api_test_cases.yml', 'w') as yaml_file: yaml.dump(api_info, yaml_file, default_flow_style=False)
步骤三:调用 DeepSeek-R1 推理 API
- 准备推理 API 请求:
根据存储的 YML 文件,读取用例并构造 API 请求:import requests import yaml # 读取 YML 文件 with open('api_test_cases.yml', 'r') as yaml_file: test_cases = yaml.safe_load(yaml_file) # 设置请求头 headers = { "Content-Type": "application/json", "Authorization": "Bearer <Your Access Token>" } # 调用 DeepSeek-R1 推理 API 进行参数化推理 for case in test_cases: payload = { "query": case['url'], "parameters": case.get('postData', {}).get('text', {}) } response = requests.post("https://api.yourservice.com/deepseek", headers=headers, json=payload) print(response.json())
步骤四:生成全面的接口测试用例
-
生成测试用例:
将返回的推理结果整理为测试用例,可以根据需要自定义每个测试用例的格式。test_results = [] for case, result in zip(test_cases, responses): # 假设 responses 是收集的所有响应 test_results.append({ 'url': case['url'], 'method': case['method'], 'expected_response': result, # 根据推理结果设置期望的响应 'status_code': response.status_code }) # 存储生成的测试用例 with open('generated_test_cases.yml', 'w') as yaml_file: yaml.dump(test_results, yaml_file, default_flow_style=False)
通过以上步骤,您可以实现对 HAR 文件的解析,将接口信息存储到 YML 文件中,并使用阿里百炼 DeepSeek-R1 的推理 API 进行参数化推理,最终生成覆盖全面的接口测试用例。这一流程不仅提高了测试的效率,还确保了用例的全面性和准确性。
3. pytest 执行与覆盖率验证
生成的 pytest 测试文件可直接运行,并通过覆盖率工具(如 coverage.py)验证差异代码的覆盖情况。
示例代码:pytest 测试执行与覆盖率报告
# 安装 pytest 和 coverage
pip install pytest coverage
# 执行用例并生成覆盖率报告
coverage run -m pytest test_generated.py
coverage html
执行后会生成 htmlcov/index.html
,可通过浏览器查看覆盖率报告。
方案优势
- 效率高:HAR 包解析结合差异代码分析,快速生成接口测试用例,节省 80% 的用例设计时间。
- 差异覆盖率高:阿里百炼 API 精确定位差异代码,与实际接口调用结合,覆盖率显著提升。
- 自动化强:结合 pytest 框架自动化执行,无需手动干预。如果不结合已有的接口测试框架,则需要手动维护接口的鉴权信息,执行用例前需更新token或cookie等信息。
总结
通过 HAR 包解析与差异代码分析相结合,测试工程师可以高效生成接口测试用例并快速覆盖差异代码。本方案依托阿里百炼 API 和 pytest 框架,具有极强的落地实践性,是测试工程师提升效率、解决差异覆盖的利器。如果你正在为覆盖率发愁,不妨试试这个方法!
更多推荐
所有评论(0)