在Unittest里使用DDT装饰器进行数据驱动测试,相对应的,在Pytest里会使用parameterize装饰器进行数据驱动。本文将围绕parameterize装饰测试类和测试方法的区别,传递单个测试数据和多个测试数据的用法,传递不同数据类型(元组,列表,字典)的区别,以及它和DDT之间的区别做一个简要介绍。
1.装饰测试类
import pytest
list1 = [(1,1,1),(3,3,9),(5,6,30)]
def multi(a,b):
return a*b
@pytest.mark.parametrize("a,b,c",list1)
class TestParam:
def test_1_multi(self,a,b,c):
print("测试函数1的数据a是{},b是{},c是{}".format(a,b,c))
assert multi(a,b) == c
def test_2_multi(self,a,b,c):
print("测试函数2的数据a是{},b是{},c是{}".format(a,b,c))
assert multi(a,b) == c
if __name__ == '__main__':
pytest.main()
输出结果是:
test_param.py .测试函数1的数据a是1,b是1,c是1
.测试函数1的数据a是3,b是3,c是9
.测试函数1的数据a是5,b是6,c是30
.测试函数2的数据a是1,b是1,c是1
.测试函数2的数据a是3,b是3,c是9
.测试函数2的数据a是5,b是6,c是30
[100%]
========================== 6 passed in 0.26 seconds ===========================
Process finished with exit code 0
2.装饰测试方法
import pytest
list1 = [(1,1,1),(3,3,9),(5,6,30)]
list2 = [(1,3,3),(2,3,6),(3,6,18)]
def multi(a,b):
return a*b
class TestParam:
@pytest.mark.parametrize("a,b,c", list1)
def test_1_multi(self,a,b,c):
print("测试函数1的数据a是{},b是{},c是{}".format(a,b,c))
assert multi(a,b) == c
@pytest.mark.parametrize("a,b,c", list2)
def test_2_multi(self,a,b,c):
print("测试函数2的数据a是{},b是{},c是{}".format(a,b,c))
assert multi(a,b) == c
if __name__ == '__main__':
pytest.main()
输出结果是:
test_param.py .测试函数1的数据a是1,b是1,c是1
.测试函数1的数据a是3,b是3,c是9
.测试函数1的数据a是5,b是6,c是30
.测试函数2的数据a是1,b是3,c是3
.测试函数2的数据a是2,b是3,c是6
.测试函数2的数据a是3,b是6,c是18
[100%]
========================== 6 passed in 0.08 seconds ===========================
Process finished with exit code 0
由此可见,装饰测试类时,会把所有的测试数据传给所有的测试函数,装饰测试函数时,只会将测试数据传给制定的测试函数。
1.传递单个数据
import pytest
list0 = [1,2,3,4,5,6,7]
@pytest.mark.parametrize("a", list0)
def test_1_multi(self,a):
print("测试函数1的数据a是{}".format(a))
if __name__ == '__main__':
pytest.main(["-v"])
输出:
test_param.py .测试函数1的数据a是1
.测试函数1的数据a是2
.测试函数1的数据a是3
.测试函数1的数据a是4
.测试函数1的数据a是5
.测试函数1的数据a是6
.测试函数1的数据a是7
[100%]
========================== 7 passed in 0.11 seconds ===========================
Process finished with exit code 0
2.传递多个数据
(1)用一个参数接受多个测试数据
(2)用多个参数接受多个测试数据
import pytest
list1 = [(1,1,1),(3,3,9),(5,6,30)]
list2 = [(1,3,3),(2,3,6),(3,6,18)]
def multi(a,b):
return a*b
class TestParam:
@pytest.mark.parametrize("data", list1)
def test_1_multi(self,data):
print("测试函数2的数据a是{},b是{},c是{}".format(data[0],data[1],data[2]))
assert multi(data[0], data[1]) == data[2]
@pytest.mark.parametrize("a,b,c", list2)
def test_2_multi(self,a,b,c):
print("测试函数2的数据a是{},b是{},c是{}".format(a,b,c))
assert multi(a,b) == c
if __name__ == '__main__':
pytest.main(["-v"])
输出结果:
test_param.py .测试函数2的数据a是1,b是1,c是1
.测试函数2的数据a是3,b是3,c是9
.测试函数2的数据a是5,b是6,c是30
.测试函数2的数据a是1,b是3,c是3
.测试函数2的数据a是2,b是3,c是6
.测试函数2的数据a是3,b是6,c是18
[100%]
========================== 6 passed in 0.07 seconds ===========================
Process finished with exit code 0
当测试用例需要多个测试数据时,我们可以使用嵌套元组的列表来传递测试数据,
第一种方法:用一个参数接受数据,就是传入一个元组,元组里的数据运用索引的方法就可以提取出来;
第二种方法:用多个参数接收数据,则位置参数与实际测试数据一一对应即可。
import pytest
list1 = [(1,1,1),(3,3,9),(5,6,30)]
list2 = [[1,3,3],[2,3,6],[3,6,18]]
list3 = [{"a":1,"b":5,"c":5},{"a":2,"b":5,"c":10},{"a":3,"b":5,"c":15}]
def multi(a,b):
return a*b
class TestParam:
# 测试数据为嵌套元组的列表
@pytest.mark.parametrize("data", list1)
def test_1_multi(self,data):
print("测试函数1的数据a是{},b是{},c是{}".format(data[0],data[1],data[2]))
assert multi(data[0], data[1]) == data[2]
# 测试数据为嵌套列表的列表
@pytest.mark.parametrize("a,b,c", list2)
def test_2_multi(self,a,b,c):
print("测试函数2的数据a是{},b是{},c是{}".format(a,b,c))
assert multi(a,b) == c
# 测试数据为嵌套字典的列表
@pytest.mark.parametrize("dict1", list3)
def test_3_multi(self, dict1):
print("测试函数3的数据a是{},b是{},c是{}".format(dict1["a"], dict1["b"], dict1["c"]))
assert multi(dict1["a"], dict1["b"]) == dict1["c"]
if __name__ == '__main__':
pytest.main(["-v"])
输出结果:
test_param.py .测试函数1的数据a是1,b是1,c是1
.测试函数1的数据a是3,b是3,c是9
.测试函数1的数据a是5,b是6,c是30
.测试函数2的数据a是1,b是3,c是3
.测试函数2的数据a是2,b是3,c是6
.测试函数2的数据a是3,b是6,c是18
.测试函数3的数据a是1,b是5,c是5
.测试函数3的数据a是2,b是5,c是10
.测试函数3的数据a是3,b是5,c是15
[100%]
========================== 9 passed in 0.10 seconds ===========================
Process finished with exit code 0
由此可见,parametrize支持元组,列表,字典嵌套的列表传递多个测试数据,字典嵌套的列表传递测试数据时可以使用一个参数来接收,用字典索引的方式传入对应数据,同上述以一个参数接受测试数据的方法
传入单个测试数据时,ddt和parameterize无差别;
但是传入多个测试数据,用到嵌套元组的列表(以嵌套元组的列表为例)时,
ddt传入数据,需要在装饰器@data(*列表)对列表做一个解包操作,然后再用一个参数去接收解包后的元组,最后使用索引方式一一接受数据,类似于parameterize用一个参数接受多个数据的处理方式;
使用parameterize则不需要解包,直接用一个参数接收即可,或使用位置参数接受,更为灵活。