因为测试用例的多样性,我们不能硬编码,比如登录的fixture,不能只写入固定的登录用户名和密码,一个是不方便后期维护,另外一个是不好拓展。
在之前的代码中我们发现,fixture是没办法直接传参的,举个例子:
import pytest
@pytest.fixture
def login(name ,password):
print(f"用户{name},使用密码{password}登录成功")
def test_01(login):
login("admin","123456")
print("正在执行test01")
def test_02(login):
login("user01","666666")
print("正在执行test02")
if __name__ == '__main__':
pytest.main(['fixture传参.py', '-s'])
目的很简单,执行casetest_01
的时候使用admin
账号,执行casetest_02
的时候,使用user01
的账号。但是 执行的时候就报错了:
@pytest.fixture
def login(name ,password):
E fixture 'name' not found
好像fixture
默认接受的参数必须是另外一个fixture
,但是又不存在另外一个叫name
的fixture,所以此时就报异常。
所以,为了解决这一问题,我们要学习新的知识点:@pytest.mark.parametrize
之前在讲fixture的参数 params的时候,讲到过request的使用:
import pytest
# 定义的夹具函数,使用装饰器pytest.fixture
@pytest.fixture(params=["胡八万","胡三条","胡七筒"])
def login(request):
temp = request.param
print(f"login:用户{temp}执行登录操作")
return temp
#当fixture 的params参数 会被循环执行
def test_01(login):
print(f"{login}已经登录成功~")
if __name__ == '__main__':
pytest.main(['MyPytest.py', '-s'])
执行结果:
collected 3 items
MyPytest.py login:用户胡八万执行登录操作
胡八万已经登录成功~
.login:用户胡三条执行登录操作
胡三条已经登录成功~
.login:用户胡七筒执行登录操作
胡七筒已经登录成功~
.
============================== 3 passed in 0.07s ==============================
***Repl Closed***
request是fixture的传参的固定写法。
为了解决上述问题,我们使用@pytest.mark.parametrize
配合request可以完美解决:
import pytest
@pytest.fixture
def login(request):
param = request.param
print(f"用户{param['name']},使用密码{param['password']}登录成功")
data01 = [{'name': 'admin', 'password': '123456'}]
@pytest.mark.parametrize("login", data01, indirect=True)
def test_01(login):
print("正在执行test01")
data02 = [{'name': 'user01', 'password': '666666'}]
@pytest.mark.parametrize("login", data02, indirect=True)
def test_02(login):
print("正在执行test02")
if __name__ == '__main__':
pytest.main(['fixture传参.py', '-s'])
执行结果:
collected 2 items
fixture传参.py
用户admin,使用密码123456登录成功
正在执行test01
.
用户user01,使用密码666666登录成功
正在执行test02
.
============================== 2 passed in 0.07s ==============================
***Repl Closed***
indirect = True
是将login作为一个函数去执行,而不是一个参数,data则是这个函数的入参。
data本质是一个列表,如果入参是fixture是单个入参,则data可以定义为:
data = [“key1”,“key2”,… …]
那么执行case则遍历执行key1
,key2
如果fixture是多个参数的入参,则data需要传入字典形式:
data=[{“key1”:“value1”},{“key2”:“value2”}… … ]
同理函数遍历执行{"key1":"value1"}
, {"key2":"value2"}
的场景
import pytest
@pytest.fixture
def openBrowser(request):
"""打开不同类型的浏览器"""
browserType = request.param
print(f"正在使用{browserType}浏览器")
@pytest.fixture
def login(request):
param = request.param
print(f"用户{param['name']},使用密码{param['password']}登录成功")
browserTypes = ["IE"]
userInfo = [{'name': 'admin', 'password': '123456'}]
@pytest.mark.parametrize("login", userInfo, indirect=True)
@pytest.mark.parametrize("openBrowser", browserTypes, indirect=True)
def test_01(openBrowser, login):
print("正在执行test01")
if __name__ == '__main__':
pytest.main(['fixture传参.py', '-s'])
运行结果:
collected 1 item
fixture传参.py
正在使用IE浏览器
用户admin,使用密码123456登录成功
正在执行test01
.
============================== 1 passed in 0.07s ==============================
***Repl Closed***
import pytest
@pytest.fixture
def openBrowser(request):
"""打开不同类型的浏览器"""
browserType = request.param
print(f"正在使用{browserType}浏览器")
@pytest.fixture
def login(request):
param = request.param
print(f"用户{param['name']},使用密码{param['password']}登录成功")
data = [('IE', {'name': 'admin', 'password': '123456'})]
@pytest.mark.parametrize("openBrowser,login", data, indirect=True)
def test_01(openBrowser, login):
print("正在执行test01")
if __name__ == '__main__':
pytest.main(['fixture传参.py', '-s'])
执行结果:
fixture传参.py
正在使用IE浏览器
用户admin,使用密码123456登录成功
正在执行test01
.
============================== 1 passed in 0.07s ==============================
***Repl Closed***
如果我们想测试多种场景即可改动data的数据,进行参数化:
import pytest
@pytest.fixture
def openBrowser(request):
"""打开不同类型的浏览器"""
browserType = request.param
print(f"正在使用{browserType}浏览器")
@pytest.fixture
def login(request):
param = request.param
print(f"用户{param['name']},使用密码{param['password']}登录成功")
data = [('IE', {'name': 'admin', 'password': '123456'}),('IE', {'name': 'root', 'password': '888888'}),('Chrome', {'name': 'admin', 'password': '123456'})]
@pytest.mark.parametrize("openBrowser,login", data, indirect=True)
def test_01(openBrowser, login):
print("正在执行test01")
if __name__ == '__main__':
pytest.main(['fixture传参.py', '-s'])
执行结果:
fixture传参.py 正在使用IE浏览器
用户admin,使用密码123456登录成功
正在执行test01
.正在使用IE浏览器
用户root,使用密码888888登录成功
正在执行test01
.正在使用Chrome浏览器
用户admin,使用密码123456登录成功
正在执行test01
.
============================== 3 passed in 0.07s ==============================
***Repl Closed***