一.概念
参数化,就是把测试过程中的数据提取出来,通过参数传递不同的数据来驱动用例运行。其实也就是数据驱动的概念。
使用 @pytest.mark.parametrize(argnames, argvalues) 装饰器达到批量传送参数的目的
在 unittest 中,使用ddt库配合unittest实现数据驱动。在pytest中并不需要额外的库,通过pytest.mark.parametrize()即可实现参数化。
parametrize()的第一个参数是用逗号分割的字符串列表,第二个参数是一个值列表
pytest有三种传参方式:
- @pytest.mark.parametrize() 通过装饰器方式进行参数化(最常使用)
- pytest.fixture()方式进行参数化,fixture装饰的函数可以作为参数传入其他函数
- conftest.py文件中存放参数化函数,可作用于模块内的所有测试用例
二.使用parametrize进行参数化
@pytest.mark.parametrize() 装饰器接收两个参数,第一个参数是以字符串的形式标识用例函数的参数,第二个参数以列表或元组的形式传递测试数据。
@pytest.mark.parametrize('参数化名称',参数化值)
-
单个数据
import pytest
data=["lucy","lisa"]
@pytest.mark.parametrize('name',data)
def test_params(name):
print(f'测试数据是{name}')
运行结果
-
一组数据
(1)列表嵌套字典
import pytest
data1 = [{"user": "admin", "password": "123456"},
{"user": "super", "password": "654321"},
{"user": "sysadmin", "password": "321456"}
]
@pytest.mark.parametrize("test_data",data1)
def test_login(test_data):
print(f"username is {test_data['user']}\n password is {test_data['password']}")
# data=["lucy","lisa"]
#
# @pytest.mark.parametrize('name',data)
# def test_params(name):
# print(f'测试数据是{name}')
运行结果
(2)列表嵌套列表
import pytest
data2 = [['admin', '12346'], ["super", "654321"], ['sysadmin', '321456']]
@pytest.mark.parametrize("user,password", data2)
def test_login(user,password):
print(f"username is {user} and password is {password}")
运行结果
(3)列表嵌套元祖
import pytest
data2 = [('admin', '12346'), ("super", "654321"), ("sysadmin", '321456')]
@pytest.mark.parametrize("user,password", data2)
def test_login(user,password):
print(f"username is {user} and password is {password}")
运行结果
相比较于嵌套列表,只是将列表换成了元祖
三.使用pytest.fixture进行参数化
上面介绍了pytest中的自带的参数化方法,我们也可以通过使用fixture中的params参数来做参数化。
request.param:用于获取测试的请求参数。【获取测试上下文的信息】
可以在fixture函数参数化的时候,通过request.param获取到测试的请求参数。【实现fixture函数的参数化】
yield request.param 此处是param
①【注意】fixture函数的 params 请求参数数量(请求参数的数据类型为列表/元组,请求参数数量为列表/元组元素个数)决定fixture函数执行的次数。
②【注意】此时fixture函数的装饰器 @pytest.fixture(params=get_data) 参数不能忘记传值。
(1)列表嵌套字典
import pytest
data3 = [{"user": "admin", "password": "123456"},
{"user": "super", "password": "654321"},
{"user": "sysadmin", "password": "321456"}
]
@pytest.fixture(params=data3,autouse=True,scope="class")
def get_data(request):
print("fixture begin")
yield request.param
print("fixture end")
class TestLogin:
def test_login(self,get_data):
test_data = get_data
print("username is {} AND password is {}".format(test_data["user"], test_data["password"]))
运行结果
(2)列表嵌套列表
import pytest
#此次是列表嵌套列表
data2 = [['admin', '12346'], ["super", "654321"], ["sysadmin", '321456']]
@pytest.fixture(params=data2,autouse=True,scope="class")
def get_data(request):
print("fixture begin")
yield request.param
print("fixture end")
class TestLogin:
def test_login(self,get_data):
test_data = get_data
print("username is {} and password is {}".format(test_data[0], test_data[1]))
运行结果
(3)列表嵌套元祖
import pytest
#此处是列表嵌套元祖
data2 = [('admin', '12346'), ("super", "654321"), ("sysadmin", '321456')]
@pytest.fixture(params=data2,autouse=True,scope="class")
def get_data(request):
print("fixture begin")
yield request.param
print("fixture end")
class TestLogin:
def test_login(self,get_data):
test_data = get_data
print("username is {};password is {}".format(test_data[0], test_data[1]))
运行结果
四.使用conftest.py进行参数化
conftest.py特点
- conftest.py 文件中存放参数化函数,可作用于模块内的所有测试用例
- conftest.py 配置里可以实现数据共享,不需要import就能自动找到一些配置,pytest默认读取里面的配置
conftest.py配置需要注意以下点:
- conftest.py配置脚本名称是固定的,不能改名称
- conftest.py与运行的用例要在同一个pakage下,并且有__init__.py文件
- 不需要import导入 conftest.py,pytest用例会自动查找
conftest.py应用场景
1、每个接口需共用到的token
conftest.py
import pytest
@pytest.fixture(scope='session')
def get_token():
token = 'qeehfjejwjwjej11sss112'
return token
test_params.py
def test_get_token(get_token):
token = get_token
print(token)
运行结果
2、每个接口需共用到的测试用例数据
编写一个fixture在conftest.py,内容如下
data = [["admin","123456"],["superadmin","654321"]]
@pytest.fixture(scope='session',params=data)
def get_test_data(request):
yield request.param
在测试脚本里面使用,只需要引入即可,新建一个测试文件test_params.py,内容如下
def test_get_data(get_test_data):
print(f"user is {get_test_data[0]} and pwd is {get_test_data[1]}")
运行结果
3、每个接口需共用到的配置信息
编写一个fixture在conftest.py,内容如下
@pytest.fixture(scope='session')
def get_base_url():
base_url = "http://www.baidu.com"
return base_url
在测试脚本里面使用,只需要引入即可,新建一个测试文件test_params.py,内容如下
def test_base_url(get_base_url):
url = get_base_url
print(url)
运行结果