必须加 --reruns 参数才能启用 pytest-rerunfailures 插件的重试功能,否则即使安装插件或使用 @pytest.mark.flaky 装饰器也无效;--reruns 0 是启用机制的必要占位,配合装饰器实现函数级重试控制。

pytest-rerunfailures 安装和基础启用为什么必须加 --reruns 参数
不加 --reruns,插件压根不会重跑失败用例,哪怕你装了、写了 @pytest.mark.flaky 也没用。这是最常被忽略的启动开关。
安装后直接运行 pytest 不会触发重试,必须显式传参:
-
pytest --reruns 3:每个失败用例最多重试 3 次(含首次运行) -
pytest --reruns 2 --reruns-delay 1:重试前等 1 秒,避免瞬时环境抖动干扰判断 - 若用
pytest.ini配置,得写成addopts = --reruns 2 --reruns-delay 0.5,否则配置不生效
标记单个测试函数重试 vs 全局统一控制的区别在哪
全局参数(如 --reruns 3)对所有失败用例生效;而 @pytest.mark.flaky(reruns=2) 只作用于打标函数,两者可共存——后者优先级更高。
常见误用是以为加了装饰器就不用传 --reruns,其实仍需启用插件主开关:
立即学习“Python免费学习笔记(深入)”;
- 正确写法:
@pytest.mark.flaky(reruns=2, reruns_delay=1)+ 运行时带--reruns 0(仅启用机制,不覆盖函数级设置) - 错误写法:只加装饰器但没传任何
--reruns,日志里完全看不到重试行为 -
reruns_delay单位是秒,支持浮点数(如0.3),但某些 CI 环境高精度 sleep 可能被截断
重试时 fixture 会不会重新执行
会。每次重试都是独立的测试执行周期,setup_method、@pytest.fixture(默认 scope="function")都会重新走一遍。
这意味着:如果 fixture 里有发请求、写临时文件、启 mock server 等操作,重试时会重复执行——可能暴露竞态或资源残留问题:
- 数据库 fixture 若没清理干净,第二次重试可能因唯一约束报错,掩盖真实失败原因
- HTTP mock(如
responses或httpx.MockTransport)需确保每次重试都重置状态 - 想跳过 fixture 重跑?不行。插件不干预 fixture 生命周期,这是 pytest 底层机制决定的
reruns=0 是什么含义,为什么有人配它
--reruns 0 表示“启用重试机制,但默认不重试”,听起来矛盾,实则是为配合 @pytest.mark.flaky 的必要占位。
没有这个参数,pytest 根本不会加载 rerunfailures 的 hook,装饰器直接被忽略:
- 只配
reruns=0,再加@pytest.mark.flaky(reruns=3)→ 按装饰器执行重试 - 不配
--reruns任何值,只加装饰器 → 无重试,控制台连 “RERUN” 日志都不会输出 - CI 流水线中常把
--reruns 0写死在命令里,再靠不同分支的装饰器控制策略,避免漏配
重试逻辑本身不改变断言行为,也不会隐藏原始失败堆栈——每次重试失败都会单独记录 traceback,但最终报告只显示最后一次结果。真要定位 flaky 根因,得翻 pytest 的详细日志或开 --verbose 看每轮输出。


















