大概的代码是这样:
import requests
import pytest
class TestRestApi():
url = 'http://xxx.com'
@pytest.fixture(scope="session")
def http_session(self):
# 省略设置 cookie 等步骤,返回一个 request.session 对象
return requests.Session()
def test_api_a(self, http_session):
response = http_session.post(self.url + '/app/sessioncontextget', json=body)
assert response.status_code == 200
data = response.json()
# 我想保存此 api 的一个返回值
self.session_id = data['data']['session_id']
assert data['code'] == 200
def test_api_b(self, http_session):
body = {
# 请求参数依赖前一个 api 的返回值
"sessionid": self.session_id,
}
response = http_session.post(self.url_ge + '/api/taskcreate', json=body)
assert response.status_code == 200
data = response.json()
assert data['errcode'] == 0
断点调试发现 session_id 是设置成功了的, test_api_a 也测试通过
但运行到 test_api_b 时却提示:AttributeError: 'TestRestApi' object has no attribute 'session_id'。不过这也很好理解,单测本来就是每个 case 独立的,每次相当于都是重新运行。
那么问题来了,这个需求怎么解决?
还有一个问题, pytest.fixture 的特性感觉不是很方便, http_session 变量无法被 IDE 识别,没有代码提示了(不过这个影响很小),关键是每个测试 case 都要传入 http_session 参数,感觉不够简洁。
初次使用 py.test ,可能理解不是很透彻,还请见谅。
解决了。再增加一个fixture
@staticmethod
@pytest.fixture(scope="session")
def global_values():
return {}
然后test case变成:
def test_api_a(self, http_session: requests.Session, global_values: dict):
……
global_values['session_id'] = data['data']['session_id']
def test_api_b(self, http_session: requests.Session, global_values: dict):
……
"sessionid": global_values['session_id'],
因为使用的是Python3,还是选择了把fixture设置的变量写进参数里面,再加上类型声明,这样IDE就能自动提示了
1
jerry14 2016-12-24 22:15:56 +08:00 via iPhone
1. 既然有个 case 需要两步,有个依赖,那就放到一起。之前的那个 case 不变
2. 你可以在 setup 方法里初始化 http_session ,然后作为一个实例属性 |