• pytest--fixture


    三、fixture
     pytest 提供的 fixture 实现 unittest  中 setup/teardown 功能,可以在每次执行case之前初始化数据。
    不同点是,fixture 可以只在执行某几个特定 case 前运行,只需要在运行 case 前调用即可,比 setup/teardown 使用起来更灵活。
     
    fixture scope 作用范围
     先看下 fixture 函数的定义:
    def fixture(scope="function", params=None, autouse=False, ids=None, name=None):
        """
        :arg scope:    可选四组参数:function(默认)、calss、module、package/session
        :arg params:   一个可选的参数列表,它将导致多个参数调用fixture函数和所有测试使用它。
        :arg autouse:  如果为True,则fixture func将为所有测试激活可以看到它。如果为False(默认值),则需要显式激活fixture。
        :arg ids:      每个参数对应的字符串id列表,因此它们是测试id的一部分。如果没有提供id,它们将从参数中自动生成。
        :arg name:     fixture的名称。 这默认为装饰函数的名称。 
    如果fixture在定义它的同一模块中使用,夹具的功能名称将被请求夹具的功能arg遮蔽; 解决这个问题的一种方法是将装饰函数命名 “fixture_ <fixturename>”然后使用”@ pytest.fixture(name ='<fixturename>')”。   
    """
     重点说下 scope 四组参数的意义:
    • function:每个方法(函数)都会执行一次。
    • class:每个类都会执行一次。类中有多个方法调用,只在第一个方法调用时执行。
    • module:一个 .py 文件执行一次。一个.py 文件可能包含多个类和方法。
    • package/session:多个文件调用一次,可以跨 .py 文件。
     
    1、通过参数引用:
    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(["test_abc.py", "-s"])
    执行结果:
    test_abc.py 
       ------->before # 发现before会优先于测试函数运行
       ------->test_a
    2、通过外部函数引用
    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(["test_abc.py", "-s"])
    执行结果:
    test_abc.py 
      ------->before # 发现before会优先于测试类运行
      ------->setup
      ------->test_a
    3、设置为自动运行
    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(["test_abc.py", "-s"])
    执行结果:
    test_abc.py 
        ------->before # 发现before自动优先于测试类运行
        ------->setup
        ------->test_a
    4、设置作用域为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(["test_abc.py", "-s"])

    执行结果:

     test_abc.py
        ------->before # 发现只运行一次
        ------->setup
            ------->test_a
            .
            ------->setup
            ------->test_b
    5、返回值
    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  # 断言
     
    if __name__ == '__main__':
        pytest.main(["test_abc.py", "-s"])

    执行结果:

    # 可以发现结果运行了三次
    test_abc.py 
    1
    ------->test_a
    .
    2 ------->test_a . 3 ------->test_a F
     2.yield
    用例执行完之后如需要 清除数据(或还原)操作,可以使用 yield 来实现。
    #!/usr/bin/env python
    # coding=utf-8
    import pytest
    
    @pytest.fixture(scope='function')
    def login():
        print("登录")
        yield
        print("注销登录")
    
    def test_1():
        print('测试用例1')
    
    def test_2(login):
        print('测试用例2')
    
    if __name__ =="__main__":
        pytest.main(['test_sample.py','-s'])
     执行结果:
    test_sample.py 
    测试用例1
    .
    登录
    测试用例2
    .注销登录
    
    ============================== 2 passed in 0.08s ==============================
     3.conftest
    倘若有多个.py 文件需要调用 login() 方法,就必须把 login() 方法写在外面,这里引用了conftest.py 配置文件。
    # conftest.py代码如下:
    import pytest
    
    @pytest.fixture(scope='function')
    def login():
        print("登录")
    
    # test_sample.py 代码如下:
    import pytest
    
    def test_1():
        print('测试用例1')
    
    def test_2(login):
        print('测试用例2')
    
    if __name__ =="__main__":
        pytest.main(['test_sample.py','-s'])

    执行结果:

    test_sample.py 
    测试用例1
    .
    登录
    测试用例2
    .
    
    ============================== 2 passed in 0.01s ==============================
    内置 fixtures 之 pytestconfig:
    pytestconfig 可以通过命令行参数、选项、配置文件、插件、运行目录等方式来控制pytest;
    pytestconfig 实际上就是 request.config 的快捷方式,被称为“pytest 配置对象”;
     
    我们最常使用的就是 getoption() 和getini():
    1.getoption() 可以获取命令行的值;
    def getoption(self, name: str, default=notset, skip: bool = False):
          """ return command line option value.
          """
    2.getini() 可以获取 pytest.ini 配置文件的参数值;
     
     
    1.使用 pytestconfig 获取命令行参数的值:
    conftest.py:
    import pytest
    # 注册自定义参数 cmdopt 到配置对象
    def pytest_addoption(parser):
        parser.addoption("--cmdopt", action="store", default="None",  help="将自定义命令行参数 ’--cmdopt' 添加到 pytest 配置中")
     
    # 其它fixture从配置对象获取 cmdopt 的值
    @pytest.fixture(scope='session')
    def get_cmdopt(pytestconfig):
        return pytestconfig.getoption('--cmdopt')
    # 然后任何 fixture 或测试用例都可以调用 cmdopt 来获得设备信息
    main.py:
    device_info = {'id': 'xxx', 'name': '华为', 'version': '10'}
    pytest.main(['-m all', f'--cmdopt={device_info}'])  # 使用自定义参数传参
     
    2.使用 pytestconfig 获取 pytest.ini 配置文件中参数的值:
    pytest.ini:
    [pytest]
    markers =
        demo : marks tests as demo
        smoke: marks tests as smoke
        test : marks tests as test
    log_cli = 1
    conftest.py:
    @pytest.fixture(autouse=True)
    def fuc_fix(pytestconfig):
        print(pytestconfig.getini('markers'))
        print(pytestconfig.getini('log_cli'))

  • 相关阅读:
    SQL第3课:具有约束的查询(第2部分)
    SQL第1课:SELECT查询
    idea快捷键
    Vue基础
    分布式基础
    数据结构-线性表
    常用算法
    数据结构-概述
    Django使用Jinja2模板引擎
    宿主机nginx使用容器php-fpm处理php请求
  • 原文地址:https://www.cnblogs.com/absoluteli/p/13984550.html
Copyright © 2020-2023  润新知