参考:
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 .