在复杂的接口测试场景中,尤其是当多个接口之间存在强依赖关系时,如何高效地保存和使用接口的请求和响应参数,成为了一项挑战。今天,我将为大家揭秘一种使用pytest测试框架实现这一目标的方法。
场景描述:
在实际测试过程中,我们常常需要从前置接口获取一些关键参数(如token、user_id),并将这些参数用于后续接口的测试。为了使测试用例更加灵活和可维护,我们需要将这些参数动态地替换到后续的接口请求中。
解决方案:
1. 上下文管理
首先,我们需要定义一个全局的context
字典,用于存储和共享接口之间的动态数据。
global_context = {
"request": {},
"response": {},
"global": {}
}
2. 参数解析器
接下来,我们实现一个递归解析器,用于解析占位符(如$response.data.token
)。
import re
def resolve_placeholders(data, context):
if isinstance(data, str):
matches = re.findall(r"$([\w.]+)", data)
for match in matches:
keys = match.split('.')
value = get_nested_value(context, keys)
if value is not None:
data = data.replace(f"${{{match}}}", str(value))
return data
elif isinstance(data, dict):
return {k: resolve_placeholders(v, context) for k, v in data.items()}
elif isinstance(data, list):
return [resolve_placeholders(item, context) for item in data]
else:
return data
def get_nested_value(data, keys):
for key in keys:
if isinstance(data, dict) and key in data:
data = data[key]
else:
return None
return data
3. 保存动态数据
在每次接口执行后,我们需要将需要保存的参数存储到上下文中。
def save_to_context(response, context, save_mapping):
for key, path in save_mapping.items():
value = get_nested_value(response, path.split('.'))
if value is not None:
context["global"][key] = value
4. 测试框架实现
结合之前的框架,整合参数解析器和动态数据保存逻辑。
import pytest
import requests
import yaml
# 加载测试用例
test_cases = load_test_cases("test_cases.yml")
@pytest.mark.parametrize("case", test_cases)
def test_api(case):
# 1. 解析请求参数(占位符替换)
request_data = resolve_placeholders(case["request"], global_context)
# 2. 发送请求
response = requests.request(
method=request_data["method"],
url=request_data["url"],
headers=request_data.get("headers"),
json=request_data.get("body")
)
# 3. 保存请求和响应数据到上下文
context["request"][case["name"]] = request_data
context["response"][case["name"]] = response.json()
# 如果存在保存规则,将指定字段保存到上下文
save_mapping = case.get("save", {})
save_to_context(response.json(), global_context, save_mapping)
# 4. 验证响应
expected_data = resolve_placeholders(case["expected"], global_context)
assert response.status_code == expected_data["status_code"]
for key, value in expected_data.get("body", {}).items():
assert value == get_nested_value(response.json(), key.split('.'))
5. 测试用例示例
调整test_cases.yml
文件,支持动态保存和参数化。
test_cases:
- name: "用户登录"
request:
method: POST
url: "http://example.com/api/login"
headers:
Content-Type: "application/json"
body:
username: "test_user"
password: "test_password"
expected:
status_code: 200
body:
token: "$response.data.token"
user_id: "$global.user_id"
save:
token: "data.token"
user_id: "data.user_id"
- name: "获取用户信息"
request:
method: GET
url: "http://example.com/api/users/$global.user_id"
headers:
Authorization: "Bearer $global.token"
expected:
status_code: 200
body:
user_id: "$global.user_id"
username: "test_user"
context
字典存储动态数据,支持跨接口依赖。$response.data.token
)动态替换参数。save
配置支持更多动态参数的保存。这种方式适用于复杂的接口测试场景,尤其是多接口之间存在强依赖关系时,非常高效且易于维护。希望这篇文章能为大家带来一些启发和帮助!
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
Copyright 2005-2024 yuanmayuan.com 【源码园】 版权所有 备案信息
声明: 本站非腾讯QQ官方网站 所有软件和文章来自互联网 如有异议 请与本站联系 本站为非赢利性网站 不接受任何赞助和广告