zoukankan      html  css  js  c++  java
  • 【pytest官方文档】解读Skipping test functions,跳过测试用例详解

    有时候,为了满足某些场景的需要,我们知道有些测试函数在这时候肯定不能执行,或者执行了也会失败。那么我们
    可以选择去跳过这个测试函数,这样也就不会影响整体的测试函数运行效果,不至于在你运行的众多绿色通过的测试
    用例中,给你加点红色的failed或者error。

    举个例子,有些测试函数只能在windows上运行,那么换了个Linux平台就不可以,就需要跳过这个测试函数。再比如,
    有些测试用例会有一些外部资源的依赖,像数据库,那么当数据库资源不可用的时候,也需要去跳过这个测试函数。

    在pytest中提供了这样一个机制来跳过测试函数。

    一、skip

    用法很简单,只要在需要跳过的测试函数上面安上@pytest.mark.skip()即可。可以传递一个参数reason,填写
    跳过的理由,不填也可以。

    @pytest.mark.skip(reason="没啥理由,就不想执行")
    def test_the_unknown():
        ...
    

    运行结果:

    test_skipif.py                                                          [100%]
    
    ============================= 1 skipped in 0.02s ==============================s
    Skipped: 没啥理由,就不想执行
    
    Process finished with exit code 0
    

    可以看到,这个测试用例被成功跳过,并且还有reason的输出。不过pytest默认情况下,不会显示跳过的测试函数的详细信息,
    避免输出与正常的混在一起,太乱。

    二、pytest.skip(reason)

    1. 在测试函数或者fixture函数里使用

    除了上述用法,还可以用pytest.skip(reason)函数,在测试函数中或者setup函数里进行跳过。比如,当有些参数不符合你
    的预期,那么就跳过后面的执行。

    上示例代码:

    import pytest
    
    
    @pytest.fixture()
    def demo_fixture(request):
        test_input = request.param
        if test_input == 3:
            pytest.skip("传入的值等于3就跳过执行")
    
    
    @pytest.mark.parametrize("demo_fixture", [1, 3], indirect=True)
    def test_the_unknown3(demo_fixture):
        ...
    
    
    if __name__ == "__main__":
        pytest.main(["-s", '-r' "test_skipif.py"])
    

    在上述代码里,我在测试函数test_the_unknown3里做了一个参数化,并且在fixture函数demo_fixture拿到这个参数。
    按理来说,参数化了1和3,所以测试函数会执行2次。

    我在fixture函数里加了判断,当拿到的参数,等于3的时候,就跳过执行。所以最终的运行结果应该是,1执行,3跳过。

    test_skipif.py                                                         [100%]
    
    ======================== 1 passed, 1 skipped in 0.09s =========================.s
    Skipped: 传入的值等于3就跳过执行
    
    Process finished with exit code 0
    

    结果符合预期。

    这个用法,刚好解决了我一个实际问题。
    那就是别的小组有不少人写case用的测试数据,是会通过别的case或者别的接口调用后传递过来的,那么当这些依赖有问题的时候
    case运行就会有问题,导致误报。如果使用pytest.skip(reason)这个函数,那么可以有效缓解case误报的问题。

    2. allow_module_level=True跳过整个模块

    如果你需要判断某些条件符合时候,就要整个模块都跳过,就可以加上这个参数allow_module_level=True

    import pytest
    
    a = 1
    
    if a != 3:
        pytest.skip("a不等于3就跳过整个文件模块", allow_module_level=True)
    
    
    @pytest.fixture()
    def demo_fixture(request):
        test_input = request.param
        if test_input == 3:
            pytest.skip("传入的值等于3就跳过")
    
    
    @pytest.mark.parametrize("demo_fixture", [1, 3], indirect=True)
    def test_the_unknown1(demo_fixture):
        ...
    
    
    def test_the_unknown2():
        ...
    
    
    def test_the_unknown3():
        ...
    

    运行一下:

    ============================= 1 skipped in 0.02s ==============================
    Skipped: a不等于3就跳过整个文件模块
    
    Process finished with exit code 0
    

    三、skipif

    1. skipif有条件的跳过

    上面提到了在函数里写判断,当满足某个条件时通过pytest.skip函数来跳过,其实还可以直接用skipif,同样可以
    达到有条件地跳过某些内容的目的。

    import sys
    
    
    @pytest.mark.skipif(sys.version_info < (4, 0), reason="版本4.0以下就跳过执行")
    def test_function():
        print(sys.version_info)
    

    运行结果:

    test_module1.py                                                         [100%]
    
    ============================= 1 skipped in 0.02s ==============================s
    Skipped: 版本4.0以下就跳过执行
    
    Process finished with exit code 0
    

    2.模块之间共享skip标记

    比如说,我现在有2个测试模块,分别是test_module1.pytest_module2.py
    我在test_module1.py当中,定义一个skipif作为marker 共享,也就是not_equal_5
    那么在test_module2.py当中导入这个marker,就可以直接使用了,看代码效果:

    # content of test_module1.py
    import pytest
    import sys
    
    version_judge = pytest.mark.skipif(
        sys.version_info < (4, 0), reason="版本4.0以下就跳过执行"
    )
    
    @version_judge
    def test_the_unknown2():
        ...
    
    if __name__ == "__main__":
        pytest.main(["-s", '-r' "test_module1.py"])
    
    

    test_module2.py中导入marker使用,运行后的预期结果,应该是test_the_unknown1跳过执行。

    # content of test_module2.py
    import pytest
    from interface.demo.test_module1 import version_judge
    
    
    @version_judge
    def test_the_unknown1():
        ...
    
    
    def test_the_unknown2():
        ...
    
    
    if __name__ == "__main__":
        pytest.main(["-s", '-r' "test_module2.py"])
    

    运行下test_module2.py:

    test_module2.py                                                        [100%]
    
    ======================== 1 passed, 1 skipped in 0.08s =========================s
    Skipped: 版本4.0以下就跳过执行
    .
    Process finished with exit code 0
    

    四、跳过类或模块下的所有测试函数

    1. 跳过类下的所有测试函数

    如果把skipif放在类上,这个类下面的所有测试函数都会跳过。

    import pytest
    import sys
    
    version_judge = pytest.mark.skipif(
        sys.version_info < (4, 0), reason="版本4.0以下就跳过执行"
    )
    
    @version_judge
    class TestDemo():
    
        def test_the_unknown2(self):
            ...
    
        def test_the_unknown3(self):
            ...
    
    def test_the_unknown1():
        ...
    
    if __name__ == "__main__":
        pytest.main(["-s", '-r' "test_module1.py"])
    

    运行结果,类TestDemo下的2个测试方法都会被跳过。

    test_module1.py                                                       [100%]
    
    ======================== 1 passed, 2 skipped in 0.09s =========================s
    Skipped: 版本4.0以下就跳过执行
    s
    Skipped: 版本4.0以下就跳过执行
    .
    Process finished with exit code 0
    

    2.跳过模块下的所有测试函数

    如果想跳过模块的所有测试函数,可以使用全局变量pytestmark:

    import pytest
    import sys
    
    
    pytestmark = pytest.mark.skipif(sys.version_info < (4, 0), reason="版本4.0以下就跳过执行")
    
    class TestDemo():
    
        def test_the_unknown2(self):
            ...
    
        def test_the_unknown3(self):
            ...
    
    def test_the_unknown1():
        ...
    
    if __name__ == "__main__":
        pytest.main(["-s", '-r' "test_module1.py"])
    

    运行,模块下的3个测试都会被跳过

    test_module1.py                                                       [100%]
    
    ============================= 3 skipped in 0.02s ==============================s
    Skipped: 版本4.0以下就跳过执行
    s
    Skipped: 版本4.0以下就跳过执行
    s
    Skipped: 版本4.0以下就跳过执行
    
    Process finished with exit code 0
    

    另外,如果多个skipif装饰器应用于同一个测试函数,只要任何一个条件为真,该函数将被跳过。

    五、跳过文件或目录

    有时可能需要跳过一整个文件或目录。例如,有文件里的代码你不想去执行。在这种情况下,必须从pytest搜集到的集合中排除文件和目录。
    有关更多信息,请参阅自定义测试集合,后续看情况单独分享。

    六、导入依赖失败跳过

    当有些依赖的包导入失败的时候,可以通过pytest.importorskip这个函数来跳过。同样,可以用在模块级别,fixture函数或者测试函数里。

    import pytest
    
    # docutils = pytest.importorskip("docutils")
    
    class TestDemo():
    
        def test_the_unknown2(self):
            ...
    
        def test_the_unknown3(self):
            pytest.importorskip("docutils")
    
    def test_the_unknown1():
        ...
    
    if __name__ == "__main__":
        pytest.main(["-s", '-r' "test_module1.py"])
    

    运行结果,应该是跳过一个,执行2个:

    test_module1.py                                                       [100%]
    
    ======================== 2 passed, 1 skipped in 0.09s =========================.s
    Skipped: could not import 'docutils': No module named 'docutils'
    .
    Process finished with exit code 0
    

    代码里的docutils是一个第三方库,你也可以根据库的版本号跳过:

    docutils = pytest.importorskip("docutils", minversion="0.3")
    

    版本将从指定模块的__version__属性中读取,如果不符合条件,也会跳过。

    七、总结

    1. 无条件跳过模块中的所有测试
    pytestmark = pytest.mark.skip("all tests still WIP")
    
    1. 基于某些条件跳过模块中的所有测试
    pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="tests for linux only")
    
    1. 如果缺少某些导入,则跳过模块中的所有测试
    pexpect = pytest.importorskip("pexpect")
    
    --不要用肉体的勤奋,去掩盖思考的懒惰--
  • 相关阅读:
    网易严选的wkwebview测试之路
    【工程实践】服务器数据解析
    从加班论客户端开发中的建模
    UVaLive 6802 Turtle Graphics (水题,模拟)
    UVaLive 6694 Toy Boxes (二分+想法)
    UVaLive 6693 Flow Game (计算几何,线段相交)
    UVaLive 6698 Sightseeing Bus Drivers (水题,贪心)
    UVaLive 6697 Homework Evaluation (DP)
    UVALive 6692 Lucky Number (思路 + 枚举)
    CodeForces 710E Generate a String (DP)
  • 原文地址:https://www.cnblogs.com/pingguo-softwaretesting/p/14683569.html
Copyright © 2011-2022 走看看