zoukankan      html  css  js  c++  java
  • pytest失败重跑插件: pytest-rerunfailures使用与坑(全网独家精华)

    背景

    在编写接口case的时候,我们常遇到一个这样的问题:

    测试环境不稳定偶发接口超时(和服务无关,纯粹是环境问题),然后执行接口case也因此偶发失败。比如同一个接口case跑五次,其中有两次失败,另外三次都是成功的,这种偶发性的环境问题就需要我们手动重跑(还不一定能够通过)。有没有一个比较好的机制,保证case能够尽最大努力通过测试呢?

    这里我们介绍pytest的一个失败重跑插件:pytest-rerunfailures

    介绍

    pytest-rerunfailures是一个通过重跑机制来消除不稳定失败的pytest插件。

    项目地址:https://github.com/pytest-dev/pytest-rerunfailures

    安装

    安装&运行要求:

    • Python 3.6~3.9, or PyPy3
    • pytest 5.0+

    安装插件

    sudo pip(pip3) install pytest-rerunfailures

    使用pytest-rerunfailures

    使用方式有两种:

    • 命令行参数
    • 装饰器方式

    命令行参数模式

    示例case:test_demo.py

    #!/usr/bin/env python3
    #!coding:utf-8
    import pytest
    import random
    
    def test_simple_assume():
        #每次case运行的值为1或者2,具有随机性
        r = random.randint(1,2)
        assert r == 1

    如果我们直接运行pytest test_demo.py,那么每次运行的结果会具有一定随机性(可能成功也可能失败)

    如果使用pytest-rerunfailures指定执行多次,只要执行次数足够多,那么遇到结果成功的机会就会更多。

    例子1

    指定失败重跑最大次数为10:pytest --reruns 10

    如下图,我们看到一共跑了次,第一次结果失败,所以重跑了第二次,最终结果用R标注。(如果跑一次就成功,结果应该是'.')

    例子2

    指定失败重跑最大次数为10,重跑间隔为1秒pytest --reruns 10 --reruns-delay 1

    如下图,一共重跑了两次,重跑两次的执行时间为2.1秒,上图中一次只需要0.07秒,这里多出的两秒就是因为--reruns-delay指定的重跑间隔为1秒。

    例子3:通过表达式指定失败重跑

    test_demo.py解释:

    • test_assert_error随机抛出AssertionError

    • test_value_error随机抛出ValueError

    #!/usr/bin/env python3
    #!coding:utf-8
    import pytest
    import random
    
    def test_assert_error():
        r = random.randint(1,2)
        with pytest.raises(AssertionError):
            #这里如果不使用pytest.raises显式抛出AssertionError异常,pytest-rerunfailures无法捕获到assert r == 1,应该是该插件的bug。
            assert r == 1
    
    def test_value_error():
        r = random.randint(1,2)
        if r == 1:
            s = int('www')

    执行:pytest --reruns 10 --only-rerun AssertionError --only-rerun ValueError test_demo.py -v

    其中多个--only-rerun之间是或的关系

    如上图,遇到AssertionErrorValueError的情况下都被重跑了

    装饰器模式

    test_demo.py 

    • test_assert_error随机抛出AssertionError,最多失败重跑五次

    • test_value_error随机抛出ValueError,最多失败重跑五次,失败重跑间隔为2秒

    • test_value_error_condition,最多失败重跑五次,仅当系统为win32系统才重跑。

    #!/usr/bin/env python3
    #!coding:utf-8
    import pytest
    import random
    import sys
    
    #这个最多失败重跑五次 @pytest.mark.flaky(reruns
    =5) def test_assert_error(): r = random.randint(1,2) #raise AssertionError("ERR") with pytest.raises(AssertionError): assert r == 1
    #这个最多失败重跑五次 
    @pytest.mark.flaky(reruns=5, reruns_delay=2) 
    def test_value_error():
      r
    = random.randint(1,2)
      if r == 1:
        s
    = int('nick')
    #官网的这个例子有问题,如果拿mac或者linux机器跑也会有重试(condition中指定的是win32平台才会触发重跑机制)
    @pytest.mark.flaky(reruns=5, condition=not sys.platform.startswith("win32")) 
    def test_value_error_condition():
      r
    = random.randint(1,2)
        if r == 1:
          s
    = int('nick')

    执行:pytest -v 

    这里前面两个testcase都有过失败重跑,但是第三个也重跑了(作者原意是condition为False情况下不会重跑),这里是有bug的,即condition是无效的

    去查看项目源码,果然发现这里有些问题,是否不重跑的函数里面用的是or,即最后一个not condition只是不重跑的条件之一,如果前面满足重跑,则condition这个参数可以被忽略掉。

    兼容性

    • 不可以与类,模块还有包级别的fixture装饰器一起使用: @pytest.fixture() 
    • 该插件与pytest-xdist的 --looponfail 标志不兼容
    • 该插件在使用pdb调试时候会有不兼容性

    最后总结,这个插件虽然还用,但是坑还是不少,建议主要使用失败重试次数和重试间隔的功能即可。 

    博主:测试生财

    座右铭:专注测试与自动化,致力提高研发效能;通过测试精进完成原始积累,通过读书理财奔向财务自由。

    csdn:https://blog.csdn.net/ccgshigao

    博客园:https://www.cnblogs.com/qa-freeroad/

    51cto:https://blog.51cto.com/14900374

  • 相关阅读:
    前端js部分面试题
    前端css部分面试笔试题
    javascript 面向对象
    string 对象
    JavaScript 正则表达式
    JavaScirpt 位运算
    JavaScript冒泡循环排序案例
    JavaScript 练习题
    浏览器缓存机制
    浏览器对象模型(BOM)
  • 原文地址:https://www.cnblogs.com/qa-freeroad/p/14289598.html
Copyright © 2011-2022 走看看