Pytest插件pytest-rerunfailures失败重跑

pytest,插件,rerunfailures,失败 · 浏览次数 : 163

小编点评

**测试结果:** ``` test_demo.py::test_a Sun Jan 29 09:39:35 2023RERUNtest_demo.py::test_a Sun Jan 29 09:39:37 2023PASSED ========================= 1 passed, 1 rerun in 2.13s ========================== test_demo.py:4: ValueError==================== short test summary info =================================================FAILED test_demo.py::test_a - ValueError: invalid literal for int() with base 10: 'a'==================== 1 failed, 2 rerun in 6.20s ===============================================--only-rerun ========================= 1 failed, 2 rerun in 0.06s ==================================================== ``` **分析:** 测试用例中使用了 `pytest-rerunfailures` 插件,其中有 `reruns` 参数用于重跑失败的测试,以及 `reruns_delay` 参数用于调整重跑间隔。 **重跑失败后行为:** * 如果 `reruns` 参数设置为 `3`,意味着测试将重跑 3 次。 * 如果 `reruns_delay` 参数设置为 `2`,意味着测试将在每次重跑后等待 2 秒。 * 如果 `condition` 参数设置为 `sys.platform.startswith('linux')`,则测试将在遇到 `ValueError` 时重跑。 **`--only-rerun` 参数:** 如果 `--only-rerun` 参数使用,只有遇到 `ValueError` 时才重跑测试。 **`--rerun-except` 参数:** 如果 `--rerun-except` 参数使用,仅在遇到 `ValueError` 时才重跑测试。

正文

Pytest插件pytest-rerunfailures失败重跑

安装

pip install pytest-rerunfailures

doc

https://github.com/pytest-dev/pytest-rerunfailures

https://pypi.org/project/pytest-rerunfailures/#description

  • 当前最新版本11.0(2023-1-12)
  • python>=3.7
  • pytest 6.0以上

使用方法

第一种用法:装饰器 @pytest.mark.flaky

  • 示例代码

    import pytest
    from time import ctime
    
    
    @pytest.mark.flaky(reruns=3, reruns_delay=2)
    def test_a():
        print(ctime())
        import random
    
        assert random.choice([True, False])  # 这个代码你可能直接passed了,随机的
    
    if __name__ == '__main__':
        pytest.main(['-sv',__file__])
    
  • 示例输出

    test_demo.py::test_a Sun Jan 29 09:39:35 2023
    RERUN
    test_demo.py::test_a Sun Jan 29 09:39:37 2023
    PASSED
    
    ========================= 1 passed, 1 rerun in 2.13s ==========================
    
  • 装饰器中的参数

    • reruns=重跑次数,如果都失败那么这个用例就失败了
    • reruns_delay就是重跑的间隔
  • 结果会记录你rerun的次数

  • 如果把assert改为

     assert random.choice([1, 0, 0, 0, 0])
    
  • 那你的输出很可能就是如下的

    test_demo.py:10: AssertionError
    =========================== short test summary info ===========================
    FAILED test_demo.py::test_a - AssertionError: assert 0
    ========================= 1 failed, 3 rerun in 6.20s ==========================
    

  • flaky还有一个参数

    • condition:有点类似于skipif中的条件
  • 示例代码

    import sys
    
    import pytest
    from time import ctime
    
    @pytest.mark.flaky(reruns=3, reruns_delay=2,condition=sys.platform.startswith('linux'))
    def test_a():
        print(ctime())
        import random
        assert random.choice([1, 0])
    
    
    if __name__ == '__main__':
        pytest.main(['-sv', __file__])
    
    
  • 你测试多次会发现,遇到失败的情况压根就不会重跑的,因为condition不满足

第二种用法:命令行

  • 跟多数插件一样,它也支持命令行的用法

  • 你可以这样用

    $ pytest --reruns 5 --reruns-delay 1
    
  • 但是condition并没有这个命令行,它变成了--only-rerun(确切的说也不是变,有点不太一样了)

    # 遇到AssertionError错误就重跑
    $ pytest --reruns 5 --only-rerun AssertionError
    # 遇到AssertionError或者ValueError 就重跑
    $ pytest --reruns 5 --only-rerun AssertionError --only-rerun ValueError
    
    
  • 示例代码

    def test_a():
        assert int('a')  # 会产生一个ValueError
    
    pytest -sv --reruns 2 --reruns-delay 1 --only-rerun ValueError test_demo.py
    
    test_demo.py:4: ValueError
    ==================== short test summary info =================================================
    FAILED test_demo.py::test_a - ValueError: invalid literal for int() with base 10: 'a'
    ==================== 1 failed, 2 rerun in 0.06s ===============================================
    
  • --only-rerun的意思很明确,只有遇到ValueError才重跑

  • 同样的代码,换个参数--rerun-except,除了ValueError才会重跑,遇到ValueError并不重跑

    pytest -sv --reruns 2 --reruns-delay 1 --rerun-except ValueError test_demo.py
    
    test_demo.py:4: ValueError
    ======================== short test summary info =================================================
    FAILED test_demo.py::test_a - ValueError: invalid literal for int() with base 10: 'a'
    ======================== 1 failed in 0.06s ====================================================
    
    

测试AssertionError的时候 貌似跟我预期的不太一样,可能是我眼花了。

  • 如果命令行没有-v显示的是R标记

    test_demo.py RRF  # 重跑了2次后失败了 , 对应底部的1 failed, 2 rerun in 0.06s 
    
    

部分源码

  • 命令行

    # command line options
    def pytest_addoption(parser):
        group = parser.getgroup(
            "rerunfailures", "re-run failing tests to eliminate flaky failures"
        )
        group._addoption(
            "--only-rerun",
            action="append",
            dest="only_rerun",
            type=str,
            default=None,
            help="If passed, only rerun errors matching the regex provided. "
            "Pass this flag multiple times to accumulate a list of regexes "
            "to match",
        )
        group._addoption(
            "--reruns",
            action="store",
            dest="reruns",
            type=int,
            default=0,
            help="number of times to re-run failed tests. defaults to 0.",
        )
        group._addoption(
            "--reruns-delay",
            action="store",
            dest="reruns_delay",
            type=float,
            default=0,
            help="add time (seconds) delay between reruns.",
        )
    
  • 装饰器参数

    def get_reruns_count(item):
        ...
        if "reruns" in rerun_marker.kwargs:
            ...
            
            
    def get_reruns_delay(item):
    	...
        if "reruns_delay" in rerun_marker.kwargs:
            ...
            
    def get_reruns_condition(item):
        ...
    	    if rerun_marker is not None and "condition" in rerun_marker.kwargs:
    			...
    

与Pytest插件pytest-rerunfailures失败重跑相似的内容:

Pytest插件pytest-rerunfailures失败重跑

Pytest插件pytest-rerunfailures失败重跑 安装 pip install pytest-rerunfailures doc https://github.com/pytest-dev/pytest-rerunfailures https://pypi.org/project/p

Pytest插件pytest-order指定用例顺序

Pytest插件pytest-order指定用例顺序 安装 pip install pytest-order 注意不是pytest-ordering 说起来这里有个故事 关于pytest-ordering和pytest-order https://github.com/ftobia/pytest-o

Pytest插件pytest-assume多重断言

Pytest插件pytest-assume多重断言 背景 import pytest def test_assume1(): assert 1 == 2 print('hello') assert 2 == 3 if __name__ == '__main__': pytest.main(['-sv

Pytest插件pytest-repeat重复执行

Pytest插件pytest-repeat重复执行 安装 pip install pytest-repeat doc https://pypi.org/project/pytest-repeat/ https://github.com/pytest-dev/pytest-repeat 2020年10

Python中的枚举类enum

0. 本文来历 上一篇文章,我写了Pytest插件pytest-order指定用例顺序 我当时就比较好奇它的顺序和英文的对应关系,肯定是写死的,找了下就发现在源码sorter.py中定义了一个dict如下 orders_map = { "first": 0, "second": 1, "third"

浅谈Pytest中的marker

浅谈Pytest中的marker 没有注册marker 我们写一个简单的测试 # test_demo.py import pytest @pytest.mark.login def test_demo(): assert True 你运行的话会有如下提示 test_demo.py:4: Pytest

浅谈Pytest中的warning处理

浅谈Pytest中的warning处理 没有处理warning 我们写一个简单的测试 import pytest def test_demo(): import warnings warnings.warn('test warn',DeprecationWarning) assert True if

详谈pytest中的xfail

详谈pytest中的xfail 原文链接: https://docs.pytest.org/en/7.2.x/how-to/skipping.html 链接中详细阐述了skip和xfail两种情况 xfail 应该译作expected fail,预期失败(我知道这个用例是因为某些原因会失败的) 有哪

数据驱动测试-从方法探研到最佳实践

作者:刘红妍 导读 在自动化测试实践中,测试数据是制造测试场景的必要条件,本文主要讲述了在沟通自动化框架如何分层,数据如何存储,以及基于单元测试pytest下如何执行。并通过实践案例分享,提供数据驱动测试的具体落地方案。 基本概念 数据驱动测试(DDT)是一种方法,其中在数据源的帮助下重复执行相同顺

pytest7.4版本的一个变更,可能会影响你的项目

# pytest7.4版本的一个变更,可能会影响你的项目 > 本文撰写于 2023.7.10 # 准备工作 - 项目结构如下 ``` D:\Gitee\DemoRepo (17.97MB) +-- testCases (1.03KB) | +-- conftest.py (252b) | +-- p