需求
- 希望编写登陆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):
# setup
print('@@@@@@@@@@@@@@@@@@@@@get token')
#toke = login_web()
self.token = 'abc'yield # 运行测试用例 # teardown def 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 itemsmy_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):
# setup
print('@@@@@@@@@@@@@@@@@@@@@get token')
#toke = login_web()
self.token = 'abc'yield # 运行测试用例 # teardown def 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 itemsmy_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
-
于是有了下面的改进
例三
-
case修改如下
admin@pc-1:~$ cat my_test.py
import pytestclass TestWebLogin:
@pytest.fixture(scope='class', autouse=False)
def setup_teardown(self):
# setup
print('@@@@@@@@@@@@@@@@@@@@@get token')
#toke = login_web()
token = 'abc'yield token # 运行测试用例 # teardown def test_case1(self, setup_teardown): token = setup_teardown assert token is not None print(f'toke={token}') # 其他测试逻辑 def test_case2(self, setup_teardown): token = setup_teardown assert token is not None print(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 itemsmy_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了