美文网首页
Python_pytest详解

Python_pytest详解

作者: 成功在于实践 | 来源:发表于2018-11-09 19:35 被阅读50次

    1.Pytest安装和介绍

    1.1 Pytest介绍

    pytest是python的一种单元测试框架,同自带的Unittest测试框架类似,相比于Unittest框架使用起来更简洁,效率更高。

    Pytest is a framework that makes building simple and scalable tests easy. Tests are expressive and readable—no boilerplate code required. Get started in minutes with a small unit test or complex functional test for your application or library. `

    1.2 Pytes安装

    1.安装包安装

    1.进入下载包路径
    2.python setup install
    3.安装出现权限问题:
    3.1.mac/linux 添加sudo,运行:sudo python setup install
    3.2.windows 管理员方式运行cmd窗口,运行:python setup install

    2.命令行安装

    1.mac/linux:sudo pip3 install -U pytest # -U:可以理解为--upgrade,表示已安装就升级为最新版本
    2.管理员方式运行cmd:pip3 install -U pytest

    2.安装成功校验:

    1.进入命令行
    2.运行:pytest --version # 会展示当前已安装版本

    1.3 Pytest文档

    存在手机里,没事就拿出来读一读,看一看.说实话,我的英文能力很渣,学这个东西感觉很难,不过一切慢慢来吧.为了一份好的工作,为了技术的提升,我给自己的目标是:一周写出一小篇文章.必须有深度,让别人能看懂,转行真的不容易.记住:有时间多看看文档,毕竟了解一些先进的技术是必须看英文文档的.

    链接在这里: https://docs.pytest.org/en/latest/contents.html

    1.4 Pytest运行方式

     # file_name: test_abc.py
     import pytest # 引入pytest包
     def test_a(): # test开头的测试函数
         print("------->test_a")
         assert 1 # 断言成功
     def test_b():
         print("------->test_b")
         assert 0 # 断言失败
     if __name__ == '__main__':
            pytest.main("-s  test_abc.py") # 调用pytest的main函数执行测试
    

    1.测试类主函数模式

      pytest.main("-s  test_abc.py")
    

    2.命令行模式

      pytest 文件路径/测试文件名
      例如:pytest ./test_abc.py
    
    在pytest框架中,有如下约束:

    所有的单测文件名都需要满足test_.py格式或test.py格式。
    在单测文件中,可以包含test
    开头的函数,也可以包含Test开头的类。
    在单测类中,可以包含一个或多个test_开头的函数。
    此时,在执行pytest命令时,会自动从当前目录及子目录中寻找符合上述约束的测试函数来执行。

    2.Pytest的setup和teardown函数

    1.setup和teardown主要分为:模块级,类级,功能级,函数级。
    2.存在于测试类内部
    代码示例:

    • 函数级别setup()/teardown()

    运行于测试方法的始末,即:运行一次测试函数会运行一次setup和teardown

    import pytest
    class Test_ABC:
      # 函数级开始
      def setup(self):
          print("------->setup_method")
      # 函数级结束
      def teardown(self):
          print("------->teardown_method")
      def test_a(self):
          print("------->test_a")
          assert 1
      def test_b(self):
          print("------->test_b")
    if __name__ == '__main__':
                  pytest.main("-s  test_abc.py")
    
    执行结果:
      test_abc.py 
      ------->setup_method # 第一次 setup()
      ------->test_a
      .
      ------->teardown_method # 第一次 teardown()
      ------->setup_method # 第二次 setup()
      ------->test_b
      .
              ------->teardown_method # 第二次 teardown()
    
    • 2.2.类级别

    运行于测试类的始末,即:在一个测试内只运行一次setup_class和teardown_class,不关心测试类内有多少个测试函数。
    代码示例:

    import pytest
    class Test_ABC:
       # 测试类级开始
       def setup_class(self):
           print("------->setup_class")
       # 测试类级结束
       def teardown_class(self):
           print("------->teardown_class")
       def test_a(self):
           print("------->test_a")
           assert 1
       def test_b(self):
           print("------->test_b")
              if __name__ == '__main__':
                  pytest.main("-s  test_abc.py")
    
    执行结果:
      test_abc.py 
      ------->setup_class # 第一次 setup_class()
      ------->test_a
      .
      ------->test_b
      F 
              ------->teardown_class # 第一次 teardown_class()
    

    3.Pytest配置文件

    pytest的配置文件通常放在测试目录下,名称为pytest.ini,命令行运行时会使用该配置文件中的配置.

    #配置pytest命令行运行参数
       [pytest]
        addopts = -s ... # 空格分隔,可添加多个命令行参数 -所有参数均为插件包的参数配置测试搜索的路径
        testpaths = ./scripts  # 当前目录下的scripts文件夹 -可自定义
    #配置测试搜索的文件名称
        python_files = test*.py 
    #当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件 -可自定义
    配置测试搜索的测试类名
        python_classes = Test_*  
    
       #当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件中,以Test开头的类 -可自定义
    配置测试搜索的测试函数名
      
        python_functions = test_*
    
    #当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件中,以Test开头的类内,以test_开头的方法 -可自定义
    
    

    4 Pytest常用插件

    插件列表网址:https://plugincompat.herokuapp.com
    包含很多插件包,大家可依据工作的需求选择使用。

    4.1 前置条件:

    1.文件路径:

    - Test_App
    - - test_abc.py
    - - pytest.ini
    

    2.pyetst.ini配置文件内容:

      [pytest]
    # 命令行参数
     addopts = -s
    # 搜索文件名
     python_files = test_*.py
     # 搜索的类名
     python_classes = Test_*
     #搜索的函数名
        python_functions = test_*
    

    4.2 Pytest测试报告

    通过命令行方式,生成xml/html格式的测试报告,存储于用户指定路径。插件名称:pytest-html

    使用方法: 命令行格式:pytest --html=用户路径/report.html

    示例:
    import pytest
    class Test_ABC:
        def setup_class(self):
            print("------->setup_class")
        def teardown_class(self):
            print("------->teardown_class")
        def test_a(self):
            print("------->test_a")
            assert 1
        def test_b(self):
                print("------->test_b")
                assert 0 # 断言失败```
    运行方式:
    1.修改Test_App/pytest.ini文件,添加报告参数,即:addopts = -s --html=./report.html 
        # -s:输出程序运行信息
        # --html=./report.html 在当前目录下生成report.html文件
        ️ 若要生成xml文件,可将--html=./report.html 改成 --html=./report.xml
    2.命令行进入Test_App目录
    3.执行命令: pytest
    执行结果:
        1.在当前目录会生成assets文件夹和report.html文件
    
    

    5.pytest的高阶用法(一)

    前置条件:

    1.文件路径:

    Test_App
        - - test_abc.py
        - - pytest.ini
    

    2.pyetst.ini配置文件内容:

    
    [pytest]
      命令行参数
     addopts = -s
     搜索文件名
     python_files = test*.py
      搜索的类名
     python_classes = Test*
    搜索的函数名
     python_functions = test_*
    

    5.1pytest之fixture

    fixture修饰器来标记固定的工厂函数,在其他函数,模块,类或整个工程调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作。

    方法:fixture(scope="function", params=None, autouse=False, ids=None, name=None)
    常用参数:

     scope:被标记方法的作用域
     function" (default):作用于每个测试方法,每个test都运行一次
    "class":作用于整个类,每个class的所有test只运行一次
     "module":作用于整个模块,每个module的所有test只运行一次
     "session:作用于整个session(慎用),每个session只运行一次
     params:(list类型)提供参数数据,供调用标记方法的函数使用
     autouse:是否自动运行,默认为False不运行,设置为True自动运行
    

    5.2fixture第一个例子(通过参数引用)

    示例:

    class Test_ABC:
        @pytest.fixture()
        def before(self):
            print("------->before")
        def test_a(self,before): # ️ test_a方法传入了被fixture标识的函数,已变量的形式
            print("------->test_a")
            assert 1
    if __name__ == '__main__':
        pytest.main("-s  test_abc.py")
    执行结果:
        test_abc.py 
            ------->before # 发现before会优先于测试函数运行
            ------->test_a
             .
    

    5.3.fixture第二个例子(通过函数引用)

    示例:
    import pytest
    @pytest.fixture() # fixture标记的函数可以应用于测试类外部
    def before():
        print("------->before")
    @pytest.mark.usefixtures("before")
    class Test_ABC:
        def setup(self):
            print("------->setup")
        def test_a(self):
            print("------->test_a")
            assert 1
    if __name__ == '__main__':
              pytest.main("-s  test_abc.py")
      执行结果:
          test_abc.py 
          ------->before # 发现before会优先于测试类运行
          ------->setup
          ------->test_a
          .
    

    5.4.fixture第三个例子(默认设置为运行)

    示例:

     import pytest
     @pytest.fixture(autouse=True) # 设置为默认运行
     def before():
         print("------->before")
     class Test_ABC:
         def setup(self):
             print("------->setup")
         def test_a(self):
             print("------->test_a")
             assert 1
     if __name__ == '__main__':
         pytest.main("-s  test_abc.py")
    执行结果:
        test_abc.py 
        ------->before # 发现before自动优先于测试类运行
        ------->setup
        ------->test_a
            .
    

    5.5.fixture第四个例子(设置作用域为function)

    示例:

        import pytest
        @pytest.fixture(scope='function',autouse=True) # 作用域设置为function,自动运行
        def before():
            print("------->before")
        class Test_ABC:
            def setup(self):
                print("------->setup")
            def test_a(self):
                print("------->test_a")
                assert 1
            def test_b(self):
                print("------->test_b")
                assert 1
        if __name__ == '__main__':
            pytest.main("-s  test_abc.py")
    执行结果:
        test_abc.py
            ------->before # 运行第一次
            ------->setup
            ------->test_a
            .------->before # 运行第二次
            ------->setup
            ------->test_b
            .
    

    5.6.fixture第五个例子(设置作用域为class)

    示例:

        import pytest
        @pytest.fixture(scope='class',autouse=True) # 作用域设置为class,自动运行
        def before():
            print("------->before")
        class Test_ABC:
            def setup(self):
                print("------->setup")
            def test_a(self):
                print("------->test_a")
                assert 1
            def test_b(self):
                print("------->test_b")
                assert 1
        if __name__ == '__main__':
            pytest.main("-s  test_abc.py")
    执行结果:
        test_abc.py
        ------->before # 发现只运行一次
        ------->setup
            ------->test_a
            .
            ------->setup
            ------->test_b
            .
    

    5.7.fixture第六个例子(返回值)

    示例一:

    
        import pytest
        @pytest.fixture()
        def need_data():
            return 2 # 返回数字2
    
        class Test_ABC:
    
            def test_a(self,need_data):
                print("------->test_a")
                assert need_data != 3 # 拿到返回值做一次断言
    
        if __name__ == '__main__':
            pytest.main("-s  test_abc.py")
    执行结果:
        test_abc.py 
        ------->test_a
        .
    ``
    
    

    示例二:

    import pytest
    @pytest.fixture(params=[1, 2, 3])
    def need_data(request): # 传入参数request 系统封装参数
        return request.param # 取列表中单个值,默认的取值方式
    class Test_ABC:
    
        def test_a(self,need_data):
            print("------->test_a")
            assert need_data != 3 # 断言need_data不等于3
    
    if __name__ == '__main__':
        pytest.main("-s  test_abc.py")
    
     执行结果:
          # 可以发现结果运行了三次
          test_abc.py 
          1
          ------->test_a
          .
          2
          ------->test_a
          .
          3
          ------->test_a
          F
    

    6.Pytest高阶用法(二)

    前置条件:

    1.文件路径:

    - Test_App
    - - test_abc.py
    - - pytest.ini
    

    2.pyetst.ini配置文件内容:

    [pytest]
    命令行参数
    addopts = -s
    搜索文件名
    python_files = test_*.py
     搜索的类名
    python_classes = Test_*
     搜索的函数名
    python_functions = test_*
    

    6.1.跳过测试函数

    根据特定的条件,不执行标识的测试函数.
     方法:
         skipif(condition, reason=None)
     参数:
         condition:跳过的条件,必传参数
         reason:标注原因,必传参数
     使用方法:
         @pytest.mark.skipif(condition, reason="xxx") 
    

    示例:

    import pytest
    class Test_ABC:
        def setup_class(self):
            print("------->setup_class")
        def teardown_class(self):
            print("------->teardown_class")
        def test_a(self):
            print("------->test_a")
            assert 1
        @pytest.mark.skipif(condition=2>1,reason = "跳过该函数") # 跳过测试函数test_b
        def test_b(self):
            print("------->test_b")
                assert 0
    执行结果:
       test_abc.py 
       ------->setup_class
       ------->test_a #只执行了函数test_a
       .
       ------->teardown_class
           s # 跳过函数```
    
    
    

    6.2 标记为预期失败函数

    标记测试函数为失败函数
     方法:
         xfail(condition=None, reason=None, raises=None, run=True, strict=False)
     常用参数:
         condition:预期失败的条件,必传参数
         reason:失败的原因,必传参数
     使用方法:
         @pytest.mark.xfail(condition, reason="xx")
    

    示例:

    import pytest
    class Test_ABC:
        def setup_class(self):
            print("------->setup_class")
        def teardown_class(self):
            print("------->teardown_class")
        def test_a(self):
            print("------->test_a")
            assert 1
        @pytest.mark.xfail(2 > 1, reason="标注为预期失败") # 标记为预期失败函数test_b
           def test_b(self):
               print("------->test_b")
              assert 0
       执行结果:
           test_abc.py 
           ------->setup_class
           ------->test_a
           .
           ------->test_b
           ------->teardown_class
           x  # 失败标记
    

    6.3 函数数据参数化

    方便测试函数对测试属于的获取。
     方法:
         parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
     常用参数:
         argnames:参数名
         argvalues:参数对应值,类型必须为list
                     当参数为一个时格式:[value]
                     当参数个数大于一个时,格式为:[(param_value1,param_value2.....),(param_value1,param_value2.....)]
     使用方法:
         @pytest.mark.parametrize(argnames,argvalues)
         ️ 参数值为N个,测试方法就会运行N次
      
    
    

    单个参数示例:

    import pytest
    class Test_ABC:
        def setup_class(self):
            print("------->setup_class")
        def teardown_class(self):
            print("------->teardown_class")
    
    @pytest.mark.parametrize("a",[3,6]) # a参数被赋予两个值,函数会运行两遍
    def test_a(self,a): # 参数必须和parametrize里面的参数一致
        print("test data:a=%d"%a)
        assert a%3 == 0
        执行结果:
        test_abc.py 
        ------->setup_class
        test data:a=3 # 运行第一次取值a=3
        .
        test data:a=6 # 运行第二次取值a=6
        . 
        ------->teardown_class
    

    多个参数示例:

    import pytest
    class Test_ABC:
        def setup_class(self):
            print("------->setup_class")
        def teardown_class(self):
            print("------->teardown_class")
    
    @pytest.mark.parametrize("a,b",[(1,2),(0,3)]) # 参数a,b均被赋予两个值,函数会运行两遍
    def test_a(self,a,b): # 参数必须和parametrize里面的参数一致
        print("test data:a=%d,b=%d"%(a,b))
        assert a+b == 3
        执行结果:
        test_abc.py 
        ------->setup_class
        test data:a=1,b=2 # 运行第一次取值 a=1,b=2
        .
        test data:a=0,b=3 # 运行第二次取值 a=0,b=3
        .
        ------->teardown_class
    

    函数返回值类型示例:

    import pytest
    def return_test_data():
        return [(1,2),(0,3)]
    class Test_ABC:
        def setup_class(self):
            print("------->setup_class")
        def teardown_class(self):
                print("------->teardown_class")
    
    @pytest.mark.parametrize("a,b",return_test_data()) # 使用函数返回值的形式传入参数值
    def test_a(self,a,b):
        print("test data:a=%d,b=%d"%(a,b))
        assert a+b == 3
        
        执行结果:
        test_abc.py 
        ------->setup_class
        test data:a=1,b=2 # 运行第一次取值 a=1,b=2
        .
        test data:a=0,b=3 # 运行第二次取值 a=0,b=3
        .
            ------->teardown_class
    

    相关文章

      网友评论

          本文标题:Python_pytest详解

          本文链接:https://www.haomeiwen.com/subject/otljxqtx.html