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

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值