pytest之参数化parametrize的使用

参考:

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
.

 

上一篇:GC的基础知识


下一篇:值得纪念的日子,mark一下