在接口自动化测试中,对 HTTP 响应的处理是一个非常关键的环节。我们不仅需要从响应中提取关键字段(如 token、userId 等),还需要对接口返回结果进行断言验证,以确保接口功能符合预期。
本文将详细介绍一个基于 requests 和 jsonpath 的通用响应处理模块 result.py,它实现了两个核心功能:
- 从响应中提取指定字段并缓存
- 根据规则自动验证响应内容
该模块适用于自动化测试框架开发、接口联调、以及 API 测试等场景。
🧰 一、依赖模块介绍
import typing as t
import pytest
import allure
from requests import Response
from common.cache import cache
from common.regular import get_var
from utils.logger import logger
import json
import logging
模块 | 用途 |
typing | 类型注解,增强代码可读性 |
pytest | 断言和测试支持 |
allure | 生成测试报告 |
Response | 来自 requests,用于处理 HTTP 响应 |
cache | 自定义缓存模块,用于存储提取的变量 |
get_var | 使用 JSONPath 提取响应中的值 |
logger | 日志记录工具 |
json / logging | JSON 解析和日志输出 |
🔍 二、核心功能一:提取响应字段并缓存 —— get_result
✅ 函数定义
def get_result(r: Response, extract: t.Dict) -> None:
"""
从响应中提取指定的值并存入缓存。
:param r: HTTP 响应对象
:param extract: 包含键和 JSONPath 表达式的字典
"""
response_json = r.json()
logger.debug("响应 JSON: {}".format(response_json))
for key, jsonpath_expr in extract.items():
value = get_var(jsonpath_expr, response_json)
if value is not None:
cache.set(key, value)
logger.info(f"成功存入缓存: {key}={value}")
else:
logger.error(f"无法提取 {key} 的值,路径: {jsonpath_expr}")
raise ValueError(f"提取失败: {key} 的路径 {jsonpath_expr} 无效")
logger.debug(f"当前缓存内容: {cache.data}") # 打印完整缓存内容
with allure.step("提取返回结果中的值"):
for key in extract.keys():
allure.attach(name=f"提取 {key}", body=str(cache.get(key)))
参数说明:
- r:HTTP 响应对象(来自 requests)
- extract:一个字典,键为变量名,值为 JSONPath 表达式,用于定位响应中的字段
示例输入:
extract = {"token": "$.data.accessToken"}
作用:
- 从响应中提取 $.data.accessToken 字段的值
- 将其保存到缓存中,供后续接口使用(比如鉴权)
📌 示例代码演示
response = Response()
response._content = json.dumps({"data": {"accessToken": "12345"}}).encode('utf-8')
extract = {"token": "$.data.accessToken"}
get_result(response, extract)
执行后,token 被缓存为 "12345",可通过 cache.get("token") 获取。
🧠 实现逻辑详解
1、解析响应 JSON 内容
response_json = r.json()
2、遍历 extract 字典,提取每个字段
for key, jsonpath_expr in extract.items():
value = get_var(jsonpath_expr, response_json)
3、缓存提取值,并记录日志
if value is not None:
cache.set(key, value)
else:
raise ValueError(...)
4、Allure 报告记录提取结果
with allure.step("提取返回结果中的值"):
allure.attach(name=f"提取 {key}", body=str(cache.get(key)))
🔍 三、核心功能二:验证响应内容 —— check_results
✅ 函数定义
def check_results(response: Response, validation: t.Dict) -> None:
"""
验证响应结果是否符合预期。
:param response: HTTP 响应对象
:param validation: 验证规则字典,包含 'type', 'actual', 'expected' 键
"""
try:
# 将响应文本转换为 JSON 对象
response_json = json.loads(response.text)
# 使用 get_nested_value 函数根据路径提取实际值
actual = get_nested_value(response_json, validation['actual'])
expected = validation['expected']
# 记录调试日志
# logger.debug(f"响应内容: {response.text}")
logger.debug(f"验证规则: {validation}")
logger.debug(f"实际值: {actual}, 预期值: {validation['expected']}")
# 根据验证规则类型进行处理
if validation['type'] == 'eq':
# 比较实际值和预期值是否相等
if actual != expected:
raise AssertionError(f"验证失败(eq比较实际值和预期值是否相等): 实际值 {actual} 不等于预期值 {expected}")
elif validation['type'] == 'not_eq':
# 比较实际值和预期值是否不相等
if actual == expected:
raise AssertionError(f"验证失败(not_eq比较实际值和预期值是否不相等): 实际值 {actual} 等于预期值 {expected}")
else:
# 如果验证规则类型未知,记录错误日志并抛出异常
logger.error(f"未知的验证规则类型: {validation['type']}")
raise ValueError(f"无效的验证规则: {validation['type']}")
except Exception as e:
# 记录错误日志并重新抛出异常
logger.error(f"处理验证规则时发生错误: {e}\n原始响应内容: {response.text}")
raise e
参数说明:
- response: HTTP 响应对象
- validation: 验证规则字典,包含以下字段:
- type: 验证类型(目前支持 eq, not_eq)
- actual: JSONPath 表达式,表示实际值路径
- expected: 期望值
示例输入:
validation = {"type": "eq", "actual": "$.data.accessToken", "expected": "12345"}
作用:
- 从响应中提取实际值
- 根据验证类型判断是否满足预期条件
- 若不满足,抛出异常中断测试流程
📌 示例代码演示
validation = {"type": "eq", "actual": "$.data.accessToken", "expected": "12345"}
check_results(response, validation)
如果实际值是 "12345",则验证通过;否则抛出 AssertionError。
🧠 实现逻辑详解
1、解析响应内容为 JSON 对象
response_json = json.loads(response.text)
2、使用 JSONPath 提取实际值
actual = get_nested_value(response_json, validation['actual'])
3、根据验证类型进行比较
if validation['type'] == 'eq':
assert actual == expected
elif validation['type'] == 'not_eq':
assert actual != expected
4、异常捕获与日志记录
except Exception as e:
logger.error(f"处理验证规则时发生错误: {e}")
raise e
🔄 四、JSONPath 支持函数 —— get_nested_value
def get_nested_value(d, path):
"""
根据路径从字典中提取嵌套的值。
:param d: 字典对象
:param path: 路径字符串,例如 "data.accessToken"
:return: 提取的值,如果路径不存在则返回 None
"""
if not path.startswith('$'):
# 如果路径不是 JSONPath 格式,直接返回 None
return None
try:
# 使用 jsonpath 提取值
import jsonpath
result = jsonpath.jsonpath(d, path)
if result and len(result) > 0:
return result[0]
return None
except Exception as e:
logger.error(f"JSONPath 解析错误: {e}")
return None
该函数用于从嵌套结构中提取字段值,支持标准 JSONPath 表达式。
✅ 示例输入
d = {"data": {"accessToken": "abc"}}
path = "$.data.accessToken"
✅ 返回值
"abc"
📌 注意事项
- 如果路径不是合法的 JSONPath 格式(如未以 $ 开头),返回 None
- 如果路径不存在,也返回 None
📦 五、完整模块结构总结
方法 | 功能 |
get_result | 从响应中提取字段并缓存,供后续使用 |
check_results | 验证响应内容是否符合预期 |
get_nested_value | 支持 JSONPath 提取字段值 |
🧪 六、应用场景举例
✅ 场景 1:登录接口获取 token 并用于后续请求
# 登录接口提取 token
get_result(login_response, {"token": "$.data.accessToken"})
# 使用 token 发起其他请求
headers = {"Authorization": f"Bearer {cache.get('token')}"}
✅ 场景 2:验证接口返回状态码是否正确
validation = {"type": "eq", "actual": "$.code", "expected": 0}
check_results(response, validation)
✅ 场景 3:验证某个字段是否不为空
"abc"
📝 七、总结
这篇文章我们介绍了一个实用的小模块,专门用来处理接口返回的数据。它可以:
- 从接口响应中提取关键字段(比如 token、用户 ID 等)
- 把提取到的数据保存起来,供后续接口使用
- 自动验证接口返回是否符合预期,比如判断状态码是否正确
这个模块结构清晰、功能实用,特别适合用在自动化测试中,帮助我们更好地管理和验证接口数据。