pytest-recording不自动录制HTTP请求,需vcrpy或responses配合patch客户端并正确配置record_mode、路径及match_on等参数;@pytest.mark.vcr仅触发回放逻辑,前提是cassette存在且vcrpy已正确patch对应HTTP库。

pytest-recording 本身不记录网络流量,它只管理磁带文件(cassette);真正录制 HTTP 请求必须靠 vcrpy 或 responses,且需手动 patch 客户端、设置 record_mode 和路径规则。
为什么 @pytest.mark.vcr 没生效?
这是最常见误判点:插件不会自动拦截请求,@pytest.mark.vcr 只是告诉 pytest-recording “这个测试该走回放逻辑”,但前提是——对应 cassette 文件已存在,且 vcrpy 已正确 patch 了你用的 HTTP 库。
- 没装
vcrpy:pytest-recording 不自带它,必须pip install vcrpy - 用了
httpx却没配match_on:vcrpy 默认只 patchrequests,对httpx需显式初始化 VCR 实例并传入match_on=['method', 'scheme', 'host', 'port', 'path', 'query', 'body'] - cassette 路径不对:pytest-recording 默认只扫描测试文件同级的
cassettes/目录,若放错位置(比如放在tests/根目录下),就会报No cassette found - pytest 版本不匹配:pytest ≥ 7.0 用
pytest-recording最新版;若用 pytest 6.x,必须降级到pytest-recording==0.11.0,否则AttributeError: 'Config' object has no attribute 'pluginmanager'
怎样让第一次运行就生成 cassette?
关键不是加装饰器,而是控制 record_mode 并清理旧文件。默认 record_mode='once' 只在 cassette 不存在时录制一次,已有文件就直接回放。
- 首次运行前删掉
cassettes/test_something.yaml(或整个cassettes/目录) - 显式指定
record_mode='new_episodes'可追加新请求,但要注意重复请求会覆盖原响应,可能破坏断言一致性 - 推荐写法:
@vcr.use_cassette('cassettes/test_api_get_user.yaml', record_mode='once'),路径和文件名必须和 pytest-recording 的扫描逻辑一致 - 确保测试函数里实际发了请求,比如
requests.get('https://httpbin.org/get');光有装饰器不发请求,cassette 仍是空的
requests 和 httpx 的录制差异在哪?
vcrpy 对两者的支持机制不同,参数和 patch 方式不能混用。
立即学习“Python免费学习笔记(深入)”;
-
requests:开箱即用,@vcr.use_cassette就够,无需额外配置 -
httpx:必须手动构建 VCR 实例,并传入patcher='httpx'和完整match_on列表,否则录制内容不全或比对失败 - 示例(httpx):
vcr = VCR( patcher='httpx', match_on=['method', 'scheme', 'host', 'port', 'path', 'query', 'body'])@vcr.use_cassette('cassettes/test_httpx.yaml', record_mode='once')def test_with_httpx(): resp = httpx.get('https://httpbin.org/get') - 动态字段(如 timestamp、token)会导致回放失败,得用
filter_query_parameters或before_record_response清洗,否则每次录制都生成新 cassette
真正的难点不在“怎么配”,而在“怎么确认它真正在录”——建议首次运行时加一句 print("recording...") 在请求前后,再检查 cassettes/ 目录是否生成了非空 YAML 文件;如果文件为空或根本没出现,说明 patch 失败或路径被忽略,而不是插件“没反应”。


















