pytest测试框架pytest-rerunfailures插件重试失败用例

Pytest提供了丰富的插件来扩展其功能,介绍下插件pytest-rerunfailures ,用于在测试用例失败时自动重新运行这些测试用例。

pytest-rerunfailures官方显示的python和pytest版本限制:

  • Python 3.8+
  • pytest 7.2 或更新版本

此插件可以通过以下可选先决条件从硬崩溃中恢复:

pytest-xdist 2.3.0 或更新版本

目前最新版本是14.0,支持了pytest 8.0, 8.1版本,但是不支持最新的pytest 8.2版本,所以大家使用时要注意版本的配套,可以去官方网站(

https://pypi.org/project/pytest-rerunfailures/)上查看。(我自己在调试的时候下载的都是最新的版本,结果运行时一直不成功,将pytest8.2.2卸载然后安装8.1.2版本就成功了。)

pytest-rerunfailures安装

使用pip命令安装: pip install pytest-rerunfailures (安装在pytest工程所运行的python环境,python的安装目录或者虚拟环境目录,可以参考之前文章查看运行环境pycharm配置pytest运行环境)

通过pycharm安装:打开设置,按照如下图中安装插件(windows系统)

pytest-rerunfailures运行

重新运行所有失败用例并指定重试次数

使用--reruns命令行选项并指定希望测试用例运行的最大次数,比如命令pytest --reruns 5或者pytest --reruns=5,同时执行过程中失败的fixture函数或者setup_class也将被重新执行。

举例:设置5条用例,第5条用例通过断言assert 1 != 1时用例预期失败,然后我们重试3次,并使用pytest-html生成测试报告。

执行参数类似如下:pytest.exe -v --reruns 3 --html=report/report.html test_case.py

执行结果如下:5条用例执行耗时4.32s

执行后测试报告如下:显示第5条测试用例重新执行了3次

重新运行所有失败用例并指定延迟时间

使用--reruns-delay命令行选项,表示在启动下一次测试重新运行之前想要等待的秒数。比如pytest --reruns 5 --reruns-delay 1

举例:设置5条用例,第5条用例通过断言assert 1 != 1时用例预期失败,然后我们重试3次,每次延迟1秒,并使用pytest-html生成测试报告。

执行参数类似如下:pytest.exe -v --reruns 3 --reruns-delay 1 --html=report/report.html test_case.py

执行后预期耗时比上面的4.32s再增加3s。

实际执行后结果:确实是显示耗时7.32s,证明每次重试时都延迟了1s执行。

重新运行所有与特定表达式匹配的失败项

使用--only-rerun命令行选项表示仅重新运行与特定表达式列表匹配的失败,例如,仅重新运行与AssertionError匹配的错误:

$ pytest --reruns 5 --only-rerun AssertionError

多次传递标志会累积参数,比如以下操作只会重新运行与AssertionError或ValueError匹配的错误:

$ pytest --reruns 5 --only-rerun AssertionError --only-rerun ValueError

举例:设置5条用例,第3条用通过使用不存在的变量预期报NameError,第4条用例通过value = 1/0预期报ZeroDivisionError,第5条用例通过断言assert 1 != 1时用例预期报AssertionError

PS:第5条用例 通过assert 1 != 1会断言失败,但并不会返回AssertionError,所以重试时会捕捉不到,此时我们使用try...except语句,通过raise语句返回AssertionError。

我们重试3次,并使用pytest-html生成测试报告。

执行参数类似如下:pytest.exe -v --reruns 3 --only-rerun

AssertionError--only-rerun NameError --html=report/report.html test_case.py

执行后预期只重试第3条用例和第5条用例

实际执行后结果如预期一样。

重新运行除匹配某些表达式之外的所有失败

使用--rerun-except命令行选项仅重新运行与特定表达式列表不匹配的失败用例。例如,以下内容将仅重新运行除匹配AssertionError之外的错误:

$ pytest --reruns 5 --rerun-except AssertionError

多次传递标志会累积参数,例如下面的例子只会重新运行与AssertionError或OSError不匹配的错误:

$ pytest --reruns 5 --rerun-except AssertionError --rerun-except OSError

举例:还是使用上面定义的5条用例,我们重试3次,并使用pytest-html生成测试报告。

执行参数类似如下:pytest.exe -v --reruns 3 --rerun-except AssertionError --rerun-except NameError --html=report/report.html test_case.py

执行后预期只重试第4条用例,排除第3和第5条用例

实际执行后结果如预期一样。

使用@pytest.mark.flaky标记测试用例并在失败时重新运行

我们可以将单个测试标记为不稳定,并让它们在失败时自动重新运行,而且还可以标记重试次数和延迟时间,或者其他一些参数

以下是 @pytest.mark.flaky 的参数,以及它们的详细描述:

  • reruns:当测试失败时,重新运行测试的次数。默认为 0(不重新运行)
  • reruns_delay:在每次重新运行测试时的延迟时间(秒)。默认为 0(无延迟)
  • condition: 配合reruns参数,当满足该条件时失败用例才被执行。
  • only_rerun: 配合reruns参数,仅重新运行与特定表达式列表匹配的失败用例,可传入单个值或列表
  • rerun_except:配合reruns参数,仅重新运行与特定表达式列表不匹配的失败用例,可传入单个值或列表

PS:网络上有些文章提到其他参数max_runs、min_passes、min_successes、run_with_increasing_delay 等是另一个插件Flaky 的功能。

举例 在测试用例1中标记重试3次,延迟1s

复制代码
@pytest.mark.flaky(reruns=3, reruns_delay=1)
def test_1():
  try:
      assert 1 != 1
  except AssertionError:
      raise AssertionError
  print('\n用例test_1执行成功')
  time.sleep(1)

执行命令如下:pytest.exe -v --html=report/report.html test_case.py

测试报告如下: 显示用例1被重复执行3次

那如果我们在执行命令行中还加上--reruns 3参数,结果如何?

我们执行pytest.exe -v --reruns 3 --html=report/report.html test_case.py来检验下:

结果显示: 加了参数也不会再多执行3次,两者不会冲突,加了参数只会执行那些没有被标记的失败用例。

举例:在测试用例1中标记重试3次,满足操作系统是windows32时才执行

复制代码
@pytest.mark.flaky(reruns=3, condition=sys.platform.startswith("win32"))
def test_1():
  try:
      assert 1 != 1
  except AssertionError:
      raise AssertionError
  print('\n用例test_1执行成功')
  time.sleep(1)

执行结果如下:因为我自己的电脑是win32,所以用例会被重复执行

举例:在测试用例1中标记重试3次,满足only_rerun=["AssertionError", "NameError"])错误时才执行。

复制代码
@pytest.mark.flaky(reruns=3, only_rerun=["AssertionError", "NameError"])
def test_1():
  try:
      assert 1 != 1
  except AssertionError:
      raise AssertionError
  print('\n用例test_1执行成功')
  time.sleep(1)

执行结果如下:因为用你预期报错AssertionError,满足条件所以用例会被重复执行

共勉: 东汉·班固《汉书·枚乘传》:"泰山之管穿石,单极之绠断干。水非石之钻,索非木之锯,渐靡使之然也。"

-----指水滴不断地滴,可以滴穿石头;

-----比喻坚持不懈,集细微的力量也能成就难能的功劳。

----感谢读者的阅读和学习,谢谢大家。

---祝愿大家都能够龙腾虎跃,步步高升!!!

相关推荐
sduwcgg26 分钟前
kaggle配置
人工智能·python·机器学习
__lost1 小时前
Python图像变清晰与锐化,调整对比度,高斯滤波除躁,卷积锐化,中值滤波钝化,神经网络变清晰
python·opencv·计算机视觉
海绵波波1071 小时前
玉米产量遥感估产系统的开发实践(持续迭代与更新)
python·flask
漫谈网络1 小时前
基于 Netmiko 的网络设备自动化操作
运维·自动化·netdevops·netmiko
逢生博客2 小时前
使用 Python 项目管理工具 uv 快速创建 MCP 服务(Cherry Studio、Trae 添加 MCP 服务)
python·sqlite·uv·deepseek·trae·cherry studio·mcp服务
堕落似梦2 小时前
Pydantic增强SQLALchemy序列化(FastAPI直接输出SQLALchemy查询集)
python
坐吃山猪3 小时前
Python-Agent调用多个Server-FastAPI版本
开发语言·python·fastapi
Bruce-li__3 小时前
使用Django REST Framework快速开发API接口
python·django·sqlite
小兜全糖(xdqt)3 小时前
python 脚本引用django中的数据库model
python·django
Arenaschi3 小时前
SQLite 是什么?
开发语言·网络·python·网络协议·tcp/ip