您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“pytest解讀fixtures之Teardown怎么處理yield和addfinalizer”,內容詳細,步驟清晰,細節處理妥當,希望這篇“pytest解讀fixtures之Teardown怎么處理yield和addfinalizer”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
當我們運行測試函數時,我們希望確保測試函數在運行結束后,可以自己清理掉對環境的影響。這樣的話,它們就不會干擾任何其他的測試函數,更不會日積月累的留下越來越多的測試數據。
用過unittest的朋友相信都知道teardown這個函數,做的是一樣的事情,那么下面姑且就把這種“善后”工作的代碼叫做teardown代碼吧。
而pytest中的fixture,也提供了這樣一個非常有用的系統,我們可以在里面定義teardown代碼。
這里可以使用2種方式來實現,分別是yield
和addfinalizer
在有yield
的fixtures函數中,關鍵字yield
可以代替 return
,可以把fixture里的一些對象傳遞給調用它們的fixture函數或者測試函數。
就像其他普通的fixture函數一樣。區別僅僅是:
yield
替換掉了return
teardown代碼放置在yield
之后
pytest在執行fixture函數時,會根據fixture函數之間的線性關系順序調用的。但是,當測試函數運行結束的時候,pytest又會按照之前的順序反方向來執行fixture中yield之后的代碼。結合示例看下,這里沒有引用官方示例了,手寫一個直觀些的:
import pytest @pytest.fixture def fixture_one(): print("\n執行fixture_one") return 1 @pytest.fixture def fixture_two(fixture_one): print("\n執行fixture_two") yield 2 print("\n執行fixture_two的teardown代碼") @pytest.fixture def fixture_adding(fixture_one, fixture_two): print("\n執行fixture_adding") result = fixture_one + fixture_two yield result print("\n執行fixture_adding的teardown代碼") def test_demo(fixture_two, fixture_adding): print("\n執行測試函數test_demo") assert fixture_adding == 3
代碼中,fixture中調用多個fixture,測試函數中調用多個fixture,通過前面幾章的接觸,相信大家這時候已經可以梳理出前后調用順序了:
test_demo 測試函數,先去調用fixture函數 fixture_two,然后調用 fixture_adding。
在fixture函數 fixture_two中,又會去調用另一個fixture函數 fixture_one。
在fixture函數 fixture_adding中,調用了 fixture_one、fixture_two。
所以,fixture函數的先后順序是:fixture_one
、fixture_two
、fixture_adding
。那么,可以得知測試結束后的teardown代碼執行順序:fixture_adding
、fixture_two
。
運行一下代碼,驗證下結果是否符合我們的梳理:
============================= test session starts ============================= platform win32 -- Python 3.6.8, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 rootdir: D:\練習\demo_fixture plugins: allure-pytest-2.8.32, celery-4.3.0, Faker-4.14.2, base-url-1.4.2, html-2.1.1, metadata-1.10.0collected 1 item test_module.py 執行fixture_one 執行fixture_two 執行fixture_adding . 執行測試函數test_demo 執行fixture_adding的teardown代碼 執行fixture_two的teardown代碼 [100%] ============================== 1 passed in 0.09s ==============================
結果與我們剛才梳理的一致。
但是,值得注意的是,就算是teardown的代碼是按照正確的順序執行,也不能保證代碼能正常執行的。比如說teardown里的某些代碼執行異常了,導致別的清理動作也沒法執行。這里就涉及到另一個點了:健壯的fixture結構應該是什么樣子。這個官方文檔另起進行說明,這里同樣。
在pytest中想要做teardown的處理,除了使用帶有yield的fixture函數,還可以直接添加終結器。直接來看示例代碼:
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===")
看下運行結果:
============================= test session starts ============================= platform win32 -- Python 3.6.8, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 rootdir: D:\練習\demo_fixture plugins: allure-pytest-2.8.32, celery-4.3.0, Faker-4.14.2, base-url-1.4.2, html-2.1.1, metadata-1.10.0collected 2 items test_module.py 這個fixture在每個case前執行一次 . ===執行了case: test_01=== 在每個case完成后執行的teardown 這個fixture在每個case前執行一次 . ===執行了case: test_02=== 在每個case完成后執行的teardown [100%] ============================== 2 passed in 0.10s ============================== Process finished with exit code 0
運行結果可以看出,效果與yield是一致的。這算是一個固定寫法,關于request
文檔中也有另外的講解,屆時再分享。
上方代碼是一個終結函數,如果要注冊多個呢?
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") #注冊demo_finalizer為終結函數 request.addfinalizer(demo_finalizer) request.addfinalizer(demo_finalizer2) def test_01(demo_fixture): print("\n===執行了case: test_01===") def test_02(demo_fixture): print("\n===執行了case: test_02===") if __name__ == '__main__': pytest.main(['-s', 'test_module.py'])
運行結果:
============================= test session starts ============================= platform win32 -- Python 3.6.8, pytest-5.4.3, py-1.9.0, pluggy-0.13.1 rootdir: D:\練習\demo_fixture plugins: allure-pytest-2.8.32, celery-4.3.0, Faker-4.14.2, base-url-1.4.2, html-2.1.1, metadata-1.10.0collected 2 items test_module.py 這個fixture在每個case前執行一次 . ===執行了case: test_01=== 在每個case完成后執行的teardown2 在每個case完成后執行的teardown 這個fixture在每個case前執行一次 . ===執行了case: test_02=== 在每個case完成后執行的teardown2 在每個case完成后執行的teardown [100%] ============================== 2 passed in 0.09s ============================== Process finished with exit code 0
這里要注意的是,多個終結器的情況下,執行的順序是與注冊時候相反的。
目前從官方文檔中看到的是
We have to be careful though, because pytest will run that finalizer once it’s been added, even if that fixture raises an exception after adding the finalizer.
一旦添加了終結器,pytest便會執行。
但是,當我嘗試在setup代碼中進行拋錯,終結器的代碼卻并沒有執行。
讀到這里,這篇“pytest解讀fixtures之Teardown怎么處理yield和addfinalizer”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。