pytest-recordingSkill pytest-recording

pytest-recording是一个用于Python测试的HTTP交互录制与回放工具,基于VCR.py封装,通过录制API请求和响应到YAML格式的cassette文件中,实现测试的确定性、可重复性和离线执行。该技能主要用于自动化测试开发,特别适用于涉及外部API调用的单元测试和集成测试场景,能有效提高测试效率、减少网络依赖并保护敏感数据。关键词:pytest-recording, VCR.py, HTTP录制, 测试回放, API测试, 自动化测试, Python测试, cassette文件, 敏感数据过滤

测试 0 次安装 0 次浏览 更新于 3/2/2026

name: pytest-recording description: 使用pytest-recording(VCR.py)在测试中录制和回放HTTP交互。适用于编写VCR测试、管理cassette文件、配置VCR选项、过滤敏感数据或调试录制的HTTP响应。

pytest-recording(VCR.py)测试

概述

pytest-recording封装了VCR.py,将HTTP交互录制为YAML格式的cassette文件,从而实现无需实时API调用的确定性测试。

快速参考

运行测试

# 运行所有测试(使用现有cassette文件)
uv run pytest tests/

# 运行单个测试
uv run pytest tests/test_module.py::test_function

# 使用新响应重写所有cassette文件
uv run pytest tests/ --vcr-record=rewrite

# 仅录制缺失的cassette文件
uv run pytest tests/ --vcr-record=new_episodes

# 禁用VCR(进行实时请求)
uv run pytest tests/ --disable-recording

录制模式

模式 标志 行为
none --vcr-record=none 仅回放,若无cassette则失败
once (默认) 若无cassette则录制
new_episodes --vcr-record=new_episodes 录制新请求,保留现有
all --vcr-record=all 总是录制,覆盖现有
rewrite --vcr-record=rewrite 删除并重新录制所有cassette

编写VCR测试

使用VCR的基本测试:

import pytest

@pytest.mark.vcr()
def test_api_call():
    response = my_api_function()
    assert response.status_code == 200

自定义cassette名称:

@pytest.mark.vcr("custom_cassette_name.yaml")
def test_with_custom_cassette():
    pass

多个cassette:

@pytest.mark.vcr("cassette1.yaml", "cassette2.yaml")
def test_with_multiple_cassettes():
    pass

conftest.py中的VCR配置

vcr_config fixture控制VCR行为:

@pytest.fixture(scope="module")
def vcr_config():
    return {
        # 从录制中过滤敏感头部
        "filter_headers": ["authorization", "api-key", "x-api-key"],

        # 过滤查询参数
        "filter_query_parameters": ["key", "api_key", "token"],

        # 按这些标准匹配请求
        "match_on": ["method", "scheme", "host", "port", "path", "query"],

        # 忽略某些主机(不录制)
        "ignore_hosts": ["localhost", "127.0.0.1"],

        # 录制模式
        "record_mode": "once",
    }

过滤敏感数据

对于LLM提供商,过滤认证信息:

@pytest.fixture(scope="module")
def vcr_config():
    return {
        "filter_headers": [
            "authorization",      # OpenAI, Anthropic
            "api-key",            # Azure OpenAI
            "x-api-key",          # Anthropic
            "x-goog-api-key",     # Google AI
        ],
        "filter_query_parameters": ["key"],
    }

响应处理

使用pytest_recording_configure进行高级处理:

def pytest_recording_configure(config, vcr):
    vcr.serializer = "yaml"
    vcr.decode_compressed_response = True

    # 清理响应头部
    def sanitize_response(response):
        response['headers']['Set-Cookie'] = 'REDACTED'
        return response

    vcr.before_record_response = sanitize_response

Cassette文件位置

默认情况下,cassette文件存储在tests/cassettes/中,按测试模块组织:

tests/
├── cassettes/
│   └── test_module/
│       └── test_function.yaml
└── test_module.py

调试

Cassette未找到

如果测试因“找不到cassette”而失败:

  1. 使用--vcr-record=once运行以创建缺失的cassette文件
  2. 检查cassette路径是否与测试位置匹配
  3. 验证cassette文件是否存在且为有效的YAML

请求不匹配

如果VCR无法匹配请求:

  1. 检查vcr_config中的match_on标准
  2. 比较cassette中的请求详情与实际请求
  3. 使用--vcr-record=new_episodes添加缺失的交互

过时的Cassette文件

当API响应发生变化时:

  1. 删除特定的cassette文件并重新运行测试
  2. 或使用--vcr-record=rewrite刷新所有cassette文件

查看Cassette内容

# 查看cassette文件
cat tests/cassettes/test_module/test_function.yaml

# 在cassette文件中搜索特定内容
grep -r "error" tests/cassettes/

添加新的LLM提供商

添加新提供商时:

  1. 识别认证头部(查阅提供商文档)
  2. 将头部添加到vcr_config中的filter_headers
  3. 将任何查询参数认证添加到filter_query_parameters
  4. 使用--vcr-record=once测试以创建cassette文件
  5. 验证cassette文件不包含机密信息

常见提供商认证:

提供商 需要过滤的头部
OpenAI authorization
Anthropic x-api-key, authorization
Azure OpenAI api-key
Google AI x-goog-api-key
Cohere authorization

最佳实践

  1. 绝不提交机密信息:始终过滤认证头部/参数
  2. 使用描述性测试名称:Cassette名称源自测试名称
  3. 保持cassette文件小巧:仅模拟需要测试的内容
  4. 在PR中审查cassette文件:检查敏感数据泄露
  5. 定期重新生成:API响应可能随时间变化
  6. 适当使用作用域:共享fixture使用scope="module"