zoukankan      html  css  js  c++  java
  • 【pytest】teardown里的yield和addfinalizer

    在之前介绍pytest中的fixture用法的文章中https://zhuanlan.zhihu.com/p/87775743,提到了teardown的实现。
    最近在翻pytest官方文档的时候,又发现了addfinalizer这个函数,跟yield一样,也可以实现在case结束后运行关键字之后的代码。那今天就来捋一下这2者的用法和区别。

    一、yield

    再来简单回顾下pytest里的setUp和tearDown的用法,我们可以看到,下方代码里有三个case用例,分别是test_开头。
    而在demo_fixture函数里,有一个yield关键字。那么在yield之前的代码,会在case之前执行,yield之后的代码,则会在case运行结束后执行。

    #yield_finalizer_demo.py
    
    import pytest
    
    @pytest.fixture()
    def demo_fixture():
        print("
    这个fixture在每个case前执行一次")
        yield
        print("
    在每个case完成后执行的teardown")
    
    def test_01(demo_fixture):
        print("
    ===执行了case: test_01===")
    
    def test_02(demo_fixture):
        print("
    ===执行了case: test_02===")
    
    def test_03(demo_fixture):
        print("
    ===执行了case: test_03===")
    

    好了,现在我3个case都传入这个demo_fixture,运行一下,看下效果。这3个红色框中标出的分别就是每一个case执行前后的代码输出,符合我们的预期。

    二、addfinalizer

    现在,我们再来看addfinalizer,这里我姑且叫它终结器。在用法上,addfinalizer跟yield是不同的,需要你去注册作为终结器使用的函数。
    这里还是用上方的代码去修改,去掉yield关键字,增加一个新的函数demo_finalizer,并且注册成终结函数:

    import pytest
    
    
    @pytest.fixture()
    def demo_fixture(request):
        print("
    这个fixture在每个case前执行一次")
        def demo_finalizer():
            print("
    在每个case完成后执行的teardown")
    
        #注册demo_finalizer为终结函数    
        request.addfinalizer(demo_finalizer)
    
    def test_01(demo_fixture):
        print("
    ===执行了case: test_01===")
    
    def test_02(demo_fixture):
        print("
    ===执行了case: test_02===")
    
    def test_03(demo_fixture):
        print("
    ===执行了case: test_03===")
    

    接下来,运行一下,可以看到结果与使用yield的时候一致。

    三、yield与addfinalizer的区别

    那么,除了在使用上的区别之外,yield与addfinalizer还有什么不同呢?

    1. addfinalizer可以注册多个终结函数。

    import pytest
    
    
    @pytest.fixture()
    def demo_fixture(request):
        print("
    这个fixture在每个case前执行一次")
        def demo_finalizer():
            print("
    在每个case完成后执行的teardown")
        def demo_finalizer2():
            print("
    在每个case完成后执行的teardown2")
        def demo_finalizer3():
            print("
    在每个case完成后执行的teardown3")
    
        #注册demo_finalizer为终结函数    
        request.addfinalizer(demo_finalizer)
        request.addfinalizer(demo_finalizer2)
        request.addfinalizer(demo_finalizer3)
    
    def test_01(demo_fixture):
        print("
    ===执行了case: test_01===")
    
    def test_02(demo_fixture):
        print("
    ===执行了case: test_02===")
    
    def test_03(demo_fixture):
        print("
    ===执行了case: test_03===")
    

    在代码里增加demo_finalizer2,demo_finalizer3,这2个终结函数。运行一下:

    可以看到,注册的3个函数都被执行了,但是要注意的是执行顺序,与注册的顺序相反

    2. 当setUp的代码执行错误,addfinalizer依旧会执行

    这里接官方文档上的例子说明一下:

    @pytest.fixture
    def equipments(request):
        r = []
        for port in ('C1', 'C3', 'C28'):
        equip = connect(port)
        request.addfinalizer(equip.disconnect)
        r.append(equip)
        return r
    

    比如,C1,C3,C28这3个端口连接,如果C28这个端口失败了,这时候会抛出一个连接异常,但是在执行teardown关闭连接的时候,C1和C3的依然可以正常关闭。

  • 相关阅读:
    property补充
    利用描述符自定制property
    类的装饰器
    上下文协议管理
    描述符
    迭代器协议
    doc属性__module__属性__del__(垃圾回收)__call__方法
    【移动支付】.NET支付宝App支付接入
    【WPF】PopupColorEdit 的使用
    【MVVM Dev】PART_Editor的使用
  • 原文地址:https://www.cnblogs.com/pingguo-softwaretesting/p/13064232.html
Copyright © 2011-2022 走看看