如何防止HTTP测试偷偷连接真实网络?pytest-recording block_network网络隔离完整指南 如何防止HTTP测试偷偷连接真实网络pytest-recording block_network网络隔离完整指南【免费下载链接】pytest-recordingA pytest plugin powered by VCR.py to record and replay HTTP traffic.项目地址: https://gitcode.com/gh_mirrors/py/pytest-recording跑 pytest 时是否遇到过测试偷偷访问了真实 API——断言偶然通过却产生了副作用请求或者 CI 因为外部服务限流而莫名变慢。pytest-recording 是基于 VCR.py 的 pytest 插件能录制和回放 HTTP 流量并内置了block_network 网络隔离能力只要启用它任何绕过磁带的真实网络请求都会被直接拦截让你彻底防止 HTTP 测试偷偷连接真实网络。为什么 HTTP 测试需要网络隔离很多团队已经用 VCR 磁带cassette回放请求但仍会漏网遗漏的请求某个测试忘了打pytest.mark.vcr或代码路径里藏着一处requests.get测试就真的连上了线上接口副作用真实创建订单、发送邮件、扣减配额测试跑一次生产数据动一次不稳定外部接口改版或限流测试套件随机失败敏感信息外泄Authorization 头等凭证可能随真实请求离开机器。网络隔离解决的就是最后一道防线无论测试里写了什么只要不该出网就让它出不了网。block_network 是如何断网的pytest-recording 的网络隔离实现在 src/pytest_recording/network.py 中核心思路是在底层动手脚给 socket 连接装上门卫socket.socket.connect和socket.socket.connect_ex会被替换为内部函数network_guard对应源码中的make_network_guard。它只检查两个条件套接字是否为网络型AF_INET/AF_INET6或 Unix 型AF_UNIX目标主机是否命中allowed_hosts正则白名单。不在白名单内直接抛出RuntimeError: Network is disabled。 注意socket.socket类本身没有被替换只有connect方法被拦截。因此本地起的真实服务如 pytest-httpbin 的 live server走本地端口时行为可控而测试结束后拦截一定会被卸载还原unblock放在finally中。pycurl 同样被拦截如果你的代码用pycurl发请求pytest-recording 会把sys.modules[pycurl]临时换成一个代理模块PyCurlWrapperCurl.perform()时先解析 URL 的 host不在白名单内就抛出同样的Network is disabled错误。也就是说无论你的 HTTP 客户端走 socket 还是 libcurl都逃不过拦截。两种启用网络隔离的方式方式一给单个测试打 pytest.mark.block_network 标记最细粒度的控制只隔离指定测试pytest.mark.block_network def test_my_api(): # 这里任何真实网络请求都会抛出 # RuntimeError: Network is disabled ...标记只接受一个关键字参数allowed_hosts传其他参数会在启动时报错校验逻辑见 src/pytest_recording/validation.py。方式二--block-network 全局命令行开关想一刀切隔离整个测试套件直接在 pytest 命令上加参数pytest --block-network tests/这个开关由--block-network命令行选项实现定义于 src/pytest_recording/plugin.py 的pytest_addoption配合一个autouse的block_networkfixture在每次测试运行前后自动装上/卸掉拦截无需在测试里写任何额外代码。allowed_hosts 白名单给必要的主机开绿灯完全断网有时不现实——比如测试确实需要访问某个测试专用服务。allowed_hosts接受一组正则表达式支持三种配置途径按优先级从高到低为优先级途径示例1pytest.mark.block_network(allowed_hosts[...])标记参数pytest.mark.block_network(allowed_hosts[httpbin.*])2命令行--allowed-hosts正则1,正则2pytest --block-network --allowed-hostshttpbin.*,localhost3vcr_configfixture 的allowed_hosts键return {allowed_hosts: [httpbin.*]}匹配逻辑在network.py的is_host_in_allowed_hosts中把多个正则用|组合后对主机名做re.match。命中白名单的主机正常放行其余一律Network is disabled。pytest.mark.block_network(allowed_hosts[httpbin.*]) def test_access(): requests.get(http://httpbin.org/get) # 放行 requests.get(http://example.com) # RuntimeError: Network is disabled与 VCR 录制模式配合什么时候才允许真实请求pytest-recording 默认的 record mode 是none——不录制、不复用之外的任何真实请求。当你需要首次录制磁带时网络隔离和 VCR 是天然配合的pytest --record-modeonce --block-network tests/这条命令的语义非常清晰实现见plugin.py中block_networkfixture 的判断逻辑打了pytest.mark.vcr的测试VCR 处于录制模式允许真实请求录制出磁带其他所有测试网络继续被拦截真实请求直接报错。也就是说该录的才能录不该出的出不了录制和隔离可以同时成立而不是二选一。常见问题与注意事项本地 live server 会受影响吗拦截只针对网络型套接字像 pytest-httpbin 这类在本地起的真实 HTTP 服务其端口可通过allowed_hosts如127.0.0.*显式放行测试照常运行。Unix socket 怎么办AF_UNIX的地址同样参与白名单匹配而AF_NETLINK等既非网络型也非 Unix 型的套接字会被直接拦截。和 pytest-vcr 冲突不兼容。插件在pytest_configure中检测到pytest-vcr会立即抛出错误提示请先卸载它。拦截一定会还原吗会。blocking_context用try/finally保证即使测试中途出错socket 和 pycurl 也会恢复原状。关键源码位置延伸阅读拦截核心socket pycurl 白名单匹配src/pytest_recording/network.py命令行参数、fixture 与优先级逻辑src/pytest_recording/plugin.py标记参数校验src/pytest_recording/validation.py全部隔离行为测试用例含 pycurl、bytes/bytearray 主机名、异常还原等tests/test_blocking_network.py上手只需三步安装 pytest-recording → 用pytest.mark.block_network或--block-network打开隔离 → 按需配置allowed_hosts白名单。从此你的 HTTP 测试套件将只依赖磁带回放任何偷偷连接真实网络的行为都会在第一时间以Network is disabled的响亮报错现出原形。【免费下载链接】pytest-recordingA pytest plugin powered by VCR.py to record and replay HTTP traffic.项目地址: https://gitcode.com/gh_mirrors/py/pytest-recording创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考