<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
當我們執行測試函數時,我們希望確保測試函數在執行結束後,可以自己清理掉對環境的影響。這樣的話,它們就不會干擾任何其他的測試函數,更不會日積月累的留下越來越多的測試資料。
用過unittest的朋友相信都知道teardown這個函數,做的是一樣的事情,那麼下面姑且就把這種“善後”工作的程式碼叫做teardown程式碼吧。
而pytest中的fixture,也提供了這樣一個非常有用的系統,我們可以在裡面定義teardown程式碼。
這裡可以使用2種方式來實現,分別是yield
和addfinalizer
在有yield
的fixtures函數中,關鍵字yield
可以代替 return
,可以把fixture裡的一些物件傳遞給呼叫它們的fixture函數或者測試函數。
就像其他普通的fixture函數一樣。區別僅僅是:
yield
替換掉了return
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,通過前面幾章的接觸,相信大家這時候已經可以梳理出前後呼叫順序了:
所以,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程式碼中進行拋錯,終端子的程式碼卻並沒有執行。
嘗試搜尋外網暫時也沒得到有效的幫助,只能在GitHub上向pytest提了issue了,這裡算是埋下一個坑,待後續解決,更多關於Teardown處理yield addfinalizer的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45