参考:https:www.cnblogs.combenben-wup11542411.htmlhttps:blog.csdn.netliudinglong1989articlede
参考:
https://www.cnblogs.com/benben-wu/p/11542411.html
https://blog.csdn.net/liudinglong1989/article/details/106206212
前言
unittest框架使用的第三方库ddt来参数化的,而pytest框架就直接使用装饰器@pytest.mark.parametrize来对测试用例进行传参。这个是针对测试方法来参数化,还有一种是针对前置处理函数来传参。但往往这两种是可以结合使用。
fixture之Params参数化(单个列表)
前面讲fixture函数时,它有个参数params用来传递参数,并且与request结合使用,先看单个:
import pytest
seq = [1, 2, 3]
@pytest.fixture(params=seq)
def test_data(request):
print("参数")
return request.param
class TestData:
def test_1(self, test_data):
print("用例", test_data)
if __name__ == '__main__':
pytest.main()
—————————————————————————————————
运行结果:
fixture_test03.py::TestData::test_1[1] 参数
PASSED [ 33%]用例 1
fixture_test03.py::TestData::test_1[2] 参数
PASSED [ 66%]用例 2
fixture_test03.py::TestData::test_1[3] 参数
PASSED [100%]用例 3
============================== 3 passed in 0.05s ==============================
fixture之Params参数化(单个列表嵌套其他格式)
列表里有多个dict数据,request会自动化循环读取每个索引下的值,从0开始,看下面例子:
注意:params需要与request一起使用。
import pytest
seq = [{'a':1,'b':2},{'c':3,'d':4}]
@pytest.fixture(params=seq)
def test_data(request):
print("参数:%s"%request.param)
return request.param
class TestData:
def test_1(self, test_data):
print("用例", test_data)
if __name__ == '__main__':
pytest.main()
—————————————————————————————————
运行结果:
============================== 2 passed in 0.04s ==============================
Process finished with exit code 0
参数:{'a': 1, 'b': 2}
PASSED [ 50%]用例 {'a': 1, 'b': 2}
参数:{'c': 3, 'd': 4}
PASSED [100%]用例 {'c': 3, 'd': 4}
装饰器@pytest.mark.parametrize参数化(单个列表)
# 方式一:直接写
@pytest.mark.parametrize("a", ['北京','上海','重庆'])
def test_add01(a):
print(a)
data = ['北京','上海','重庆']
# 方式二:参数为列表
@pytest.mark.parametrize("a", data)
def test_add02(a):
print(a)
装饰器@pytest.mark.parametrize参数化(单个列表嵌套其他格式)
import pytest
test_datas = [
(11, 22, 33),
(22, 33, 55)
]
datas_dict = [
{"a": 1, "b": 2, "c": 3},
{"a": 11, "b": 22, "c": 33},
{"a": 111, "b": 222, "c": 333},
]
# 方式一:直接写
@pytest.mark.parametrize("a, b, c", [(1, 2, 3), (4, 5, 9)])
def test_add01(a, b, c):
res = a + b
assert res == c
# 方式二:参数为列表中嵌套元组
@pytest.mark.parametrize("data", test_datas)
def test_add02(data):
res = data[0] + data[1]
assert res == data[2]
# 方式三:参数为列表中嵌套字典
@pytest.mark.parametrize("data", datas_dict)
def test_add03(data):
res = data["a"] + data["b"]
assert res == data["c"]
装饰器@pytest.mark.parametrize参数化(多个组合)
#若要获得多个参数化参数的所有组合,可以堆叠参数化装饰器
import pytest
@pytest.mark.parametrize("a",[0,1])
@pytest.mark.parametrize("b",[3,4])
def test_01(a,b):
print("测试数据组合:a->%s,b->%s"%(a,b))
if __name__ == "__main__":
pytest.main(["-s", "test_3.py"])
_______________________________________________________运行结果:
test_123.py 测试数据组合:a->0,b->3
.测试数据组合:a->1,b->3
.测试数据组合:a->0,b->4
.测试数据组合:a->1,b->4
import pytest
@pytest.mark.parametrize("a", [0, 1])
@pytest.mark.parametrize("b", [3, 4])
@pytest.mark.parametrize("c", [2, 6])
def test_01(a, b, c):
print("测试数据组合:a->%s,b->%s,c->%s" % (a, b, c))
if __name__ == "__main__":
pytest.main(["-s", "test_123.py"])
———————————————————————————————————
运行结果:
test_123.py 测试数据组合:a->0,b->3,c->2
.测试数据组合:a->1,b->3,c->2
.测试数据组合:a->0,b->4,c->2
.测试数据组合:a->1,b->4,c->2
.测试数据组合:a->0,b->3,c->6
.测试数据组合:a->1,b->3,c->6
.测试数据组合:a->0,b->4,c->6
.测试数据组合:a->1,b->4,c->6
.
单个fixture与@pytest.mark.parametrize组合
如果装饰器@pytest.mark.parametrize与request结合使用,如果测试方法写在类中,则@pytest.mark.parametrize的参数名称要与@pytest.fixture函数名称保持一致。并且要添加indirect=True参数,目的是把ss_data当做函数去执行,而不是参数。
根据开关indirect自由控制,默认是False当做参数。indirect是True则当做函数
单个参数--例子1.1 参数是列表格式,indirect=True
import pytest
seq = [1,2,3]
@pytest.fixture()
def ss_data(request):
print("参数:%s"%request.param)
return request.param
class TestData:
@pytest.mark.parametrize("ss_data",seq,indirect=True)
def test_1(self,ss_data):
print("用例", ss_data)
if __name__ == '__main__':
pytest.main()
—————————————————————————————————运行结果:
test_123.py 参数:1
用例 1
.参数:2
用例 2
.参数:3
用例 3
.
单个参数--例子1.2 参数是列表格式,indirect=False
如果不使用fixture装饰器函数,也不使用外部函数,也是可以的,indirect默认是False例子如下:
import pytest
seq = [1,2,3]
class TestData:
@pytest.mark.parametrize("x",seq,indirect=False)
def test_1(self,x):
print("用例", x)
if __name__ == '__main__':
pytest.main()
———————————————————————————————————运行结果:
test_123.py 用例 1
.用例 2
.用例 3
.
单个参数--例子2 参数是列表嵌套元组格式,indirect=True
import pytest
seq = [(1,2),(3,4)]
@pytest.fixture()
def get_data(request):
x = request.param[0]
y = request.param[1]
print(x,111)
print(y,222)
# print(request.param)
pass
# indirect=True声明x是个函数
@pytest.mark.parametrize("get_data",seq,indirect=True)
def test_data(get_data):
print(get_data)
if __name__ == '__main__':
pytest.main()
—————————————————————————————————
运行结果:
test_123.py 1 111
2 222
None
.3 111
4 222
None
.
多个fixture与@pytest.mark.parametrize组合
参数化装饰器也可以叠加,使用parametrize装饰器叠加时,用例组合是2个参数个数相乘
import pytest
seq1 = [1,2,3]
seq2 = [4,5,6]
@pytest.fixture()
def get_seq1(request):
seq1 = request.param
print("seq1:",seq1)
return seq1
@pytest.fixture()
def get_seq2(request):
seq2 = request.param
print("seq2:", seq2)
return seq2
@pytest.mark.parametrize("get_seq1",seq1,indirect=True)
@pytest.mark.parametrize("get_seq2",seq2,indirect=True)
def test_1(get_seq1,get_seq2):
print(get_seq1,11)
print(get_seq2,22)
if __name__ == '__main__':
pytest.main()
—————————————————————————————————
运行结果:
test_123.py seq1: 1
seq2: 4
1 11
4 22
.seq1: 2
seq2: 4
2 11
4 22
.seq1: 3
seq2: 4
3 11
4 22
.seq1: 1
seq2: 5
1 11
5 22
.seq1: 2
seq2: 5
2 11
5 22
.seq1: 3
seq2: 5
3 11
5 22
.seq1: 1
seq2: 6
1 11
6 22
.seq1: 2
seq2: 6
2 11
6 22
.seq1: 3
seq2: 6
3 11
6 22
.