必须显式配置超时策略,否则 pytest-timeout 完全不生效;它不会自动拦截死循环或阻塞 i/o,仅作为需手动指定触发条件的“守门人”。

必须显式配置超时策略,否则 pytest-timeout 完全不生效。 它不会自动拦截死循环或阻塞 I/O,只是个“守门人”,你得告诉它什么时候该拉闸。
安装后要立即启用,否则插件静默失效
装完 pip install pytest-timeout 只是注册了插件,但默认所有测试都不受控。常见错误是只装不配,结果 pytest test_deadloop.py 还是卡住不动。
- 最简验证方式:加
--timeout=1运行一个必然超时的测试,比如含time.sleep(2)的用例 —— 应该立刻报TimeoutExpired错误 - 若没反应,说明插件未触发:检查是否拼错参数(
--timeout不是--time-out),或项目里有同名自定义插件冲突 - Windows 下默认 fallback 到
thread方法,Linux/macOS 默认用signal;跨平台项目建议显式指定--timeout_method=thread避免行为不一致
三种配置方式优先级与适用场景
它们不是并列选项,而是有明确覆盖顺序:装饰器 > 命令行 > 配置文件。别指望 pytest.ini 里的 timeout=30 能管住一个标了 @pytest.mark.timeout(5) 的测试。
-
pytest --timeout=60 --timeout_method=thread:适合 CI 流水线兜底,防整个套件挂死。注意:这个值应大于 95% 正常测试耗时,否则会误杀 -
[pytest]段落写入pytest.ini或pyproject.toml:适合团队统一基线,比如 RPA 测试普遍设timeout = 120 -
@pytest.mark.timeout(8, method="thread"):仅用于已知高风险点,比如调外部 API、等待页面元素、socket 连接 —— 这里method="thread"是必须的,因为signal在 Windows 无效,且无法中断socket.connect()这类底层阻塞
超时后 fixture 清理可能失效,得手动兜底
插件强制终止测试时,teardown 阶段通常被跳过,尤其是用 signal 方式时 —— os._exit() 直接杀进程,连 finally 都不执行。这会导致临时文件残留、端口未释放、RPA 浏览器实例卡在后台。
- 关键资源操作必须用
with上下文管理器,比如with open(...) as f:、with socket.socket() as s: - RPA 场景中,不要只依赖
rpa.close()在teardown里调用;应在测试函数末尾显式加try/finally或用atexit.register()注册清理逻辑 - 避免在
setup中启动长期服务(如 mock server),改用pytest-asyncio+async with管理生命周期
真正难处理的不是超时本身,而是超时发生后你不知道代码停在哪一行 —— 插件输出的堆栈是当前所有线程快照,但主线程可能早已被信号中断。所以别只看 TimeoutExpired,得结合 --tb=short 和 stderr 里的线程 dump 定位真实阻塞点。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











