17.pytest的responses_validator

Pytest 的 Responses Validator 详解

1. 什么是 Responses Validator

1.1 Responses Validator 简介

responses-validator 是一个专门用于验证 HTTP 响应的 Python 库,它提供了声明式的方式来定义复杂的响应验证规则。这个库的设计理念是”验证即数据”(validation as data),将验证规则从测试代码中分离出来,使用 YAML 格式来定义验证规则。

1.2 Responses Validator 的特点

  • 🚀 易于使用:支持 YAML 配置和 Python 代码两种方式
  • 🎯 多种验证模式:支持精确匹配、通配符、正则表达式、JSON Path 等
  • 📝 详细的错误信息:验证失败时提供清晰的错误原因
  • 🔧 高度可定制:支持自定义验证函数
  • 📋 类型提示:完整支持类型注解
  • 🌟 灵活的验证规则:每个字段都支持简单和详细两种配置方式

1.3 Responses Validator 的核心优势

1.3.1 关注点分离

在传统的测试中,断言逻辑往往与代码紧密耦合,难以维护。responses-validator 将验证规则抽象到独立的 YAML 文件中,实现了”验证即数据”的模式。这样做的好处包括:

  • 测试工程师或 QA 人员可以专注于编写和维护 YAML 验证文件,无需深入了解测试框架的内部实现
  • 代码与数据分离:测试代码和验证规则分离,便于维护和修改
  • 可读性和可维护性:YAML 格式的验证规则比 Python 代码更容易阅读和管理,特别是当有很多断言时
  • 可重用性:同一套验证规则可以轻松地在不同的测试用例中重用,甚至在不同的项目中重用

1.3.2 在测试中的作用

在 pytest 测试中,responses-validator 主要用于:

  1. API 接口测试:验证 RESTful API 的各种接口响应
  2. 响应数据验证:验证 API 返回的数据格式和内容
  3. 自动化测试:在自动化测试流程中验证 HTTP 响应
  4. 接口监控:监控接口的响应是否符合预期
  5. 数据驱动测试:结合 YAML 文件实现数据驱动的测试

1.4 系统要求

  • Python 版本:Python >= 3.12
  • 依赖库:requests(或 httpx)

2. 安装 Responses Validator

2.1 使用 pip 安装

# 使用 pip 安装最新版本
pip install responses-validator

# 使用 pip 安装指定版本
pip install responses-validator==0.3.0

# 使用 pip 从国内镜像源安装(推荐)
pip install responses-validator -i https://pypi.tuna.tsinghua.edu.cn/simple

2.2 验证安装是否成功

安装完成后,可以通过以下方式验证:

# 方式一:检查版本
import responses_validator
print(responses_validator.__version__)  # 输出:0.3.0

# 方式二:尝试导入
from responses_validator import validator
print("安装成功!")

2.3 安装依赖库

responses-validator 主要与 requests 库配合使用,如果你还没有安装 requests,需要先安装:

pip install requests

如果你使用的是 httpx,也可以配合使用:

pip install httpx

3. 基础使用

3.1 YAML 模式(推荐)

YAML 模式是最推荐的使用方式,它将验证规则与测试代码完全分离。

3.1.1 基本示例

步骤一:创建 YAML 验证文件

创建一个名为 validation.yaml 的文件:

# validation.yaml
status_code: 200
headers:
  content-type: 'application/json'
json:
  id: 1
  name: "*"
text: "*success*"

步骤二:在测试中使用

import pytest
import requests
from responses_validator import validator
from yaml import safe_load

def test_api_with_yaml():
    """使用 YAML 文件进行响应验证"""
    # 加载 YAML 验证配置
    with open('validation.yaml', 'r', encoding='utf-8') as f:
        validate_config = safe_load(f)

    # 发送请求
    response = requests.get("https://api.example.com/users/1")

    # 使用 validator 进行验证(验证失败会抛出异常)
    validator(response, **validate_config)

    print("✅ 验证通过!")

3.1.2 详细说明

在上面的示例中:

  1. status_code: 200:验证响应状态码必须是 200
  2. headers: content-type: 'application/json':验证响应头中的 content-type 必须包含 application/json
  3. json: id: 1:验证 JSON 响应中必须包含 id 字段,且值为 1
  4. *`json: name: “**:验证 JSON 响应中必须包含name字段,值可以是任意内容(*` 是通配符)
  5. text: "*success*":验证响应文本中必须包含 success 字符串

3.2 Python 模式

Python 模式允许直接在代码中传递验证参数,适合简单的验证场景。

3.2.1 基本示例

import pytest
import requests
from responses_validator import validator

def test_api_with_python():
    """使用 Python 参数进行响应验证"""
    # 发送请求
    response = requests.get("https://api.example.com/users/1")

    # 方式一:验证失败时抛出异常(默认行为)
    validator(
        response,
        status_code=200,
        headers={"content-type": "application/json*"},
        json={"id": 1, "name": "*"},
        text="*success*"
    )
    print("✅ 验证通过!")

3.2.2 不抛出异常的模式

如果你希望验证失败时不抛出异常,而是返回错误信息,可以设置 raise_exception=False

import pytest
import requests
from responses_validator import validator

def test_api_without_exception():
    """验证失败时不抛出异常,返回错误信息"""
    # 发送请求
    response = requests.get("https://api.example.com/users/1")

    # 方式二:验证失败时不抛出异常,返回错误字典
    errors = validator(
        response,
        status_code=200,
        headers={"content-type": "application/json*"},
        json={"id": 1, "name": "*"},
        text="*success*",
        raise_exception=False  # 不抛出异常
    )

    if errors:
        print("❌ 验证失败:")
        for field, message in errors.items():
            print(f"  {field}: {message}")
    else:
        print("✅ 验证通过!")

3.3 两种模式的对比

特性 YAML 模式 Python 模式
可读性 ⭐⭐⭐⭐⭐ 非常好 ⭐⭐⭐ 一般
可维护性 ⭐⭐⭐⭐⭐ 非常好 ⭐⭐⭐ 一般
灵活性 ⭐⭐⭐⭐ 很好 ⭐⭐⭐⭐⭐ 非常好
适用场景 复杂验证规则、数据驱动测试 简单验证、快速测试
代码分离 ✅ 完全分离 ❌ 耦合在代码中

建议

  • 对于复杂的验证规则,推荐使用 YAML 模式
  • 对于简单的验证,可以使用 Python 模式

4. 状态码验证(status_code)

状态码验证是最基础的验证类型,用于验证 HTTP 响应的状态码是否符合预期。

4.1 单个状态码验证

验证响应状态码必须等于指定的值:

# 验证状态码必须是 200
status_code: 200

Python 代码示例

import requests
from responses_validator import validator

def test_status_code_single():
    """验证单个状态码"""
    response = requests.get("https://api.example.com/users")

    # 验证状态码必须是 200
    validator(response, status_code=200)
    print("✅ 状态码验证通过!")

4.2 通配符匹配

使用通配符 * 可以匹配一类状态码:

# 匹配所有 2xx 状态码(200, 201, 202, 204 等)
status_code: "2*"

注意:使用通配符时,必须用引号将值括起来。

Python 代码示例

import requests
from responses_validator import validator

def test_status_code_wildcard():
    """使用通配符验证状态码"""
    response = requests.post("https://api.example.com/users", json={"name": "test"})

    # 验证状态码必须是 2xx(200, 201, 202, 204 等)
    validator(response, status_code="2*")
    print("✅ 状态码验证通过!")

4.3 多个可能的状态码

使用 | 分隔符可以指定多个可能的状态码:

# 状态码可以是 200、201 或 204 中的任意一个
status_code: "200|201|204"

Python 代码示例

import requests
from responses_validator import validator

def test_status_code_multiple():
    """验证多个可能的状态码"""
    response = requests.post("https://api.example.com/users", json={"name": "test"})

    # 状态码可以是 200、201 或 204
    validator(response, status_code="200|201|204")
    print("✅ 状态码验证通过!")

4.4 复杂匹配

可以组合使用通配符和多个值:

# 匹配 2xx 或 3xx 状态码
status_code: "20*|30*"

Python 代码示例

import requests
from responses_validator import validator

def test_status_code_complex():
    """复杂的状态码匹配"""
    response = requests.get("https://api.example.com/users")

    # 匹配 2xx 或 3xx 状态码
    validator(response, status_code="20*|30*")
    print("✅ 状态码验证通过!")

4.5 实际应用示例

import pytest
import requests
from responses_validator import validator

class TestUserAPI:
    """用户 API 测试类"""

    def test_get_user_success(self):
        """测试获取用户成功"""
        response = requests.get("https://api.example.com/users/1")
        validator(response, status_code=200)

    def test_create_user_success(self):
        """测试创建用户成功"""
        data = {"name": "张三", "email": "zhangsan@example.com"}
        response = requests.post("https://api.example.com/users", json=data)
        # 创建成功可能是 201
        validator(response, status_code="200|201")

    def test_delete_user_success(self):
        """测试删除用户成功"""
        response = requests.delete("https://api.example.com/users/1")
        # 删除成功可能是 200 或 204
        validator(response, status_code="200|204")

    def test_user_not_found(self):
        """测试用户不存在"""
        response = requests.get("https://api.example.com/users/99999")
        # 用户不存在应该返回 404
        validator(response, status_code=404)

5. 文本验证(text)

文本验证用于验证 HTTP 响应的文本内容是否符合预期。支持多种验证模式。

5.1 简单字符串匹配(glob 模式)

默认使用 glob 模式(通配符匹配),支持 *? 通配符:

# 验证响应文本中包含 "success"
text: "*success*"

Python 代码示例

import requests
from responses_validator import validator

def test_text_glob():
    """使用 glob 模式验证文本"""
    response = requests.get("https://api.example.com/status")

    # 验证响应文本中包含 "success"
    validator(response, text="*success*")
    print("✅ 文本验证通过!")

5.2 数字自动转换

如果提供的是数字,会自动转换为字符串:

# 数字会自动转换为字符串
text: 12345

Python 代码示例

import requests
from responses_validator import validator

def test_text_number():
    """数字自动转换为字符串"""
    response = requests.get("https://api.example.com/count")

    # 数字会自动转换为字符串进行匹配
    validator(response, text=12345)
    print("✅ 文本验证通过!")

5.3 详细配置模式

对于更复杂的验证需求,可以使用详细配置:

5.3.1 精确匹配(same 模式)

text:
  value: "Welcome home"
  mode: same  # 精确匹配
  msg: "响应内容必须完全等于 'Welcome home'"

Python 代码示例

import requests
from responses_validator import validator

def test_text_exact():
    """精确匹配文本"""
    response = requests.get("https://api.example.com/welcome")

    # 精确匹配
    validator(
        response,
        text={
            "value": "Welcome home",
            "mode": "same",
            "msg": "响应内容必须完全等于 'Welcome home'"
        }
    )
    print("✅ 文本验证通过!")

5.3.2 正则表达式匹配(re 模式)

text:
  value: "^Welcome(?:to)?[a-zA-Z]+$"
  mode: re  # 正则表达式匹配
  msg: "响应内容必须以 'Welcome' 或 'Welcome to' 开头"

Python 代码示例

import requests
from responses_validator import validator
import re

def test_text_regex():
    """使用正则表达式验证文本"""
    response = requests.get("https://api.example.com/welcome")

    # 正则表达式匹配
    validator(
        response,
        text={
            "value": "^Welcome(?:to)?[a-zA-Z]+$",
            "mode": "re",
            "msg": "响应内容格式不正确"
        }
    )
    print("✅ 文本验证通过!")

5.3.3 自定义函数验证(function 模式)

text:
  value: "lambda text: len(text) > 100"
  mode: function  # 自定义函数验证
  msg: "响应文本长度必须大于 100 个字符"

Python 代码示例

import requests
from responses_validator import validator

def test_text_function():
    """使用自定义函数验证文本"""
    response = requests.get("https://api.example.com/article")

    # 自定义函数验证
    validator(
        response,
        text={
            "value": "lambda text: len(text) > 100",
            "mode": "function",
            "msg": "响应文本长度必须大于 100 个字符"
        }
    )
    print("✅ 文本验证通过!")

5.4 实际应用示例

import pytest
import requests
from responses_validator import validator

class TestTextValidation:
    """文本验证测试类"""

    def test_api_success_message(self):
        """验证 API 成功消息"""
        response = requests.post("https://api.example.com/users", json={"name": "test"})
        validator(response, text="*success*")

    def test_error_message_format(self):
        """验证错误消息格式"""
        response = requests.post("https://api.example.com/users", json={})
        validator(
            response,
            text={
                "value": ".*error.*",
                "mode": "re",
                "msg": "错误消息格式不正确"
            }
        )

    def test_response_length(self):
        """验证响应长度"""
        response = requests.get("https://api.example.com/data")
        validator(
            response,
            text={
                "value": "lambda text: len(text) > 500",
                "mode": "function",
                "msg": "响应内容太短"
            }
        )

6. 响应头验证(headers)

响应头验证用于验证 HTTP 响应头是否符合预期。每个响应头字段都支持文本验证的所有模式。

6.1 简单键值匹配

最简单的验证方式,直接指定响应头名称和期望值:

headers:
  content-type: "application/json"
  server: "nginx*"

Python 代码示例

import requests
from responses_validator import validator

def test_headers_simple():
    """简单响应头验证"""
    response = requests.get("https://api.example.com/users")

    # 验证响应头
    validator(
        response,
        headers={
            "content-type": "application/json",
            "server": "nginx*"
        }
    )
    print("✅ 响应头验证通过!")

6.2 详细配置模式

对于需要更精确控制的响应头,可以使用详细配置:

6.2.1 精确匹配

headers:
  content-type:
    value: "application/json"
    mode: same  # 精确匹配
    msg: "响应类型必须是 JSON"

Python 代码示例

import requests
from responses_validator import validator

def test_headers_exact():
    """精确匹配响应头"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        headers={
            "content-type": {
                "value": "application/json",
                "mode": "same",
                "msg": "响应类型必须是 JSON"
            }
        }
    )
    print("✅ 响应头验证通过!")

6.2.2 正则表达式匹配

headers:
  server:
    value: "nginx.*"
    mode: re  # 正则表达式匹配
    msg: "服务器必须是 nginx"

Python 代码示例

import requests
from responses_validator import validator

def test_headers_regex():
    """使用正则表达式验证响应头"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        headers={
            "server": {
                "value": "nginx.*",
                "mode": "re",
                "msg": "服务器必须是 nginx"
            }
        }
    )
    print("✅ 响应头验证通过!")

6.2.3 自定义函数验证

headers:
  x-rate-limit-remaining:
    value: "lambda x: int(x) > 0"
    mode: function  # 自定义函数验证
    msg: "API 调用次数限制已用完"

Python 代码示例

import requests
from responses_validator import validator

def test_headers_function():
    """使用自定义函数验证响应头"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        headers={
            "x-rate-limit-remaining": {
                "value": "lambda x: int(x) > 0",
                "mode": "function",
                "msg": "API 调用次数限制已用完"
            }
        }
    )
    print("✅ 响应头验证通过!")

6.3 混合使用

可以在同一个验证配置中混合使用简单和详细配置:

headers:
  content-type: "application/json"  # 简单配置
  server:  # 详细配置
    value: "nginx*"
    mode: glob
    msg: "服务器必须是 nginx"

Python 代码示例

import requests
from responses_validator import validator

def test_headers_mixed():
    """混合使用简单和详细配置"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        headers={
            "content-type": "application/json",  # 简单配置
            "server": {  # 详细配置
                "value": "nginx*",
                "mode": "glob",
                "msg": "服务器必须是 nginx"
            }
        }
    )
    print("✅ 响应头验证通过!")

6.4 响应头大小写不敏感

重要提示:响应头的键名会自动转换为小写进行匹配,所以 Content-Typecontent-type 是等价的。

import requests
from responses_validator import validator

def test_headers_case_insensitive():
    """响应头键名大小写不敏感"""
    response = requests.get("https://api.example.com/users")

    # 以下两种写法是等价的
    validator(response, headers={"Content-Type": "application/json"})
    validator(response, headers={"content-type": "application/json"})

    print("✅ 响应头验证通过!")

6.5 实际应用示例

import pytest
import requests
from responses_validator import validator

class TestHeadersValidation:
    """响应头验证测试类"""

    def test_content_type(self):
        """验证内容类型"""
        response = requests.get("https://api.example.com/users")
        validator(
            response,
            headers={
                "content-type": "application/json*"
            }
        )

    def test_cors_headers(self):
        """验证 CORS 响应头"""
        response = requests.options("https://api.example.com/users")
        validator(
            response,
            headers={
                "access-control-allow-origin": "*",
                "access-control-allow-methods": {
                    "value": ".*GET.*POST.*",
                    "mode": "re",
                    "msg": "CORS 配置不正确"
                }
            }
        )

    def test_rate_limit_headers(self):
        """验证限流响应头"""
        response = requests.get("https://api.example.com/users")
        validator(
            response,
            headers={
                "x-rate-limit-remaining": {
                    "value": "lambda x: int(x) > 0",
                    "mode": "function",
                    "msg": "API 调用次数限制已用完"
                },
                "x-rate-limit-reset": {
                    "value": "lambda x: int(x) > 0",
                    "mode": "function",
                    "msg": "限流重置时间无效"
                }
            }
        )

7. Cookies 验证(cookies)

Cookies 验证与响应头验证完全相同,每个 Cookie 字段都支持文本验证的所有模式。

7.1 简单键值匹配

cookies:
  session_id: "*"
  user_token: "abc*"

Python 代码示例

import requests
from responses_validator import validator

def test_cookies_simple():
    """简单 Cookies 验证"""
    response = requests.post("https://api.example.com/login", json={"username": "test"})

    validator(
        response,
        cookies={
            "session_id": "*",
            "user_token": "abc*"
        }
    )
    print("✅ Cookies 验证通过!")

7.2 详细配置模式

7.2.1 使用正则表达式验证 Cookie 格式

cookies:
  session_id:
    value: "*"
    mode: glob
    msg: "Session ID 不能为空"
  user_token:
    value: "[a-f0-9]{32}"
    mode: re
    msg: "用户 Token 格式不正确"

Python 代码示例

import requests
from responses_validator import validator

def test_cookies_regex():
    """使用正则表达式验证 Cookies"""
    response = requests.post("https://api.example.com/login", json={"username": "test"})

    validator(
        response,
        cookies={
            "session_id": {
                "value": "*",
                "mode": "glob",
                "msg": "Session ID 不能为空"
            },
            "user_token": {
                "value": "[a-f0-9]{32}",
                "mode": "re",
                "msg": "用户 Token 格式不正确(必须是 32 位十六进制字符串)"
            }
        }
    )
    print("✅ Cookies 验证通过!")

7.2.2 使用自定义函数验证 Cookie 值

cookies:
  expires:
    value: "lambda x: int(x) > 1234567890"
    mode: function
    msg: "Cookie 必须未过期"

Python 代码示例

import requests
from responses_validator import validator
import time

def test_cookies_function():
    """使用自定义函数验证 Cookies"""
    response = requests.post("https://api.example.com/login", json={"username": "test"})

    current_timestamp = int(time.time())

    validator(
        response,
        cookies={
            "expires": {
                "value": f"lambda x: int(x) > {current_timestamp}",
                "mode": "function",
                "msg": "Cookie 必须未过期"
            }
        }
    )
    print("✅ Cookies 验证通过!")

7.3 实际应用示例

import pytest
import requests
from responses_validator import validator

class TestCookiesValidation:
    """Cookies 验证测试类"""

    def test_login_sets_session(self):
        """验证登录后设置 Session Cookie"""
        response = requests.post(
            "https://api.example.com/login",
            json={"username": "test", "password": "123456"}
        )

        validator(
            response,
            cookies={
                "session_id": {
                    "value": "*",
                    "mode": "glob",
                    "msg": "登录后必须设置 Session ID"
                }
            }
        )

    def test_secure_cookie_format(self):
        """验证安全 Cookie 格式"""
        response = requests.post("https://api.example.com/login", json={"username": "test"})

        validator(
            response,
            cookies={
                "auth_token": {
                    "value": "^[a-zA-Z0-9]{64}$",
                    "mode": "re",
                    "msg": "认证 Token 格式不正确"
                }
            }
        )

8. JSON 验证(json)

JSON 验证是 responses-validator 最强大的功能,支持多种验证模式。

8.1 简单部分匹配(glob 模式,默认)

默认使用 glob 模式进行部分匹配,只要响应 JSON 包含指定的字段和值即可:

json:
  id: 1
  name: "John"

说明:实际响应可以包含其他字段,只要包含 id: 1name: "John" 即可。

Python 代码示例

import requests
from responses_validator import validator

def test_json_glob():
    """使用 glob 模式验证 JSON(部分匹配)"""
    response = requests.get("https://api.example.com/users/1")

    # 验证响应 JSON 中包含 id=1 和 name="John"
    # 实际响应可以是:{"id": 1, "name": "John", "email": "john@example.com"}
    validator(response, json={"id": 1, "name": "John"})
    print("✅ JSON 验证通过!")

8.2 数组部分匹配

对于数组,也可以进行部分匹配:

json:
  users:
    - id: 1
      name: "John"

说明:实际数组可以包含更多元素,只要包含指定的元素即可。

Python 代码示例

import requests
from responses_validator import validator

def test_json_array():
    """验证 JSON 数组"""
    response = requests.get("https://api.example.com/users")

    # 验证 users 数组中包含 id=1, name="John" 的元素
    validator(
        response,
        json={
            "users": [
                {"id": 1, "name": "John"}
            ]
        }
    )
    print("✅ JSON 验证通过!")

8.3 精确匹配(same 模式)

如果需要验证 JSON 必须完全匹配,使用 same 模式:

json:
  value:
    id: 1
    name: "John"
    email: "john@example.com"
  mode: same  # 精确匹配
  msg: "JSON 结构和内容必须完全相同"

Python 代码示例

import requests
from responses_validator import validator

def test_json_exact():
    """精确匹配 JSON"""
    response = requests.get("https://api.example.com/users/1")

    validator(
        response,
        json={
            "value": {
                "id": 1,
                "name": "John",
                "email": "john@example.com"
            },
            "mode": "same",
            "msg": "JSON 结构和内容必须完全相同"
        }
    )
    print("✅ JSON 验证通过!")

8.4 JSON Schema 验证(schema 模式)

使用 schema 模式可以验证 JSON 的结构是否符合某个 Schema,而不关心具体的值:

json:
  value:
    id: 99999
    name: "string"
    email: "email@example.com"
  mode: schema
  msg: "JSON 必须符合相同的 Schema"

说明schema 模式会验证实际 JSON 和期望 JSON 具有相同的结构(字段类型、是否必需等),但具体值可以不同。

Python 代码示例

import requests
from responses_validator import validator

def test_json_schema():
    """使用 Schema 模式验证 JSON 结构"""
    response = requests.get("https://api.example.com/users/1")

    validator(
        response,
        json={
            "value": {
                "id": 99999,  # 示例值,实际可以是任何整数
                "name": "string",  # 示例值,实际可以是任何字符串
                "email": "email@example.com"  # 示例值,实际可以是任何字符串
            },
            "mode": "schema",
            "msg": "JSON 必须符合相同的 Schema"
        }
    )
    print("✅ JSON Schema 验证通过!")

8.5 JSONPath 验证(jsonpath 模式)

使用 jsonpath 模式可以通过 JSONPath 表达式查询 JSON 数据并验证结果:

json:
  value:
    "$.users[*].id": [1, 2, 3]
    "$.users[0].name": ["John"]
    "$.total": 3
  mode: jsonpath
  msg: "JSONPath 查询结果不符合预期"

说明

  • 键是 JSONPath 表达式
  • 值是期望的结果列表
  • 如果值不是列表,会自动转换为列表

Python 代码示例

import requests
from responses_validator import validator

def test_json_jsonpath():
    """使用 JSONPath 验证 JSON"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        json={
            "value": {
                "$.users[*].id": [1, 2, 3],  # 所有用户的 ID
                "$.users[0].name": ["John"],  # 第一个用户的名称
                "$.total": 3  # 总数(会自动转换为 [3])
            },
            "mode": "jsonpath",
            "msg": "JSONPath 查询结果不符合预期"
        }
    )
    print("✅ JSONPath 验证通过!")

JSONPath 表达式示例

# 示例响应 JSON
{
    "status": "ok",
    "data": {
        "users": [
            {"id": 1, "name": "John", "age": 25},
            {"id": 2, "name": "Jane", "age": 30}
        ],
        "total": 2
    }
}

# JSONPath 表达式示例
validator(
    response,
    json={
        "value": {
            "$.status": ["ok"],  # 根级别的 status
            "$.data.users[*].id": [1, 2],  # 所有用户的 ID
            "$.data.users[0].name": ["John"],  # 第一个用户的名称
            "$.data.total": [2]  # 总数
        },
        "mode": "jsonpath"
    }
)

8.6 KeyPath 验证(keypath 模式)

keypath 模式类似于 JSONPath,但语法更简单,并且可以对每个字段使用不同的文本验证模式:

json:
  value:
    "users[0].name": "John"  # 这个字段使用文本 glob 模式
    "data.status":  # 这个字段使用文本 function 模式
      value: "lambda data: data == 'active'"
      mode: function
  mode: keypath
  msg: "KeyPath 验证失败"

Python 代码示例

import requests
from responses_validator import validator

def test_json_keypath():
    """使用 KeyPath 验证 JSON"""
    response = requests.get("https://api.example.com/users/1")

    validator(
        response,
        json={
            "value": {
                "users[0].name": "John",  # 简单文本验证
                "data.status": {  # 详细文本验证
                    "value": "lambda data: data == 'active'",
                    "mode": "function"
                }
            },
            "mode": "keypath",
            "msg": "KeyPath 验证失败"
        }
    )
    print("✅ KeyPath 验证通过!")

KeyPath 与 JSONPath 的区别

特性 JSONPath KeyPath
语法 $.users[*].id users[0].name
复杂度 复杂,功能强大 简单,易于理解
结果 列表 字符串
验证方式 所有字段都是相等验证 每个字段可以使用不同的文本验证模式
适用场景 复杂查询、批量验证 简单字段验证、需要不同验证模式

8.7 自定义函数验证(function 模式)

使用 function 模式可以编写自定义的验证函数:

8.7.1 Lambda 表达式

json:
  value: "lambda data: data.get('id', 0) > 0"
  mode: function
  msg: "用户 ID 必须大于 0"

Python 代码示例

import requests
from responses_validator import validator

def test_json_lambda():
    """使用 Lambda 表达式验证 JSON"""
    response = requests.get("https://api.example.com/users/1")

    validator(
        response,
        json={
            "value": "lambda data: data.get('id', 0) > 0",
            "mode": "function",
            "msg": "用户 ID 必须大于 0"
        }
    )
    print("✅ JSON Lambda 验证通过!")

8.7.2 模块函数

如果验证逻辑比较复杂,可以将其提取到单独的模块中:

步骤一:创建验证函数模块

创建 validators.py 文件:

# validators.py
def validate_user_response(data):
    """验证用户响应数据"""
    # 检查必需字段
    if 'id' not in data or 'name' not in data or 'email' not in data:
        return False

    # 检查 ID 是否为正整数
    if not isinstance(data['id'], int) or data['id'] <= 0:
        return False

    # 检查邮箱格式
    if '@' not in data['email']:
        return False

    return True

def validate_users_list(data):
    """验证用户列表响应数据"""
    if 'users' not in data:
        return False

    if not isinstance(data['users'], list):
        return False

    if len(data['users']) == 0:
        return False

    # 验证每个用户都有必需的字段
    for user in data['users']:
        if 'id' not in user or 'name' not in user:
            return False

    return True

步骤二:在验证中使用

json:
  value: "validators.validate_user_response"
  mode: function
  msg: "用户响应验证失败"

Python 代码示例

import requests
from responses_validator import validator

def test_json_module_function():
    """使用模块函数验证 JSON"""
    response = requests.get("https://api.example.com/users/1")

    validator(
        response,
        json={
            "value": "validators.validate_user_response",
            "mode": "function",
            "msg": "用户响应验证失败"
        }
    )
    print("✅ JSON 模块函数验证通过!")

8.8 JSON 验证模式对比

模式 用途 适用场景
glob 部分匹配 验证响应包含某些字段和值
same 精确匹配 验证响应完全匹配
schema Schema 验证 验证响应结构,不关心具体值
jsonpath JSONPath 查询 复杂查询、批量验证
keypath KeyPath 验证 简单字段验证、需要不同验证模式
function 自定义函数 复杂业务逻辑验证

8.9 实际应用示例

import pytest
import requests
from responses_validator import validator

class TestJSONValidation:
    """JSON 验证测试类"""

    def test_user_response_structure(self):
        """验证用户响应结构"""
        response = requests.get("https://api.example.com/users/1")

        # 使用 glob 模式验证部分字段
        validator(
            response,
            json={
                "id": 1,
                "name": "*",
                "email": "*@*"
            }
        )

    def test_users_list_schema(self):
        """验证用户列表 Schema"""
        response = requests.get("https://api.example.com/users")

        # 使用 schema 模式验证结构
        validator(
            response,
            json={
                "value": {
                    "users": [
                        {"id": 0, "name": "string", "email": "string"}
                    ],
                    "total": 0
                },
                "mode": "schema",
                "msg": "用户列表结构不正确"
            }
        )

    def test_user_ids_with_jsonpath(self):
        """使用 JSONPath 验证用户 ID"""
        response = requests.get("https://api.example.com/users")

        # 使用 jsonpath 模式
        validator(
            response,
            json={
                "value": {
                    "$.users[*].id": [1, 2, 3],
                    "$.total": [3]
                },
                "mode": "jsonpath",
                "msg": "用户 ID 列表不正确"
            }
        )

    def test_complex_validation(self):
        """复杂验证示例"""
        response = requests.get("https://api.example.com/users/1")

        # 使用自定义函数验证
        validator(
            response,
            json={
                "value": "lambda data: data.get('id', 0) > 0 and len(data.get('name', '')) > 0 and '@' in data.get('email', '')",
                "mode": "function",
                "msg": "用户数据验证失败"
            }
        )

9. 函数验证(function)

函数验证允许你编写自定义函数来验证整个 Response 对象,适用于复杂的验证需求。

9.1 Lambda 表达式验证

最简单的函数验证方式是使用 Lambda 表达式:

# 验证状态码
function: "lambda resp: resp.status_code == 200"

# 验证状态码范围
function: "lambda resp: 200 <= resp.status_code < 300"

# 验证 JSON 数据
function: "lambda resp: resp.json().get('status') == 'success'"

# 验证数组长度
function: "lambda resp: len(resp.json().get('data', [])) > 0"

# 验证文本内容
function: "lambda resp: 'error' not in resp.text.lower()"

# 复合条件验证
function: "lambda resp: resp.status_code == 200 and resp.json().get('total', 0) > 10"

Python 代码示例

import requests
from responses_validator import validator

def test_function_lambda_status_code():
    """使用 Lambda 验证状态码"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        function="lambda resp: resp.status_code == 200"
    )
    print("✅ 函数验证通过!")

def test_function_lambda_status_range():
    """使用 Lambda 验证状态码范围"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        function="lambda resp: 200 <= resp.status_code < 300"
    )
    print("✅ 函数验证通过!")

def test_function_lambda_json():
    """使用 Lambda 验证 JSON 数据"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        function="lambda resp: resp.json().get('status') == 'success'"
    )
    print("✅ 函数验证通过!")

def test_function_lambda_array_length():
    """使用 Lambda 验证数组长度"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        function="lambda resp: len(resp.json().get('data', [])) > 0"
    )
    print("✅ 函数验证通过!")

def test_function_lambda_text():
    """使用 Lambda 验证文本内容"""
    response = requests.get("https://api.example.com/status")

    validator(
        response,
        function="lambda resp: 'error' not in resp.text.lower()"
    )
    print("✅ 函数验证通过!")

def test_function_lambda_complex():
    """使用 Lambda 进行复合条件验证"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        function="lambda resp: resp.status_code == 200 and resp.json().get('total', 0) > 10"
    )
    print("✅ 函数验证通过!")

9.2 模块函数验证

对于复杂的验证逻辑,可以将其提取到单独的模块中:

步骤一:创建验证函数模块

创建 my_funcs.py 文件:

# my_funcs.py
def ret_true(resp):
    """总是返回 True(示例函数)"""
    print(f"调用 ret_true: resp={resp}")
    return True

def ret_false(resp):
    """总是返回 False(示例函数)"""
    print(f"调用 ret_false: resp={resp}")
    return False

def validate_response_time(resp):
    """验证响应时间"""
    if hasattr(resp, 'elapsed'):
        elapsed_seconds = resp.elapsed.total_seconds()
        return elapsed_seconds < 2.0
    return False

def validate_user_response(resp):
    """验证用户响应"""
    if resp.status_code != 200:
        return False

    try:
        data = resp.json()
        # 验证必需字段
        if 'id' not in data or 'name' not in data:
            return False
        # 验证 ID 是否为正整数
        if not isinstance(data['id'], int) or data['id'] <= 0:
            return False
        return True
    except:
        return False

def validate_users_list_response(resp):
    """验证用户列表响应"""
    if resp.status_code != 200:
        return False

    try:
        data = resp.json()
        if 'users' not in data:
            return False
        if not isinstance(data['users'], list):
            return False
        if len(data['users']) == 0:
            return False
        return True
    except:
        return False

步骤二:在验证中使用

# 导入模块函数
function: "my_funcs.validate_user_response"

# 验证响应时间
function: "my_funcs.validate_response_time"

Python 代码示例

import requests
from responses_validator import validator

def test_function_module():
    """使用模块函数验证响应"""
    response = requests.get("https://api.example.com/users/1")

    validator(
        response,
        function="my_funcs.validate_user_response"
    )
    print("✅ 函数验证通过!")

def test_function_response_time():
    """验证响应时间"""
    response = requests.get("https://api.example.com/users")

    validator(
        response,
        function="my_funcs.validate_response_time"
    )
    print("✅ 响应时间验证通过!")

9.3 函数验证的注意事项

9.3.1 函数签名

函数验证函数必须:

  • 接受一个位置参数(resp),类型为 requests.Responsehttpx.Response
  • 返回一个布尔值:True 表示验证通过,False 表示验证失败
def my_validator(resp):
    """自定义验证函数"""
    # resp 是 Response 对象
    # 返回 True 表示验证通过,False 表示验证失败
    return resp.status_code == 200

9.3.2 Lambda 表达式的安全限制

Lambda 表达式在受限环境中执行,只能使用以下内置函数:

基本类型

  • len, str, int, float, bool
  • list, dict, tuple, set

数学函数

  • abs, max, min, sum

逻辑函数

  • any, all

其他安全函数

  • sorted, reversed, enumerate, zip, range
  • isinstance, hasattr, getattr

允许的模块

  • re(用于正则表达式)

不允许的操作

  • 文件操作
  • 网络请求
  • 导入其他模块(除了 re
  • 执行系统命令

9.4 实际应用示例

import pytest
import requests
from responses_validator import validator

class TestFunctionValidation:
    """函数验证测试类"""

    def test_response_time(self):
        """验证响应时间"""
        response = requests.get("https://api.example.com/users")

        validator(
            response,
            function="lambda resp: resp.elapsed.total_seconds() < 2.0"
        )

    def test_status_and_data(self):
        """验证状态码和数据"""
        response = requests.get("https://api.example.com/users")

        validator(
            response,
            function="lambda resp: resp.status_code == 200 and len(resp.json().get('data', [])) > 0"
        )

    def test_error_not_in_response(self):
        """验证响应中不包含错误"""
        response = requests.get("https://api.example.com/status")

        validator(
            response,
            function="lambda resp: 'error' not in resp.text.lower()"
        )

    def test_complex_business_logic(self):
        """复杂业务逻辑验证"""
        response = requests.get("https://api.example.com/users/1")

        # 使用模块函数进行复杂验证
        validator(
            response,
            function="my_funcs.validate_user_response"
        )

10. 完整示例

10.1 完整的 YAML 验证配置示例

创建一个完整的验证配置文件 complete_validation.yaml

# complete_validation.yaml
# 状态码验证:可以是 200 或 201
status_code: "200|201"

# 响应头验证
headers:
  # 简单配置
  content-type: "application/json*"

  # 详细配置
  server:
    value: "nginx.*"
    mode: re
    msg: "必须是 nginx 服务器"

  # 自定义函数验证
  x-rate-limit-remaining:
    value: "lambda x: int(x) > 10"
    mode: function
    msg: "API 调用次数限制不足"

# Cookies 验证
cookies:
  session_id: "*"
  auth_token:
    value: "[a-f0-9]{64}"
    mode: re
    msg: "认证 Token 格式不正确"

# 文本验证
text:
  value: "*success*"
  mode: glob
  msg: "响应文本必须包含 success"

# JSON 验证(使用 JSONPath)
json:
  value:
    "$.data[*].id": [1, 2, 3]
    "$.meta.total": [3]
    "$.status": ["ok"]
  mode: jsonpath
  msg: "数据结构和内容验证失败"

# 函数验证(验证响应时间)
function: "lambda resp: resp.elapsed.total_seconds() < 2.0"

10.2 在 pytest 中使用完整配置

import pytest
import requests
from responses_validator import validator
from yaml import safe_load
import os

class TestCompleteAPI:
    """完整 API 测试类"""

    @pytest.fixture
    def validation_config(self):
        """加载验证配置"""
        file_path = os.path.join(os.path.dirname(__file__), 'complete_validation.yaml')
        with open(file_path, 'r', encoding='utf-8') as f:
            return safe_load(f)

    def test_create_user_complete(self, validation_config):
        """完整的用户创建测试"""
        # 准备请求数据
        user_data = {
            "name": "张三",
            "email": "zhangsan@example.com",
            "password": "123456"
        }

        # 发送请求
        response = requests.post(
            "https://api.example.com/users",
            json=user_data
        )

        # 使用完整配置进行验证
        validator(response, **validation_config)

        print("✅ 完整验证通过!")

    def test_get_users_complete(self, validation_config):
        """完整的用户列表获取测试"""
        # 发送请求
        response = requests.get("https://api.example.com/users")

        # 使用完整配置进行验证
        validator(response, **validation_config)

        print("✅ 完整验证通过!")

10.3 数据驱动测试示例

结合 pytest 的参数化功能,可以实现数据驱动的测试:

步骤一:创建测试数据文件 test_data.yaml

# test_data.yaml
test_cases:
  - name: "创建用户成功"
    url: "https://api.example.com/users"
    method: "POST"
    data:
      name: "张三"
      email: "zhangsan@example.com"
    validation:
      status_code: "200|201"
      json:
        id: "*"
        name: "张三"

  - name: "获取用户列表"
    url: "https://api.example.com/users"
    method: "GET"
    validation:
      status_code: 200
      json:
        users: "*"
        total: "*"

  - name: "获取单个用户"
    url: "https://api.example.com/users/1"
    method: "GET"
    validation:
      status_code: 200
      json:
        id: 1
        name: "*"

步骤二:创建测试文件

import pytest
import requests
from responses_validator import validator
from yaml import safe_load
import os

def load_test_data():
    """加载测试数据"""
    file_path = os.path.join(os.path.dirname(__file__), 'test_data.yaml')
    with open(file_path, 'r', encoding='utf-8') as f:
        return safe_load(f)

@pytest.mark.parametrize(
    "test_case",
    load_test_data()['test_cases'],
    ids=lambda case: case['name']
)
def test_api_data_driven(test_case):
    """数据驱动的 API 测试"""
    # 获取测试数据
    url = test_case['url']
    method = test_case['method']
    data = test_case.get('data')
    validation = test_case.get('validation', {})

    # 发送请求
    if method.upper() == 'GET':
        response = requests.get(url)
    elif method.upper() == 'POST':
        response = requests.post(url, json=data)
    elif method.upper() == 'PUT':
        response = requests.put(url, json=data)
    elif method.upper() == 'DELETE':
        response = requests.delete(url)
    else:
        pytest.fail(f"不支持的 HTTP 方法: {method}")

    # 进行验证
    validator(response, **validation)

    print(f"✅ {test_case['name']} 验证通过!")

11. 错误处理

11.1 异常模式(默认)

默认情况下,验证失败会抛出 ResponseAssertionError 异常:

import requests
from responses_validator import validator, ResponseAssertionError

def test_with_exception():
    """验证失败时抛出异常"""
    response = requests.get("https://api.example.com/users")

    try:
        validator(response, status_code=200)
        print("✅ 验证通过!")
    except ResponseAssertionError as e:
        print(f"❌ 验证失败: {e}")
        # 可以在这里进行错误处理,比如记录日志、发送通知等
        raise  # 重新抛出异常,让 pytest 捕获

11.2 非异常模式

设置 raise_exception=False 可以返回错误信息而不抛出异常:

import requests
from responses_validator import validator

def test_without_exception():
    """验证失败时不抛出异常"""
    response = requests.get("https://api.example.com/users")

    # 不抛出异常,返回错误字典
    errors = validator(
        response,
        status_code=200,
        raise_exception=False
    )

    if errors:
        print("❌ 验证失败:")
        for field, message in errors.items():
            print(f"  {field}: {message}")
        # 可以在这里进行自定义的错误处理
    else:
        print("✅ 验证通过!")

11.3 错误信息格式

错误信息是一个字典,键是验证失败的字段名,值是对应的错误消息:

{
    "status_code": "状态码验证失败: 期望 200, 实际 404",
    "headers": {
        "content-type": "响应头 content-type 验证失败: 期望包含 'application/json', 实际 'text/html'"
    },
    "json": {
        "id": "JSON 字段 id 验证失败: 期望 1, 实际 2"
    }
}

11.4 实际应用示例

import pytest
import requests
from responses_validator import validator, ResponseAssertionError
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class TestErrorHandling:
    """错误处理测试类"""

    def test_with_logging(self):
        """验证失败时记录日志"""
        response = requests.get("https://api.example.com/users")

        try:
            validator(response, status_code=200)
            logger.info("✅ 验证通过")
        except ResponseAssertionError as e:
            logger.error(f"❌ 验证失败: {e}")
            # 记录详细的响应信息
            logger.error(f"响应状态码: {response.status_code}")
            logger.error(f"响应内容: {response.text[:500]}")  # 只记录前 500 个字符
            raise

    def test_collect_errors(self):
        """收集所有错误信息"""
        response = requests.get("https://api.example.com/users")

        errors = validator(
            response,
            status_code=200,
            headers={"content-type": "application/json"},
            json={"id": 1},
            raise_exception=False
        )

        if errors:
            # 收集所有错误
            error_messages = []
            for field, message in errors.items():
                if isinstance(message, dict):
                    # 嵌套的错误(如 headers, json)
                    for sub_field, sub_message in message.items():
                        error_messages.append(f"{field}.{sub_field}: {sub_message}")
                else:
                    error_messages.append(f"{field}: {message}")

            # 统一处理错误
            error_summary = "n".join(error_messages)
            pytest.fail(f"验证失败:n{error_summary}")

12. 最佳实践

12.1 使用 YAML 配置管理验证规则

推荐做法

# validation_rules.yaml
# 将验证规则按功能模块组织
user_api:
  get_user:
    status_code: 200
    json:
      id: "*"
      name: "*"

  create_user:
    status_code: "200|201"
    json:
      id: "*"
      name: "*"

  list_users:
    status_code: 200
    json:
      users: "*"
      total: "*"

Python 代码

import yaml
from responses_validator import validator

def load_validation_rules():
    """加载验证规则"""
    with open('validation_rules.yaml', 'r', encoding='utf-8') as f:
        return yaml.safe_load(f)

def test_user_api():
    """使用组织好的验证规则"""
    rules = load_validation_rules()
    response = requests.get("https://api.example.com/users/1")
    validator(response, **rules['user_api']['get_user'])

12.2 选择合适的验证模式

建议

  • 简单验证:使用 glob 模式(默认)
  • 精确匹配:使用 same 模式
  • 结构验证:使用 schema 模式
  • 复杂查询:使用 jsonpath 模式
  • 业务逻辑:使用 function 模式

12.3 提供清晰的错误消息

推荐做法

json:
  value:
    id: 1
  mode: glob
  msg: "用户 ID 必须是 1"  # 提供清晰的错误消息

12.4 模块化验证函数

推荐做法

将复杂的验证逻辑提取到单独的模块中:

# validators/user_validators.py
def validate_user_response(data):
    """验证用户响应"""
    # 复杂的验证逻辑
    pass

# 在验证中使用
validator(response, json={"value": "validators.user_validators.validate_user_response", "mode": "function"})

12.5 性能考虑

建议

  • 对于高频验证,优先使用简单的验证模式(glob, same)
  • 避免在 Lambda 表达式中执行复杂计算
  • 对于复杂验证,使用模块函数而不是 Lambda 表达式

12.6 测试组织结构

推荐的项目结构

project/
├── tests/
│   ├── test_user_api.py
│   ├── test_product_api.py
│   └── validations/
│       ├── user_api.yaml
│       ├── product_api.yaml
│       └── common.yaml
├── validators/
│   ├── user_validators.py
│   └── common_validators.py
└── conftest.py

13. 常见问题(FAQ)

13.1 如何验证数组中的特定元素?

问题:如何验证数组中的第一个元素?

答案:使用 JSONPath 模式:

validator(
    response,
    json={
        "value": {
            "$.users[0].name": ["John"]
        },
        "mode": "jsonpath"
    }
)

13.2 Headers 和 Cookies 是否区分大小写?

问题:响应头的键名是否区分大小写?

答案:不区分。库会自动将键名转换为小写进行匹配。Content-Typecontent-type 是等价的。

13.3 Lambda 表达式有哪些安全限制?

问题:Lambda 表达式中可以使用哪些函数?

答案:Lambda 表达式在受限环境中执行,只能使用以下内置函数:

  • 基本类型:len, str, int, float, bool, list, dict, tuple, set
  • 数学函数:abs, max, min, sum
  • 逻辑函数:any, all
  • 其他安全函数:sorted, reversed, enumerate, zip, range, isinstance, hasattr, getattr
  • 允许的模块:re(用于正则表达式)

13.4 如何同时使用简单和详细配置?

问题:可以在同一个验证中混合使用简单和详细配置吗?

答案:可以。对于任何字段,详细配置会优先于简单配置。

headers:
  content-type: "application/json"  # 简单配置
  server:  # 详细配置
    value: "nginx*"
    mode: glob
    msg: "服务器必须是 nginx"

13.5 jsonpath 和 keypath 有什么区别?

问题:什么时候使用 jsonpath,什么时候使用 keypath?

答案

特性 jsonpath keypath
语法 $.users[*].id users[0].name
复杂度 复杂,功能强大 简单,易于理解
结果 列表 字符串
验证方式 所有字段都是相等验证 每个字段可以使用不同的文本验证模式
适用场景 复杂查询、批量验证 简单字段验证、需要不同验证模式

建议

  • 需要复杂查询时使用 jsonpath
  • 需要简单字段验证且需要不同验证模式时使用 keypath

13.6 如何处理动态值验证?

问题:如何验证动态生成的值(如时间戳、随机 ID)?

答案:使用 function 模式或自定义验证函数:

import time
from responses_validator import validator

def test_dynamic_value():
    """验证动态值"""
    response = requests.get("https://api.example.com/data")

    # 使用 Lambda 验证时间戳
    current_time = int(time.time())
    validator(
        response,
        json={
            "value": f"lambda data: data.get('timestamp', 0) > {current_time - 60}",
            "mode": "function",
            "msg": "时间戳验证失败"
        }
    )

13.7 如何验证可选字段?

问题:如何验证一个字段可能存在也可能不存在?

答案:在 glob 模式下,只验证存在的字段。如果字段不存在,验证会失败。如果需要验证可选字段,可以使用 function 模式:

validator(
    response,
    json={
        "value": "lambda data: 'optional_field' not in data or isinstance(data.get('optional_field'), str)",
        "mode": "function",
        "msg": "可选字段验证失败"
    }
)

13.8 如何验证响应时间?

问题:如何验证 API 响应时间?

答案:使用 function 模式:

validator(
    response,
    function="lambda resp: resp.elapsed.total_seconds() < 2.0"
)

13.9 如何处理验证失败的情况?

问题:验证失败时应该如何处理?

答案:有两种方式:

  1. 抛出异常(默认):

    try:
    validator(response, status_code=200)
    except ResponseAssertionError as e:
    # 处理错误
    logger.error(f"验证失败: {e}")
    raise
  2. 返回错误信息

    errors = validator(response, status_code=200, raise_exception=False)
    if errors:
    # 处理错误
    for field, message in errors.items():
        logger.error(f"{field}: {message}")

14. 总结

14.1 核心概念回顾

  1. responses-validator 是一个用于验证 HTTP 响应的 Python 库
  2. 核心优势:将验证规则与测试代码分离,使用 YAML 格式定义验证规则
  3. 支持多种验证模式:状态码、文本、响应头、Cookies、JSON、函数验证
  4. 灵活的配置方式:支持简单配置和详细配置两种方式

14.2 验证类型总结

验证类型 支持的模式 适用场景
status_code 精确值、通配符、多个值 验证 HTTP 状态码
text glob, same, re, function 验证响应文本内容
headers glob, same, re, function 验证响应头
cookies glob, same, re, function 验证 Cookies
json glob, same, schema, jsonpath, keypath, function 验证 JSON 数据
function Lambda, 模块函数 自定义复杂验证

14.3 使用建议

  1. 优先使用 YAML 模式:对于复杂验证规则,推荐使用 YAML 配置文件
  2. 选择合适的验证模式:根据验证需求选择合适的模式,避免过度复杂化
  3. 提供清晰的错误消息:为重要的验证规则提供清晰的错误消息
  4. 模块化验证函数:将复杂的验证逻辑提取到单独的、可重用的函数中
  5. 性能考虑:对于高频验证,优先使用简单的验证模式

14.4 下一步学习

掌握了 responses-validator 的基础用法后,你可以:

  1. 深入学习 JSONPath:学习更复杂的 JSONPath 表达式
  2. 自定义验证函数:编写更复杂的自定义验证函数
  3. 集成到 CI/CD:将验证集成到持续集成和持续部署流程中
  4. 性能优化:优化验证性能,提高测试执行速度

15. 附录

15.1 完整示例代码

15.1.1 基础示例

import pytest
import requests
from responses_validator import validator

def test_basic_validation():
    """基础验证示例"""
    response = requests.get("https://api.example.com/users/1")

    validator(
        response,
        status_code=200,
        headers={"content-type": "application/json"},
        json={"id": 1, "name": "*"}
    )

15.1.2 YAML 配置示例

# validation.yaml
status_code: 200
headers:
  content-type: "application/json"
json:
  id: 1
  name: "*"
import pytest
import requests
from responses_validator import validator
from yaml import safe_load

def test_yaml_validation():
    """YAML 配置验证示例"""
    with open('validation.yaml', 'r', encoding='utf-8') as f:
        config = safe_load(f)

    response = requests.get("https://api.example.com/users/1")
    validator(response, **config)

15.2 常用验证模式速查表

验证需求 配置方式 示例
状态码等于 200 status_code: 200 精确匹配
状态码是 2xx status_code: "2*" 通配符
状态码是 200 或 201 status_code: "200|201" 多个值
文本包含 “success” text: "*success*" glob 模式
文本精确匹配 text: {value: "...", mode: same} same 模式
响应头包含 JSON headers: {content-type: "application/json*"} glob 模式
JSON 包含字段 json: {id: 1} glob 模式
JSON 精确匹配 json: {value: {...}, mode: same} same 模式
JSON Schema 验证 json: {value: {...}, mode: schema} schema 模式
JSONPath 查询 json: {value: {"$.users[*].id": [1,2]}, mode: jsonpath} jsonpath 模式
自定义验证 function: "lambda resp: ..." function 模式

15.3 参考资源


文档结束

希望这份详细的文档能够帮助你全面掌握 responses-validator 的使用方法!如果你在学习过程中遇到任何问题,欢迎查阅官方文档或寻求帮助。

发表评论