# 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
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.