【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("\n這個fixture在每個case前執行一次")
    yield
    print("\n在每個case完成后執行的teardown")

def test_01(demo_fixture):
    print("\n===執行了case: test_01===")

def test_02(demo_fixture):
    print("\n===執行了case: test_02===")

def test_03(demo_fixture):
    print("\n===執行了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("\n這個fixture在每個case前執行一次")
    def demo_finalizer():
        print("\n在每個case完成后執行的teardown")

    #注冊demo_finalizer為終結函數    
    request.addfinalizer(demo_finalizer)

def test_01(demo_fixture):
    print("\n===執行了case: test_01===")

def test_02(demo_fixture):
    print("\n===執行了case: test_02===")

def test_03(demo_fixture):
    print("\n===執行了case: test_03===")

接下來,運行一下,可以看到結果與使用yield的時候一致。

三、yield與addfinalizer的區別

那么,除了在使用上的區別之外,yield與addfinalizer還有什么不同呢?

1. addfinalizer可以注冊多個終結函數。

import pytest


@pytest.fixture()
def demo_fixture(request):
    print("\n這個fixture在每個case前執行一次")
    def demo_finalizer():
        print("\n在每個case完成后執行的teardown")
    def demo_finalizer2():
        print("\n在每個case完成后執行的teardown2")
    def demo_finalizer3():
        print("\n在每個case完成后執行的teardown3")

    #注冊demo_finalizer為終結函數    
    request.addfinalizer(demo_finalizer)
    request.addfinalizer(demo_finalizer2)
    request.addfinalizer(demo_finalizer3)

def test_01(demo_fixture):
    print("\n===執行了case: test_01===")

def test_02(demo_fixture):
    print("\n===執行了case: test_02===")

def test_03(demo_fixture):
    print("\n===執行了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的依然可以正常關閉。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM