需求
希望編寫登陸web后做一些操作的測試用例,使用pytest框架 具體測試用例執行前,需要先拿到web的token,這個獲取token的動作只執行一次
例一
admin@pc-1:~$ cat my_test.py
import pytestclass TestWebLogin:@pytest.fixture(scope='function', autouse=True)def setup_teardown(self):# setupprint('@@@@@@@@@@@@@@@@@@@@@get token')#toke = login_web()self.token = 'abc'yield # 運行測試用例# teardowndef test_case1(self):# 使用 self.app 進行測試assert self.token is not None# 其他測試邏輯def test_case2(self):# 使用 self.app 進行測試assert self.token is not None# 其他測試邏輯
admin@pc-1:~$
admin@pc-1:~$
admin@pc-1:~$ pytest -sv my_test.py
================================================================= test session starts ==================================================================
platform linux -- Python 3.8.10, pytest-7.4.0, pluggy-1.2.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/centec
plugins: dash-2.14.1, solara-1.21.0, anyio-4.0.0
collected 2 items my_test.py::TestWebLogin::test_case1 @@@@@@@@@@@@@@@@@@@@@get token
PASSED
my_test.py::TestWebLogin::test_case2 @@@@@@@@@@@@@@@@@@@@@get token
PASSED================================================================== 2 passed in 0.01s ===================================================================
admin@pc-1:~$
解釋 class TestWebLogin里每個test_開頭的function就是一個測試用例 setup_teardown函數是實現login和logout,yield之前是setup,yield之后是teardown 運行結果是在每個test case前都執行了一遍獲取token的動作(scope=‘function’)
例二
希望所有的case只在執行第一個的時候獲取一下token,后面的case直接使用token即可 嘗試將fixture的scope從fuction
改為class
,并執行
admin@pc-1:~$ cat my_test.py
import pytestclass TestWebLogin:@pytest.fixture(scope='class', autouse=True)def setup_teardown(self):# setupprint('@@@@@@@@@@@@@@@@@@@@@get token')#toke = login_web()self.token = 'abc'yield # 運行測試用例# teardowndef test_case1(self):# 使用 self.app 進行測試assert self.token is not None# 其他測試邏輯def test_case2(self):# 使用 self.app 進行測試assert self.token is not None# 其他測試邏輯
admin@pc-1:~$
admin@pc-1:~$ pytest -sv my_test.py
================================================================= test session starts ==================================================================
platform linux -- Python 3.8.10, pytest-7.4.0, pluggy-1.2.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/centec
plugins: dash-2.14.1, solara-1.21.0, anyio-4.0.0
collected 2 items my_test.py::TestWebLogin::test_case1 @@@@@@@@@@@@@@@@@@@@@get token
FAILED
my_test.py::TestWebLogin::test_case2 FAILED======================================================================= FAILURES =======================================================================
_______________________________________________________________ TestWebLogin.test_case1 ________________________________________________________________self = <my_test.TestWebLogin object at 0x7f909a307cd0>def test_case1(self):# 使用 self.app 進行測試
> assert self.token is not None
E AttributeError: 'TestWebLogin' object has no attribute 'token'my_test.py:17: AttributeError
_______________________________________________________________ TestWebLogin.test_case2 ________________________________________________________________self = <my_test.TestWebLogin object at 0x7f909a307610>def test_case2(self):# 使用 self.app 進行測試
> assert self.token is not None
E AttributeError: 'TestWebLogin' object has no attribute 'token'my_test.py:22: AttributeError
=============================================================== short test summary info ================================================================
FAILED my_test.py::TestWebLogin::test_case1 - AttributeError: 'TestWebLogin' object has no attribute 'token'
FAILED my_test.py::TestWebLogin::test_case2 - AttributeError: 'TestWebLogin' object has no attribute 'token'
================================================================== 2 failed in 0.14s ===================================================================
admin@pc-1:~$
意料之外的是,在setup_teardown中明明已經給self.token賦值了,但是同在一個class下,其它的測試用例卻看不到self.token
!!! pytest的test class是比較特殊的,不能通過self.xxx來傳遞值,只能通過fixture 于是有了下面的改進
例三
admin@pc-1:~$ cat my_test.py
import pytestclass TestWebLogin:@pytest.fixture(scope='class', autouse=False)def setup_teardown(self):# setupprint('@@@@@@@@@@@@@@@@@@@@@get token')#toke = login_web()token = 'abc'yield token # 運行測試用例# teardowndef test_case1(self, setup_teardown):token = setup_teardownassert token is not Noneprint(f'toke={token}')# 其他測試邏輯def test_case2(self, setup_teardown):token = setup_teardownassert token is not Noneprint(f'token={token}')# 其他測試邏輯
admin@pc-1:~$
admin@pc-1:~$
admin@pc-1:~$
admin@pc-1:~$ pytest -sv my_test.py
================================================================= test session starts ==================================================================
platform linux -- Python 3.8.10, pytest-7.4.0, pluggy-1.2.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/centec
plugins: dash-2.14.1, solara-1.21.0, anyio-4.0.0
collected 2 items my_test.py::TestWebLogin::test_case1 @@@@@@@@@@@@@@@@@@@@@get token
toke=abc
PASSED
my_test.py::TestWebLogin::test_case2 token=abc
PASSED================================================================== 2 passed in 0.01s ===================================================================
admin@pc-1:~$
修改點包括 fixture的scope為class,表示在TestWebLogin中只會執行一次 fixture的autouse賦值為False,相當于需要顯式調用,不會自動運行 所有的賦值就沒有要加self了 setup_teardown的yield后面加token,類似于return token 后面的testcase 將setup_teardown作為一個參數傳入,然后進行顯式的賦值 從執行結果來看,獲取token只做了一次,后續所有的case都直接使用這個token了