fixture使用详解【pytest系列 4】

1、前言

  • setup和teardown可以实现用例执行前和执行后加入一些操作,但是这种操作是全局的生效的
  • 有一些操作,我们只想要做用在部分用例上,这时可以使用fixture来自定义前置操作

2、fixture参数列表

@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
def login():
	print("this is login")

参数列表:

  • scope: 默认function。可以理解为fixture的作用域,一般还有4种:class module package session(整个测试会话,即开始执行pytest到结束测试)
  • autouse:默认False,表示需要手动调用该fixture。如果是True,scope表示的作用域内的测试用例都会自动调用该fixture
  • name:默认:函数名称。如果配置了,调用fixture时使用该配置的名称,否则使用函数名即可调用

3、测试用例如何调用fixture

一般有三种方式:

  • 将fixture名称作为测试用例函数的输入参数
  • 测试用例使用装饰器:@pytest.mark.usefixtures(fixture_name)
  • fixture设置autouse=True

说明:

  • 如果在类声明上加@pytest.mark.usefixures(),代表这个类里面所有的测试用例都会调用该fixuture
  • 如果fixture有返回值,使用@pytest.mark.usefixures()无法获取到返回值,必须用传参的方式

将fixture名称作为测试用例函数的输入参数

  • 代码
    import pytest
    
    @pytest.fixture()
    def login():
    	print("this is login")
    
    def test_s1(login):
    	print("this is test_s1")
    
  • 结果
    test_1.py::test_s1 
    ========this is login
    PASSED                                                [100%]
    ========this is case 1
    

测试用例使用装饰器

  • 代码1:usefixtures中可以放多个fixture参数,先执行的放前面,后执行的放后面

    import pytest
    
    @pytest.fixture()
    def login():
    	print("this is login")
    
    @pytest.fixture()
    def login2():
    	print("this is login2")
    
    @pytest.mark.usefixures("login", "login2")
    def test_s1():
    	print("this is test_s1")
    
  • 结果1:先执行login(),后执行login2()

    test_1.py::test_s2 
    ========this is login
    ========this is login2
    PASSED                                                [100%]
    ========this is test_s2
    
  • 代码2:可以叠加多个@pytest.mark.usefixures(),先执行的放底层,后执行的放上层

    import pytest
    
    @pytest.fixture()
    def login():
    	print("this is login")
    
    @pytest.fixture()
    def login2():
    	print("this is login2")
    	
    @pytest.mark.usefixures("login2")
    @pytest.mark.usefixures("login")
    def test_s1():
    	print("this is test_s1")
    
  • 结果2:先执行login(),后执行login2()

    test_1.py::test_s2 
    ========this is login
    ========this is login2
    PASSED                                                [100%]
    ========this is test_s2
    

fixture设置autouse

  • 代码:
    import pytest
    
    @pytest.fixture(autouse=True)
    def login():
    	print("this is login")
    
    def test_s1():
    	print("this is test_s1")
    
  • 结果:
    test_1.py::test_s1 
    ========this is login
    PASSED                                                [100%]
    ========this is test_s1
    

4、关于fixture实例化顺序

  • fixture按照scope表示的顺序进行实例化的:session > package > module > class > function
  • 相同作用域的fixture会按照声明顺序进行实例化,如果fixture之间有依赖关系,会将依赖的fixture先实例化。
  • autouse=True的fixture会在传参或者装饰器的fixture前实例化
  • 添加了@pytest.fixture,如果还想要依赖其他fixture,需要使用函数传参的方式,使用@pytest.mark.usefixtures()的方式不生效
  • 代码
    import pytest
    
    order = []
    
    @pytest.fixture(scope="session")
    def s():
        order.append("s")
    
    @pytest.fixture(scope="module")
    def m():
        order.append("m")
    
    @pytest.fixture()
    def f1(f3, a1):
        order.append("f1")
    
    @pytest.fixture()
    def f3():
        order.append("f3")
        a = 123
        yield a
    
    @pytest.fixture()
    def a1():
        order.append("a1")
    
    @pytest.fixture()
    def f2():
        order.append("f2")
    
    def test_order(f1, m, f2, s):
        print(order)
    
  • 结果:test_order(f1, m, f2, s)执行顺序会按照s -> m -> f1 -> f2
    test_1.py::test_order PASSED                                             [100%]
    ['s', 'm', 'f3', 'a1', 'f1', 'f2']
    

5、fixture实现teardown功能

使用yield实现teardown功能

说明:

  • 用fixture实现teardown不是一个独立的函数,而是由yield关键字开启
  • 如果yield前面的代码,及setup部分已经抛出异常,就不会再执行yield后面的teardown部分
  • 如果测试用例抛出异常,yield后面的teardown部分还是会正常执行
  • 代码
    import pytest
    
    
    @pytest.fixture(scope="session")
    def open():
        # 会话前置操作
        print("====打开浏览器====")
        test = "测试变量是否返回"
        yield test
        # 会话的后置操作
        print("====关闭浏览器====")
    
    
    @pytest.fixture()
    def login(open):
        # 方法级别前置操作
        print(f"====open返回值是: {open}====")
        username = "====我是账号===="
        password = "====我是密码===="
        yield username, password
        print("登录成功")
    
    
    def test_s1(login):
        print("====测试用例s1====")
        username, password = login
        print(username)
        print(password)
    
    
    def test_s2(login):
        print("====测试用例s2====")
        print(login)
    
  • 结果
    test_1.py::test_s1 
    ====打开浏览器====
    ====open返回值是: 测试变量是否返回====
    PASSED                                                [ 50%]
    ====测试用例s1====
    ====我是账号====
    ====我是密码====
    登录成功
    
    test_1.py::test_s2 
    ====open返回值是: 测试变量是否返回====
    PASSED                                                [100%]
    ====测试用例s2====
    ('====我是账号====', '====我是密码====')
    登录成功
    ====关闭浏览器====
    

addfinalizer终结函数

说明

  • 如下代码:如果request.addfinalizer()前面的setup部分抛出异常,则不会执行request.addfinalizer()中的teardown内容
  • 可以声明多个终结函数并调用
  • 步骤:传入request参数;在fixture中定义一个内置函数;将定义的内置函数添加到request的addfinalizer中
  • 代码
    import pytest
    
    
    @pytest.fixture()
    def myfixture(request):
        print("====执行setup部分====")
    
        def fin():
            print("====执行teardown部分====")
    
        request.addfinalizer(fin)
    
    
    def test_addfinalizer(myfixture):
        print("====执行用例====")
    
  • 结果
    test_1.py::test_addfinalizer 
    ====执行setup部分====
    PASSED                                      [100%]
    ====执行用例====
    ====执行teardown部分====
    

参考文章:https://www.cnblogs.com/poloyy/p/12642602.html

pytest.fixture装饰器是pytest测试框架中的一个重要特性,用于定义测试用例中的共享资源或者测试环境的初始化和清理操作。通过使用fixture装饰器,我们可以在测试用例中方便地使用这些共享资源。 fixture装饰器可以应用在函数、类或者模块级别上,它的作用是将被装饰的函数或者方法转变为一个fixture对象。fixture对象可以在测试用例中作为参数进行调用,pytest会自动根据参数名匹配相应的fixture对象,并将其传递给测试用例。 fixture装饰器可以接受一些参数来定制其行为,例如scope参数用于指定fixture的作用域,autouse参数用于指定是否自动使用fixture等。 下面是一些常见的fixture用法: 1. 无参数fixture: ```python import pytest @pytest.fixture def setup(): # 初始化操作 yield # 清理操作 def test_example(setup): # 使用setup fixture assert 1 + 1 == 2 ``` 2. 带参数fixture: ```python import pytest @pytest.fixture def setup(request): # 初始化操作 def teardown(): # 清理操作 request.addfinalizer(teardown) def test_example(setup): # 使用setup fixture assert 1 + 1 == 2 ``` 3. fixture作用域: ```python import pytest @pytest.fixture(scope="module") def setup_module(): # 模块级别的初始化操作 yield # 模块级别的清理操作 @pytest.fixture(scope="function") def setup_function(): # 函数级别的初始化操作 yield # 函数级别的清理操作 def test_example(setup_module, setup_function): # 使用setup_module和setup_function fixture assert 1 + 1 == 2 ``` 通过使用fixture装饰器,我们可以更加灵活地管理测试用例中的共享资源和测试环境的初始化和清理操作,提高测试用例的可维护性和可重复性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值