pytest-rerunfailures必须通过命令行--reruns N或配置文件显式启用,默认不重试;仅对assert失败、未捕获异常等执行阶段失败生效,setup/teardown错误、skip、导入失败等不触发重试。

pytest-rerunfailures 重试机制怎么启用
必须通过命令行参数或配置文件显式开启,pytest 默认不重试任何用例。最常用的是 --reruns 参数,指定失败后重试次数,比如 --reruns 2 表示最多重试 2 次(即总共运行 3 次)。注意:不是“成功后停止”,而是“失败后尝试再跑 N 次”,哪怕中间某次成功也结束该用例执行。
常见错误是只装了包但没加参数,结果发现失败还是失败,毫无重试迹象。确认是否生效,可加 -v 看输出里有没有类似 RERUN 或 re-run 的标记。
-
--reruns 3:失败后最多再跑 3 次(共 4 次) -
--reruns-delay 1:每次重试前等待 1 秒(避免密集触发) - 在
pyproject.toml中配置更稳定:[tool.pytest.ini_options] reruns = 2 reruns_delay = 0.5
哪些失败会被重试?哪些不会
pytest-rerunfailures 只重试因断言失败(AssertionError)或未捕获异常(如 requests.exceptions.ConnectionError)导致的失败,**不重试跳过(skip)、xfail、setup/teardown 阶段崩溃、或 pytest 自身错误(如导入失败、语法错误)**。
典型误判场景:用例里手动 raise 了一个自定义异常但没继承 Exception,或者用了 sys.exit() —— 这些不会被识别为“可重试失败”,直接终止。
立即学习“Python免费学习笔记(深入)”;
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
- ✅ 会被重试:
assert response.status_code == 200失败、time.sleep(0.1); assert False - ❌ 不会重试:
pytest.skip("skip me")、@pytest.mark.xfail、import nonexistent_module - ⚠️ 注意:
KeyboardInterrupt和SystemExit也不会重试,它们属于信号级中断
如何给单个用例或类定制重试策略
用 @pytest.mark.flaky 装饰器可以覆盖全局设置,对特定用例单独控制。它支持 reruns 和 reruns_delay 两个关键字参数,优先级高于命令行和配置文件。
适合用于已知不稳定但又不想全局开重试的接口测试,比如依赖第三方服务的调用。
@pytest.mark.flaky(reruns=3, reruns_delay=2)
def test_third_party_api():
assert requests.get("https://httpbin.org/delay/2").status_code == 200
- 装饰器仅作用于当前函数;类上使用则影响类内所有测试方法
- 如果同时用了
@pytest.mark.parametrize,每个参数组合独立计数重试次数 - 不要在 fixture 里加这个装饰器——fixture 不是测试用例,加了无效
重试日志和结果怎么看
重试过程会在 pytest 输出中以不同颜色或前缀标出。默认情况下,首次失败显示为 F,重试成功显示为 .,最终失败仍为 F;若重试后成功,该用例整体算通过,但会在详细输出里注明 “RERUN”。
关键点:pytest 报告中的“总用例数”包含重试次数,但“通过数”只统计最终状态。容易误以为“跑了 10 次却只报 3 个失败”,其实是 7 个用例里有 3 个最终失败,其余 4 个可能各重试了 2 次才成功。
- 加
--tb=short可避免堆栈刷屏,聚焦失败根源 - 用
--junitxml=report.xml生成 XML 报告时,每个重试会产生独立的<testcase>条目,含rerun="true"属性 - CI 环境里别只看 “passed/failed” 总数,要解析日志确认是否真有不稳定用例反复失败

















