如果你还想从头学起Pytest,可以看看这个系列的文章哦!

https://www.cnblogs.com/poloyy/category/1690628.html

前言

pytest允许在多个级别启用测试参数化:

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

参数化场景

只有测试数据和期望结果不一样,但操作步骤是一样的测试用例可以用上参数化;

可以看看下面的栗子

未参数化的代码

def test_1():
assert 3 + 5 == 9 def test_2():
assert 2 + 4 == 6 def test_3():
assert 6 * 9 == 42

可以看到,三个用例都是加法然后断言某个值,重复写三个类似的用例有点冗余

利用参数化优化之后的代码

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

执行结果

可以看到,只有一条用例,但是利用参数化输入三组不同的测试数据和期望结果,最终执行的测试用例数=3,可以节省很多代码

实际Web UI自动化中的开发场景,比如是一个登录框

  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", ""), ("yy2", "")])  # 错的
@pytest.mark.parametrize(("name", "pwd"), [("yy1", ""), ("yy2", "")]) # 错的
@pytest.mark.parametrize("name,pwd", [("yy1", ""), ("yy2", "")])

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,则把传进来的参数当函数执行,而不是一个参数(下一篇博文即讲解)

讲完源码,对方法有更深入的了解了,我们就讲讲常用的场景

装饰测试类

@pytest.mark.parametrize('a, b, expect', data_1)
class TestParametrize: def test_parametrize_1(self, a, b, expect):
print('\n测试函数11111 测试数据为\n{}-{}'.format(a, b))
assert a + b == expect def test_parametrize_2(self, a, b, expect):
print('\n测试函数22222 测试数据为\n{}-{}'.format(a, b))
assert a + b == expect

执行结果

重点

当装饰器 @pytest.mark.parametrize 装饰测试类时,会将数据集合传递给类的所有测试用例方法

“笛卡尔积”,多个参数化装饰器

# 笛卡尔积,组合数据
data_1 = [1, 2, 3]
data_2 = ['a', 'b'] @pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(a, b):
print(f'笛卡尔积 测试数据为 : {a},{b}')

执行结果

重点知识

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

参数化 ,传入字典数据

# 字典
data_1 = (
{
'user': 1,
'pwd': 2
},
{
'user': 3,
'pwd': 4
}
) @pytest.mark.parametrize('dic', data_1)
def test_parametrize_1(dic):
print(f'测试数据为\n{dic}')
print(f'user:{dic["user"]},pwd{dic["pwd"]}')

没啥特别的,只是数据类型是常见的dict而已

执行结果

09parametrize.py::test_parametrize_1[dic0] PASSED                        [ 50%]测试数据为
{'user': 1, 'pwd': 2}
user:1,pwd2 09parametrize.py::test_parametrize_1[dic1] PASSED [100%]测试数据为
{'user': 3, 'pwd': 4}
user:3,pwd4

参数化,标记数据

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

执行结果

参数化,增加可读性

# 增加可读性
data_1 = [
(1, 2, 3),
(4, 5, 9)
] # ids
ids = ["a:{} + b:{} = expect:{}".format(a, b, expect) for a, b, expect in data_1] @pytest.mark.parametrize('a, b, expect', data_1, ids=ids)
class TestParametrize(object): def test_parametrize_1(self, a, b, expect):
print('测试函数1测试数据为{}-{}'.format(a, b))
assert a + b == expect def test_parametrize_2(self, a, b, expect):
print('测试函数2数据为{}-{}'.format(a, b))
assert a + b == expect

执行结果

知识点

多少组数据,就要有多少个id,然后组成一个id的列表

作用:主要是为了更加清晰看到用例的含义

Pytest系列(9) - 参数化@pytest.mark.parametrize的更多相关文章

  1. Pytest 系列(28)- 参数化 parametrize + @allure.title() 动态生成标题

    如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 参数化 @pytest.ma ...

  2. pytest自动化6:pytest.mark.parametrize装饰器--测试用例参数化

    前言:pytest.mark.parametrize装饰器可以实现测试用例参数化. parametrizing 1.  下面是一个简单是实例,检查一定的输入和期望输出测试功能的典型例子 2.  标记单 ...

  3. pytest.mark.parametrize()参数化应用二,读取json文件

    class TestEnorll(): def get_data(self): """ 读取json文件 :return: """ data ...

  4. pytest.mark.parametrize()参数化的应用一

    from page.LoginPage import Loginpage import os, sys, pytest base_dir = os.path.dirname(os.path.dirna ...

  5. pytest系列(二):筛选用例新姿势,mark 一下,你就知道。

    pytest系列(一)中给大家介绍了pytest的特性,以及它的编写用例的简单至极. 那么在实际工作当中呢,我们要写的自动化用例会比较多,不会都放在一个py文件里. 如下图所示,我们编写的用例存放在不 ...

  6. 5.@pytest.mark.parametrize()数据驱动

    简介: pytest.mark.parametrize 是 pytest 的内置装饰器,它允许你在 function 或者 class 上定义多组参数和 fixture 来实现数据驱动. @pytes ...

  7. pytest文档9-参数化parametrize

    前言 pytest.mark.parametrize装饰器可以实现测试用例参数化. parametrizing 1.这里是一个实现检查一定的输入和期望输出测试功能的典型例子 # content of ...

  8. Pytest进阶之参数化

    前言 unittest单元测试框架使用DDT进行数据驱动测试,那么身为功能更加强大且更加灵活的Pytest框架怎么可能没有数据驱动的概念呢?其实Pytest是使用@pytest.mark.parame ...

  9. 11、pytest -- 测试的参数化

    目录 1. @pytest.mark.parametrize标记 1.1. empty_parameter_set_mark选项 1.2. 多个标记组合 1.3. 标记测试模块 2. pytest_g ...

随机推荐

  1. 吃透这份pdf,面试阿里、腾讯、百度等一线大厂,顺利拿下心仪offer!

    前言 最近一位年前裸辞的朋友来找我诉苦,说因为疫情原因现在都在家吃老本.本想着年后就来找工作的,但是现在这个情况也不好找,而且很多公司也随着这次疫情面临着资金紧缺导致裁员严重的甚至倒闭,导致很多人失业 ...

  2. 基于 Roslyn 实现一个简单的条件解析引擎

    基于 Roslyn 实现一个简单的条件解析引擎 Intro 最近在做一个勋章的服务,我们想定义一些勋章的获取条件,满足条件之后就给用户颁发一个勋章,定义条件的时候会定义需要哪些参数,参数的类型,获取勋 ...

  3. 关于BitmapImage EndInit()时报值不在范围内的异常

    值不在预期的范围内.ArgumentException 在 System.Windows.Media.ColorContext.GetColorContextsHelper(GetColorConte ...

  4. 【TIJ4】第五章全部习题

    第五章习题 5.1 package ex0501; //[5.1]创建一个类,它包含一个未初始化的String引用.验证该引用被Java初始化成null class TestDefaultNull { ...

  5. VsCode代码段添加方法

    VsCode代码段添加方法 我们在编写代码的过程中,常常会遇到一些固定的结构或常用的处理方法. 编写耗费时间尽力,这时我们想到了添加代码段功能,帮助我们快速的完成编写. 下面以VsCode为例子: 我 ...

  6. [C++]请麻烦压一下定理的棺材板啦

    从去年还在竞赛的时候2/12的原博客里搬运来的 不得不说之前取名真的很艺术qwq 今天开始上的数论课,让头发以肉眼可见的速度掉落emmm 没关系我头发多我不怕啦啦啦QwQ 其中最令人头疼的就是那些人名 ...

  7. M-Renamer方法名修改器,iOS项目方法名重构,Objective-C/Swift,代码模型预判,减少误改的机率,替换速度更快,可视化操作,傻瓜式操作,一键操作,引用处自动修改,马甲包的福音

    M-Renamer M-Renamer(Method-Name-Renamer)类方法名修改器,采用链式解析头文件,代码模型预判,减少误改的机率,替换速度更快:可以解析整个项目大多数类的方法,可视化操 ...

  8. MySQL:REPLACE函数的使用

    原文链接 REPLACE函数功能 REPLACE(columnName, search_str, replace_str) 查找columnName字段中所有search_str,并替换为replac ...

  9. springboot集成axis1.4

    1.首先通过axis工具根据wsdl文件生成java代码和wsdd文件 set Axis_Lib=/Users/apple/configuration/axis-1_4/lib //lib文件目录se ...

  10. Postman从入门到入门

    1.Postman简介 Postman是一个接口测试工具,在做接口测试的时候, Postman相当于一个客户端,可以发送请求到服务器端.Postman分为Chrome插件版本(不再更新维护)和Nati ...