1.unittest单元测试框架使用DDT进行数据驱动测试,那么Pytest框架有没有数据驱动呢?

2.Pytest是使用@pytest.mark.parametrize装饰器来实现数据驱动测试的。

3.装饰测试类

import pytestdata_1 = [(1, 2, 3),(4, 5, 9)
]def add(a, b):return a + b@pytest.mark.parametrize('a, b, expect', data_1)
class TestParametrize(object):def test_parametrize_1(self, a, b, expect):print('\n测试函数1测试数据为\n{}-{}'.format(a, b))assert add(a, b) == expectdef test_parametrize_2(self, a, b, expect):print('\n测试函数2数据为\n{}-{}'.format(a, b))assert add(a, b) == expectif __name__ == '__main__':pytest.main(['-sv'])

3.1.输出:当装饰器装饰测试类时,给数据集合会被传递给给类的所有方法。

collecting ... collected 4 itemstest_parametrize.py::TestParametrize::test_parametrize_1[1-2-3]
测试函数1测试数据为
1-2
PASSED
test_parametrize.py::TestParametrize::test_parametrize_1[4-5-9]
测试函数1测试数据为
4-5
PASSED
test_parametrize.py::TestParametrize::test_parametrize_2[1-2-3]
测试函数2数据为
1-2
PASSED
test_parametrize.py::TestParametrize::test_parametrize_2[4-5-9]
测试函数2数据为
4-5
PASSED========================== 4 passed in 0.21 seconds ===========================
Process finished with exit code 0

4.装饰测试函数

4.1.单个数据

import pytestdata = [1, 2]@pytest.mark.parametrize('a', data)
def test_parametrize(a):print('\n被加载测试数据为\n{}'.format(a))if __name__ == '__main__':pytest.main(['-s'])

4.2.输出:当测试用例只需要一个参数时,存放数据的列表无序嵌套序列@pytest.mark.parametrize(‘a’, data)装饰器的第一个参数也只需要一个变量接收列表中的每个元素,第二个参数传递存储数据的列表,那么测试用例需要使用同名的字符串接收测试数据(实例中的a)且列表有多少个元素就会生成并执行多少个测试用例。

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collected 2 itemstest_parametrize.py
被加载测试数据为
1
.
被加载测试数据为
2
.
========================== 2 passed in 0.16 seconds ===========================Process finished with exit code 0

4.3.一组数据

import pytestdata = [[1, 2, 3],[4, 5, 9]
]  # 列表嵌套列表
# data_tuple = [
#     (1, 2, 3),
#     (4, 5, 9)
# ]  # 列表嵌套元组@pytest.mark.parametrize('a, b, expect', data)
def test_parametrize_1(a, b, expect):  # 一个参数接收一个数据print('\n测试数据为\n{},{},{}'.format(a, b, expect))actual = a + bassert actual == expect@pytest.mark.parametrize('value', data)
def test_parametrize_2(value):  # 一个参数接收一组数据print('\n测试数据为\n{}'.format(value))actual = value[0] + value[1]assert actual == value[2]if __name__ == '__main__':pytest.main(['-s'])

4.4.输出

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collected 4 itemstest_parametrize.py
测试数据为
1,2,3
.
测试数据为
4,5,9
.
测试数据为
[1, 2, 3]
.
测试数据为
[4, 5, 9]
.
========================== 4 passed in 0.17 seconds ===========================
Process finished with exit code 0

5.说明

5.2.当测试用例需要多个数据时,可以使用嵌套序列(嵌套元组&嵌套列表)的列表来存放测试数据。

5.3.装饰器@pytest.mark.parametrize()可以使用单个变量接收数据,也可以使用多个变量接收,同样,测试用例函数也需要与其保持一致。

5.4.当使用单个变量接收时,测试数据传递到测试函数内部时为列表中的每一个元素或者小列表,需要使用索引的方式取得每个数据。

5.5.当使用多个变量接收数据时,那么每个变量分别接收小列表或元组中的每个元素。

5.6.列表嵌套多少多组小列表或元组,生成多少条测试用例。

5.7.图解对应关系

6.组合数据

import pytestdata_1 = [1, 2]
data_2 = [3, 4]  @pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(a, b):print('\n测试数据为\n{},{}'.format(a, b))if __name__ == '__main__':pytest.main(['-s'])

6.1.输出:一个测试函数还可以同时被多个参数化装饰器装饰,那么多个装饰器中的数据会进行交叉组合的方式传递给测试函数,进而生成n*n个测试用例。

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collected 4 itemstest_parametrize.py
测试数据为
1,3
.
测试数据为
2,3
.
测试数据为
1,4
.
测试数据为
2,4
.========================== 4 passed in 0.24 seconds ===========================Process finished with exit code 0

7.标记用例

7.1.直接标记测试用例,参数化装饰器也可以识别(标记用例失败或跳过)。

7.2.标记为无条件跳过(标记为失败为xfail,自己尝试)。

import pytestdata_1 = [[1, 2, 3],pytest.param(3, 4, 8, marks=pytest.mark.skip)
]def add(a, b):return a + b@pytest.mark.parametrize('a, b, expect', data_1)
def test_parametrize_1(a, b, expect):print('\n测试数据为\n{},{}'.format(a, b))assert add(a, b) == expectif __name__ == '__main__':pytest.main(['-vs'])

7.3.输出:输出结果显示收集到2个用例,一个通过,一个被跳过,当不想执行某组测试数据时,可以标记skip或skipif;当预期某组数据会执行失败时,可以标记为xfail等。

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0 -- C:\Programs\Python\Python37-32\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.2', 'Platform': 'Windows-7-6.1.7601-SP1', 'Packages': {'pytest': '4.3.1', 'py': '1.8.0', 'pluggy': '0.9.0'}, 'Plugins': {'rerunfailures': '7.0', 'metadata': '1.8.0', 'html': '1.20.0'}, 'JAVA_HOME': 'D:\\JDK'}
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collecting ... collected 2 itemstest_parametrize.py::test_parametrize_1[1-2-3]
测试数据为
1,2
PASSED
test_parametrize.py::test_parametrize_1[3-4-8] SKIPPED===================== 1 passed, 1 skipped in 0.17 seconds =====================Process finished with exit code 0

8.嵌套字典

import pytestdata_1 = ({'user': 1,'pwd': 2},{'user': 3,'pwd': 4}
)@pytest.mark.parametrize('dic', data_1)
def test_parametrize_1(dic):print('\n测试数据为\n{}'.format(dic))if __name__ == '__main__':pytest.main(['-s'])

8.1.输出

============================= test session starts =============================
platform win32 -- Python 3.7.2, pytest-4.3.1, py-1.8.0, pluggy-0.9.0
rootdir: E:\CnblogCode\pytest_parametrize, inifile:
plugins: rerunfailures-7.0, metadata-1.8.0, html-1.20.0
collected 2 itemstest_parametrize.py
测试数据为
{'user': 1, 'pwd': 2}
.
测试数据为
{'user': 3, 'pwd': 4}
.========================== 2 passed in 0.20 seconds ===========================Process finished with exit code 0

9.增加可读性:使用ids参数。

9.1.参数化装饰器有参数ids,可以标识每一个测试用例,自定义测试数据结果的显示,为了增加可读性,可以标记每一个测试用例使用的测试数据是什么,适当的增加一些说明。

9.2.在使用前你需要知道,ids参数应该是一个字符串列表,必须和数据对象列表的长度保持一致,我们可以试着使用ids。

import pytestdata_1 = [(1, 2, 3),(4, 5, 9)
]ids = ["a:{} + b:{} = expect:{}".format(a, b, expect) for a, b, expect in data_1]def add(a, b):return a + b@pytest.mark.parametrize('a, b, expect', data_1, ids=ids)
class TestParametrize(object):def test_parametrize_1(self, a, b, expect):print('\n测试函数1测试数据为\n{}-{}'.format(a, b))assert add(a, b) == expectdef test_parametrize_2(self, a, b, expect):print('\n测试函数2数据为\n{}-{}'.format(a, b))assert add(a, b) == expectif __name__ == '__main__':pytest.main(['-v'])  # -v : 更加详细的输出测试结果

9.3.装饰器不传递ids参数的输出:执行命令使用了-v。

collecting ... collected 4 itemstest_parametrize.py::TestParametrize::test_parametrize_1[1-2-3] PASSED   [ 25%]
test_parametrize.py::TestParametrize::test_parametrize_1[4-5-9] PASSED   [ 50%]
test_parametrize.py::TestParametrize::test_parametrize_2[1-2-3] PASSED   [ 75%]
test_parametrize.py::TestParametrize::test_parametrize_2[4-5-9] PASSED   [100%]========================== 4 passed in 0.16 seconds ===========================Process finished with exit code 0

9.4.装饰器传递ids参数的输出:执行命令使用了-v,会更加详细的显示输出结果,可以看到所有的数据结果中的用例都被一个列表明确的标记了,而且通过这种标记可以更加直观的看出来,每个测试用例使用的数据名称及测试内容。

collecting ... collected 4 itemstest_parametrize.py::TestParametrize::test_parametrize_1[a:1 + b:2 = expect:3] PASSED [ 25%]
test_parametrize.py::TestParametrize::test_parametrize_1[a:4 + b:5 = expect:9] PASSED [ 50%]
test_parametrize.py::TestParametrize::test_parametrize_2[a:1 + b:2 = expect:3] PASSED [ 75%]
test_parametrize.py::TestParametrize::test_parametrize_2[a:4 + b:5 = expect:9] PASSED [100%]========================== 4 passed in 0.20 seconds ===========================
Process finished with exit code 0

10.自定义id做标识

10.1.除了使用ids参数增加输出可读性外,还可以在参数列表的参数旁边定义一个id值来做标识。

import pytestdata_1 = [pytest.param(1, 2, 3, id="(a+b):pass"),  # id的值可以自定义, 只要方便理解每个用例是干什么的即可pytest.param(4, 5, 10, id="(a+b):fail")
]def add(a, b):return a + bclass TestParametrize(object):@pytest.mark.parametrize('a, b, expect', data_1)def test_parametrize_1(self, a, b, expect):assert add(a, b) == expectif __name__ == '__main__':pytest.main(['-v'])

10.2.输出:如果使用此方法来标记测试用例,一定要严格按照写的格式来使用,语法为pytest.param(value, id=‘somthing’)

test_parametrize.py::TestParametrize::test_parametrize_1[(a+b):pass] PASSED [ 50%]
test_parametrize.py::TestParametrize::test_parametrize_1[(a+b):fail] FAILED [100%]================================== FAILURES ===================================
_______________ TestParametrize.test_parametrize_1[(a+b):fail] ________________self = <pytest_parametrize.test_parametrize.TestParametrize object at 0x000001D7BFC4C748>
a = 4, b = 5, expect = 10@pytest.mark.parametrize('a, b, expect', data_1)def test_parametrize_1(self, a, b, expect):
>       assert add(a, b) == expect
E       assert 9 == 10
E         -9
E         +10test_parametrize.py:28: AssertionError
===================== 1 failed, 1 passed in 0.35 seconds ======================Process finished with exit code 0

11.总结

11.1.Pytest中实现数据驱动就是使用@pytest.mark.parametrize装饰器来实现数据驱动。

11.2.装饰器与测试用例使用单个变量接收多组数据与多个变量接收多个数据的访问方法。

11.3.不同测试数据形式(列表嵌套元组,列表,字典等)时,如何传递数据及访问数据。

11.4.装饰器装饰测试类和测试函数的不同之处:装饰测试类时,类内所有的方法必须接送测试数据,否则会报错,装饰测试函数时比较灵活,如果函数不使用数据就可以不装饰。

11.5.为了输出结果的可读性,可以选择使用ids参数,与测试数据中定义id参数值来标识测试用例。

12.注意

12.1.装饰器的第一个参数是一个列表形式的字符串参数"a, b, c" 不能写成"a", “b”, “c”

12.2.ids是个字符串列表,它的长度需要与测试数据列表的长度一致。

第十三:Pytest参数化-@pytest.mark.parametrize装饰器来实现数据驱动测试相关推荐

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

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

  2. 软件测试 pytest pytest的命名规则 用例的前后置 conftest.py 定制allure报告 @pytest.mark.parametrize()装饰器作数据驱动

    文章目录 1 pytest简介 1.1 pytest的命名规则 1.2 运行方式 1.2.1 主函数方式(少用) 1.2.2 命令行方式(少用) 1.2.3 pytest.ini的配置文件方式(最经常 ...

  3. 『德不孤』Pytest框架 — 14、Pytest参数化

    文章目录 1.Pytest参数化说明 2.Pytest参数化方式 3.parametrize装饰器参数说明 4.Pytest参数化(单个参数) 5.Pytest参数化(多个参数) 6.ids参数说明 ...

  4. Pytest参数化-详解

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

  5. 【pytest】(详解)@pytest.mark.parametrize: 参数化测试函数

    目录 1.快速入门 1.1介绍 1.2代码示例 1.3运行结果 1.4结果分析 2.装饰测试类 2.1介绍 2.2示例代码 2.3.运行结果 2.4结果分析 3.全局变量方式进行参数化 3.1介绍 3 ...

  6. pytest学习和使用12-Unittest和Pytest参数化详解

    12-Unittest和Pytest参数化详解 1 Unittest参数化 1.1 ddt 1.1.1 简介 1.1.2 说明 1.1.3 安装 1.1.4 版本信息 1.1.5 实例1 1.1.6 ...

  7. pytest——04 pytest.mark.xxx

    目录 使用 @pytest.mark.xxx 标记测试用例 注册.管理 mark 标记 注册 mark 标记: 规范使用 mark 标记 使用Marks标记测试用例 @pytest.mark.skip ...

  8. 【Pytest+Allure】pytest+allure自学轨迹1--认识pytest和pytest的装饰器

    认识pytest和pytest的装饰器 认识pytest pytest的装饰器 使用pytest 安装与导入 pytest用例的写法 使用fixture装饰器 作用域 不指定作用域(默认作用域func ...

  9. 51 Python - 装饰器 参数化装饰器——装饰器更通用

    05参数化装饰器--装饰器更通用 参数化装饰器如何理解,简单理解就是让装饰器可以通用.场景举例,现在有个需求要改某一段文字,既要加<P>标签,又要加<B>,还有加<Div ...

最新文章

  1. Codeforces round 1083
  2. 使用Golang flag包解析字符串
  3. 【看这里】网易云信 IM 红包上线啦!最快3小时集成红包功能
  4. 30 个极简Python代码,拿走即用(真干货)
  5. 瑞德西韦有效吗?专家一句大实话解释清楚了
  6. C#中一些常用的方法使用
  7. 小程序助手多功能微信小程序反编译工具
  8. YOLOv2检测过程的Tensorflow实现
  9. mac git 命令自动补全
  10. 51nod-1131: 覆盖数字的数量
  11. linux下交叉编译ffmpeg,并加入H264编码支持
  12. VS安装VAssistX插件导致WPF-XAML文件输入中文出现乱码问题解决方案
  13. 基于java springboot活动报名微信小程序源码(毕设)
  14. iOS | Swift图片剪切圆角
  15. 文件系统管理 之 reiserfs文件系统反删除(Undelete)操作的实践
  16. CF1282 B 背包
  17. sql可以查询数据但是提示对象名无效
  18. c语言中函数值类型的定义,C语言允许函数值类型缺省定义,此时该函数值隐含的类型是( )。(A)float (B)int (C)long (D)double...
  19. 外国小伙发现乌云是黑色的……
  20. Python+opencv 人脸识别

热门文章

  1. 在.net2.0下使用System.Web.Script.Serialization;
  2. 布同:pdf自定义分割(断章)
  3. 如何才干创建一个空的IBM DB2 ECO数据库
  4. 简单实现系统托盘 - 回复 闪 的问题
  5. JQuery Dialog(JS模态窗口,可拖拽的DIV)
  6. hibernate one2one 唯一外键关联(双向关联)
  7. 解决编译错误: 非法字符: '\ufeff' 解决方案|错误: 需要class, interface或enum
  8. iOS成长之button
  9. 【报告分享】2020中国企业数字化转型研究报告-清华大学.pdf(附下载链接)
  10. 【报告分享】2020新零售直播活力报告.pdf(附下载链接)