Novice学Pytest(9)-参数化

一、前言

  写用例脚本时,只有测试数据和期望结果不一样,但操作步骤是一样的测试用例,可以用参数化。pytest允许在多个级别启用测试参数化

  • pytest.fixture() 允许fixture有参数化功能
  • @pytest.mark.parameterize 允许在测试函数或类中定义多组参数和fixtures
  • pytest_generate_tests 允许定义自定义参数化方案或扩展

二、未参数化的示例代码

1 def test_one():
2     assert 3 + 5 == 8
3 
4 def test_two():
5     assert 2 + 4 == 6
6 
7 def test_three():
8     assert 3 * 

 以上三个用例都是加法计算,然后断言和,重复写3个类似的用例有点冗余

三、参数化的示例代码

1 @pytest.mark.parametrize("test_input,expected",[("3+5",8),("2+4",6),("3*4",11)])
2 def test_eval(test_input,expected):
3     print(f"测试数据{test_input},期望结果{expected}")
4     assert eval(test_input) == expected

  执行结果:

  we can see:只有一条用例,但是利用参数化输入三组不同的测试数据和期望结果,执行用例数也是3个,节省很多代码

五、工作思考

  1、写登录模块的用例脚本时,根据等价类划分,我们一般会测试账号和密码正确、账号不存在、密码错误、账号为空、密码为空和账号密码都为空

  2、这些用例的区别在于输入的测试数据和对应的交互结果

  3、我们可以只写一条登录测试用例,然后把多组测试数据和期望结果参数化,节省代码量

六、源码分析

def parametrize(self,argnames, argvalues, indirect=False, ids=None, scope=None):

argnames
源码解析:a comma-separated string denoting one or more argument names, or a list/tuple of argument strings.

含义:参数名字

格式:字符串"arg1,arg2,arg3"【需要用逗号分隔】

备注:源码中写了可以是参数字符串的list或者tuple,但博主实操过是不行的,不知道是不是写的有问题,大家可以看看评论下

示例

@pytest.mark.parametrize(["name", "pwd"], [("yy1", "123"), ("yy2", "123")])
@pytest.mark.parametrize(("name", "pwd"), [("yy1", "123"), ("yy2", "123")])
@pytest.mark.parametrize("name,pwd", [("yy1", "123"), ("yy2", "123")])
备注

有朋友提出现在上面标注错的两个可以正常使用了

 

argvalues
源码解析:

The list of argvalues determines how often a test is invoked with different argument values.
If only one argname was specified argvalues is a list of values.【只有一个参数,则是值列表】
If N argnames were specified, argvalues must be a list of N-tuples, where each tuple-element specifies a value for its respective argname.【如果有多个参数,则用元组来存每一组值】
含义:参数值列表

格式:必须是列表,如:[ val1,val2,val3 ]

如果只有一个参数,里面则是值的列表如:@pytest.mark.parametrize("username", ["yy", "yy2", "yy3"])

如果有多个参数例,则需要用元组来存放值,一个元组对应一组参数的值,如:@pytest.mark.parametrize("name,pwd", [("yy1", "123"), ("yy2", "123"), ("yy3", "123")])

备注:虽然源码说需要list包含tuple,但我试了下,tuple包含list,list包含list也是可以的........

 

ids
含义:用例的ID

格式:传一个字符串列表

作用:可以标识每一个测试用例,自定义测试数据结果的显示,为了增加可读性

强调:ids的长度需要与测试数据列表的长度一致

 

indirect
作用:如果设置成True,则把传进来的参数当函数执行,而不是一个参数

七、装饰测试类

 1 import pytest
 2 data_1 = [(1,2,3),(4,5,9)]
 3 @pytest.mark.parametrize('a,b,expected',data_1)
 4 class TestParametrize:
 5     def test_parametrize(self,a,b,expected):
 6         print("\n测试函数11111 测试数据为\n{}{}.format(a,b")
 7         assert a + b == expected
 8 
 9     def test_parametrize_two(self,a,b,expected):
10         print("\n测试函数22222 测试数据为\n{}-{}".format(a,b))
11         assert a + b == expected

  执行结果: 

  Notes:当装饰器@pytest.mark.parametrize装饰测试类时,会将数据集合(比如上面的data_1)传递给类的所有测试用例方法

八、多个参数化装饰器--举例笛卡尔积

1 import pytest
2 
3 # 类似于笛卡尔积,有序组合
4 data_one = [1,2,3]
5 data_two = ["a","b"]
6 @pytest.mark.parametrize("a",data_one)
7 @pytest.mark.parametrize("b",data_two)
8 def test_parametrize_one(a,b):
9     print(f"\n笛卡尔积 测试数据为:{a},{b}")

  执行结果:

  Notes:

  • 一个函数或一个类可以装饰多个 @pytest.mark.parametrize
  • 这种方式,最终生成的用例数是n*m,比如上面的代码就是:参数a的数据有3个,参数b的数据有2个,所以最终的用例数有3*2=6条

九、参数化,传入字典数据

 1 import pytest
 2 # 字典
 3 data_one = (
 4     {
 5         "user":1,
 6         "pwd":2
 7     },
 8     {
 9         "user":3,
10         "pwd":4
11     }
12 )
13 
14 @pytest.mark.parametrize("dic",data_one)
15 def test_parametrize_one(dic):
16     print(f"测试数据为\n{dic}")
17     print(f'user:{dic["user"]},pwd:{dic["pwd"]}')

  执行结果:

十、参数化,标记数据

 1 import pytest
 2 
 3 # 标记参数化
 4 @pytest.mark.parametrize("test_input,expected",[("3+5",8),
 5                                                 ("2+4",6),
 6                                                 pytest.param("3*4",11,marks=pytest.mark.xfail),
 7                                                 pytest.param("3*5",16,marks=pytest.mark.skip)
 8                                                 ])
 9 def test_mark(test_input,expected):
10     assert eval(test_input) == expected

  执行结果:

十一、参数化,增加可读性

 1 import pytest
 2 
 3 # 增加可读性
 4 data_one = [(3,5,8),(2,4,6)]
 5 
 6 # ids
 7 ids = ["a:{} + b:{} = expected:{}".format(a,b,expected) for a,b,expected in data_one]
 8 @pytest.mark.parametrize("a,b,expected",data_one,ids=ids)
 9 class Testparametrize:
10     def test_parametrize(self,a,b,expected):
11         print("\n测试函数1 测试数据为\n{}-{}".format(a,b))
12         assert a + b == expected

  执行结果:

  Notes:多少组数据,就要有多少个id,然后组成一个id的列表,作用主要是为了更加清晰看到用例的含义。

 

参考链接:https://www.cnblogs.com/poloyy/p/12675457.html

 

posted @ 2022-04-22 22:45  方缘  阅读(50)  评论(0编辑  收藏  举报