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:
    			...
    
  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wuxianfeng023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值