pytest之parameterize参数化

在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支持元组,列表,字典嵌套的列表传递多个测试数据,字典嵌套的列表传递测试数据时可以使用一个参数来接收,用字典索引的方式传入对应数据,同上述以一个参数接受测试数据的方法

四.parameterize和DDT之间的区别

传入单个测试数据时,ddt和parameterize无差别;
但是传入多个测试数据,用到嵌套元组的列表(以嵌套元组的列表为例)时,
ddt传入数据,需要在装饰器@data(*列表)对列表做一个解包操作,然后再用一个参数去接收解包后的元组,最后使用索引方式一一接受数据,类似于parameterize用一个参数接受多个数据的处理方式;
使用parameterize则不需要解包,直接用一个参数接收即可,或使用位置参数接受,更为灵活。

你可能感兴趣的:(python之selenium)