# pytest fixture的分級(scope) ###### tags: `unit-test` `pytest` 閱讀本文前,我們會假設各位都知道 fixture是一個"測試單元都能拿去用的公共物件" 先上個例子 ```python= @pytest.fixture def db(): # open db yield # close db def test1(db): logging.info("test1 use db") def test2(db): logging.info("test2 use db") ``` 現在我們有一個fixture跟兩個測試,如果他們都需要跟db交互的話,會發生什麼事呢? 在上面這個範例中,fixture會被運行兩次。但如果在測試情境上,我們覺得db其實不用每次都重新打開一次要怎麼辦? 當我們在cmd中運行pytest的瞬間,這個fixture就會在每個測試開始的時候將db打開並yield住,保持db開啟,並在測試結束時關閉db,沒有問題,也不會出錯。 但今天如果這個打開db的行為是另外一個相當耗時或記憶體的行為時,又要怎麼辦呢? 於是在pytest fixture中,有scope這個參數,可以讓撰寫測試的各位決定fixture的觸發頻率,scope一共有五種。 ## Function 預設的scope層級,會在每個test function結束後進行teardown並結束 ## class 如果在撰寫測試單元時有用class把測試包起來,那麼在class內的測試可以用這個scope來確認在同個class內fixture只觸發一次 ```python= import pytest @pytest.fixture(scope="class") def my_fixture(): print("Setup") yield print("Teardown") class TestClass: def test_foo(self, my_fixture): print("my_fixture setup once in this class") def test_bar(self, my_fixture): print("my_fixture setup once in this class") ``` ## module 在同個file內的測試都會確保只觸發一次fixture 假設我們的資料夾結構長這樣 ``` project/ ├── tests/ │ ├── conftest.py │ └── test_module1.py │ └── test_module2.py ``` 而我們的fixture長這樣 ```python= @pytest.fixture(scope="module") def db(): # open db yield # close db ``` 那麼test_module1.py與test_module2.py會各自觸發一次fixture ## package 在同個folder內的測試會觸發一次fixture 用跟上面一樣的資料夾結構 ``` project/ ├── tests/ │ ├── conftest.py │ └── test_module1.py │ └── test_module2.py ``` ```python= @pytest.fixture(scope="package") def db(): # open db yield # close db ``` 現在test_module1.py與test_module2.py只會觸發一次fixture了 ## session 在整個測試流程中此fixture只會觸發一次 # 總結 其實還有很多小坑,包含fixture運作的順序,scope可以是動態等等,但本篇範例主要是讓各位理解,其實pytest可以用scope來讓撰寫測試的各位決定fixture該在什麼時候觸發。 有了以上這些分級的概念,相信各位在撰寫自己的測試時,就能根據不同fixture function的用途分配scope,最終達到節省測試總時長與消耗資源的目的。 如果有更多問題也歡迎詢問,或查閱官方文件如下: https://docs.pytest.org/en/stable/how-to/fixtures.html#how-to-fixtures
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up