pytest-recording仅录制requests库的HTTP流量为YAML文件,依赖responses回放,不支持浏览器或非requests请求;需匹配pytest版本安装,用@pytest.mark.vcr标记测试函数触发录制/回放,支持vcr.use_cassette显式控制session,注意请求字段一致性及动态参数过滤。

pytest-recording 不能真正“录制”请求,它只是把 requests 库的 HTTP 流量存成 YAML 文件,后续回放时用 responses 模拟响应——所以别指望它能抓浏览器或非 requests 发起的请求。
安装与基础配置要匹配 pytest 版本
新版 pytest-recording(v0.12+)要求 pytest ≥ 7.0;如果用的是 pytest 6.x,得降级到 pytest-recording==0.11.0,否则会报 AttributeError: 'Config' object has no attribute 'pluginmanager'。
安装命令:
pip install pytest-recording==0.11.0 # 兼容 pytest 6.x<br>pip install pytest-recording # 默认适配 pytest ≥ 7.0
同时确保已安装 requests 和 responses(后者由插件自动依赖,但显式装上更稳妥)。
立即学习“Python免费学习笔记(深入)”;
用 @pytest.mark.vcr 标记测试函数
这是唯一触发录制/回放的开关。没加这个装饰器,插件完全不生效。
- 首次运行时,若对应 YAML 文件不存在,会自动生成(默认存于
cassettes/目录下) - 文件名默认是测试函数名 +
.yaml,比如test_fetch_user.yaml - YAML 中记录的是 request method、url、headers、body 和 response status、headers、body —— 不包含 cookies 或重定向跳转链
示例:
import pytest<br>import requests<br><br>@pytest.mark.vcr<br>def test_api_call():<br> resp = requests.get("https://httpbin.org/json")<br> assert resp.status_code == 200<br> assert "slideshow" in resp.json()录制时要注意 requests 的 session 复用问题
pytest-recording 只拦截全局 requests.request(),对自定义 requests.Session() 实例默认不生效——除非你手动 patch 它:
- 在测试里用
session = requests.Session()?得加@pytest.mark.vcr(allow_playback_repeats=True)并确保 session 调用的是标准 requests 方法 - 更稳妥的做法:用
vcr.use_cassette()上下文管理器显式包裹,支持 session 实例 - 避免在 cassette 文件里混入不同 host 的请求(比如同时录了 api.example.com 和 httpbin.org),否则回放时可能因 host 不匹配失败
显式控制示例:
import vcr<br><br>with vcr.use_cassette("test_session.yaml"): <br> session = requests.Session()<br> resp = session.get("https://httpbin.org/get")回放失败常见原因和绕过方式
最常遇到的是 CannotOverwriteExistingCassetteException 或 NoMatchError:
-
NoMatchError:请求 URL、method、query、body 任意一项和 cassette 里存的不一致 —— 注意 URL query 参数顺序、JSON body 字段顺序、headers 大小写都必须完全相同 - 想允许重复回放(比如测试中多次调用同一接口),加参数
@pytest.mark.vcr(record_mode="all")或record_mode="once"(默认) - 临时跳过录制直接回放,设环境变量
VCR_RECORD=none,或命令行加--vcr-record=none
调试建议:打开 --vcr-verbose 看插件实际匹配了哪些请求字段。
真正麻烦的是请求体含时间戳、随机 token 或签名字段——这些没法稳定回放,得用 vcr.filter_request() 或 vcr.before_record_request 预处理,否则每次录制都会生成新 cassette。


















