pytest测试框架使用基础06 fixture——parametrize

@pytest.mark.parametrize 允许在测试函数或类中定义多组参数和 fixtures。
参数化场景:
只有测试数据和预期结果不一样,但操作步骤是一样的测试用例是可以用上参数化的。
创建test_cases02.py文件
示例一:未参数化
1.脚本代码:

# 未作参数化示例
import pytestdef test_case01():assert 3 + 4 == 9def test_case02():assert 6 + 1 == 7def test_case03():assert 3 * 4 == 15if __name__ == '__main__':pytest.main(['-s', '-v', '-k' 'test_cases02'])

可以看到,三个用例都是先计算,然后断言某个值,重复写三个类似的用例有些冗余。
2.运行结果:

============================= test session starts =============================
collecting ... collected 3 itemstest_cases02.py::test_case01 FAILED                                      [ 33%]
test_cases02.py:4 (test_case01)
7 != 9Expected :9
Actual   :7
<Click to see difference>def test_case01():
>       assert 3 + 4 == 9
E       assert (3 + 4) == 9test_cases02.py:6: AssertionErrortest_cases02.py::test_case02 PASSED                                      [ 66%]
test_cases02.py::test_case03 FAILED                                      [100%]
test_cases02.py:12 (test_case03)
12 != 15Expected :15
Actual   :12
<Click to see difference>def test_case03():
>       assert 3 * 4 == 15
E       assert (3 * 4) == 15test_cases02.py:14: AssertionError========================= 2 failed, 1 passed in 0.14s =========================Process finished with exit code 1

示例二:参数化(优化代码)
脚本代码:

# 参数化(优化代码)
import pytest@pytest.mark.parametrize("test_input, expected", [("3+4", 6), ("2+5", 7), ("6*9", 48)])
def test_case01(test_input, expected):print(f"测试数据{test_input},预期结果{expected}")assert eval(test_input) == expected

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

============================= test session starts =============================
collecting ... collected 3 itemstest_cases02.py::test_case01[3+4-6] 
test_cases02.py::test_case01[2+5-7] 
test_cases02.py::test_case01[6*9-48] ========================= 2 failed, 1 passed in 0.12s =========================
FAILED                               [ 33%]测试数据3+4,预期结果6test_cases02.py:4 (test_case01[3+4-6])
7 != 6Expected :6
Actual   :7
<Click to see difference>test_input = '3+4', expected = 6@pytest.mark.parametrize("test_input, expected", [("3+4", 6), ("2+5", 7), ("6*9", 48)])def test_case01(test_input, expected):print(f"测试数据{test_input},预期结果{expected}")
>       assert eval(test_input) == expected
E       AssertionError: assert 7 == 6
E        +  where 7 = eval('3+4')test_cases02.py:8: AssertionError
PASSED                               [ 66%]测试数据2+5,预期结果7
FAILED                              [100%]测试数据6*9,预期结果48test_cases02.py:4 (test_case01[6*9-48])
54 != 48Expected :48
Actual   :54
<Click to see difference>test_input = '6*9', expected = 48@pytest.mark.parametrize("test_input, expected", [("3+4", 6), ("2+5", 7), ("6*9", 48)])def test_case01(test_input, expected):print(f"测试数据{test_input},预期结果{expected}")
>       assert eval(test_input) == expected
E       AssertionError: assert 54 == 48
E        +  where 54 = eval('6*9')test_cases02.py:8: AssertionErrorProcess finished with exit code 1

1、参数

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

主要参数:
1)argnames:参数名,是个字符串,如中间用逗号分隔则表示为多个参数名。
创建test_cases03.py文件
参数名也可以是list或者tuple里的字符串。
脚本代码:

import pytest@pytest.mark.parametrize(["name", "pwd"], [("AllTests", "123456"), ("qq", "85135506")])
def test_case1(name, pwd):print(name, pwd)@pytest.mark.parametrize(("name", "pwd"), [("wangmcn", "567890"), ("admin", "123qwe")])
def test_case3(name, pwd):print(name, pwd)@pytest.mark.parametrize("name, pwd", [("root", "root"), ("guest", "guest")])
def test_case3(name, pwd):print(name, pwd)

运行结果:

============================= test session starts =============================
collecting ... collected 4 itemstest_cases03.py::test_case1[AllTests-123456] PASSED                      [ 25%]AllTests 123456test_cases03.py::test_case1[qq-85135506] PASSED                          [ 50%]qq 85135506test_cases03.py::test_case3[root-root] PASSED                            [ 75%]root roottest_cases03.py::test_case3[guest-guest] PASSED                          [100%]guest guest============================== 4 passed in 0.05s ==============================Process finished with exit code 0

2)argvalues:参数值,参数组成的列表,列表中有几个元素,就会生成几条用例。
创建 test_cases04.py 文件
脚本代码:

import pytest# 如果只有一个参数,里面则是值的列表
@pytest.mark.parametrize("name", ["AllTests", "wangmcn", "admin"])
def test_case01(name):print(name)# 如果有多个参数,list包含tuple
@pytest.mark.parametrize(["name", "pwd"], [("AllTests", "123456"), ("qq", "45646144")])
def test_case02(name, pwd):print(name, pwd)# 如果有多个参数,tuple包含list
@pytest.mark.parametrize(("name", "pwd"), (["AllTests", "123456"], ["qq", "45646144"]))
def test_case03(name, pwd):print(name, pwd)# 如果有多个参数,list包含list
@pytest.mark.parametrize(["name", "pwd"], [["AllTests", "123456"], ["qq", "45646144"]])
def test_case03(name, pwd):print(name, pwd)

运行结果:

============================= test session starts =============================
collecting ... collected 7 items
test_cases04.py::test_case01[AllTests] PASSED                            [ 14%]AllTests
test_cases04.py::test_case01[wangmcn] PASSED                             [ 28%]wangmcn
test_cases04.py::test_case01[admin] PASSED                               [ 42%]admin
test_cases04.py::test_case02[AllTests-123456] PASSED                     [ 57%]AllTests 123456
test_cases04.py::test_case02[qq-45646144] PASSED                         [ 71%]qq 45646144
test_cases04.py::test_case03[AllTests-123456] PASSED                     [ 85%]AllTests 123456
test_cases04.py::test_case03[qq-45646144] PASSED                         [100%]qq 45646144
============================== 7 passed in 0.05s ==============================
Process finished with exit code 0

3)ids:用例的ID。传一个字符串列表,可以标识每一个测试用例,自定义测试数据结果的显示,为了增加可读性。
注:ids的长度需要与测试数据列表的长度一致。
创建test_cases05.py文件
脚本代码:

import pytestmy_data = [(1, 2, 3), (4, 5, 9)]ids = ["a:{} + b:{} = expect:{}".format(a, b, expect) for a, b, expect in my_data]@pytest.mark.parametrize("a, b, expect", my_data, ids=ids)
def test_parametrize_case(a, b, expect):print("测试数据为{}-{}".format(a, b))assert a + b == expect

运行结果:

============================= test session starts =============================
collecting ... collected 2 itemstest_cases05.py::test_parametrize_case[a:1 + b:2 = expect:3] PASSED      [ 50%]测试数据为1-2test_cases05.py::test_parametrize_case[a:4 + b:5 = expect:9] PASSED      [100%]测试数据为4-5============================== 2 passed in 0.03s ==============================Process finished with exit code 0

2、装饰测试类

创建test_cases06.py文件
脚本代码:

import pytestmy_data = [(1, 2, 3), (4, 5, 9)]@pytest.mark.parametrize("a, b, expect", my_data)
class TestParametrize:def test_parametrize_case1(self, a, b, expect):print("\n测试用例case1:测试数据为{}+{}".format(a, b))assert a + b == expectdef test_parametrize_case2(self, a, b, expect):print("\n测试用例case1:测试数据为{}+{}".format(a, b))assert a + b == expect

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

============================= test session starts =============================
collecting ... collected 4 itemstest_cases06.py::TestParametrize::test_parametrize_case1[1-2-3] PASSED   [ 25%]
测试用例case1:测试数据为1+2test_cases06.py::TestParametrize::test_parametrize_case1[4-5-9] PASSED   [ 50%]
测试用例case1:测试数据为4+5test_cases06.py::TestParametrize::test_parametrize_case2[1-2-3] PASSED   [ 75%]
测试用例case1:测试数据为1+2test_cases06.py::TestParametrize::test_parametrize_case2[4-5-9] PASSED   [100%]
测试用例case1:测试数据为4+5============================== 4 passed in 0.05s ==============================Process finished with exit code 0

3、多个参数化装饰器

  • 一个函数或一个类可以装饰多个 @pytest.mark.parametrize
  • 当参数化装饰器有很多个的时候,用例数等于n(个)*n(个)*n(个)n(个)
    创建test_cases07.py文件。
    脚本代码:
import pytestmy_data1 = [1, 2, 3]
my_data2 = ["a", "b"]@pytest.mark.parametrize("a", my_data1)
@pytest.mark.parametrize("b", my_data2)
def test_parametrize_case(a, b):print(f"测试数据为{a},{b}")

运行结果:
参数a的数据有3个,参数b的数据有2个,所以最终的用例数有3*2=6条。

============================= test session starts =============================
collecting ... collected 6 itemstest_cases07.py::test_parametrize_case[a-1] PASSED                       [ 16%]测试数据为1,atest_cases07.py::test_parametrize_case[a-2] PASSED                       [ 33%]测试数据为2,atest_cases07.py::test_parametrize_case[a-3] PASSED                       [ 50%]测试数据为3,atest_cases07.py::test_parametrize_case[b-1] PASSED                       [ 66%]测试数据为1,btest_cases07.py::test_parametrize_case[b-2] PASSED                       [ 83%]测试数据为2,btest_cases07.py::test_parametrize_case[b-3] PASSED                       [100%]测试数据为3,b============================== 6 passed in 0.04s ==============================Process finished with exit code 0

4、参数化(传入字典数据)

创建test_cases08.py文件
数据类型为字典
脚本代码:

import pytestmy_data = ({"user": "AllTests","pwd": "123456"},{"user": "TestUser","pwd": "235689"}
)@pytest.mark.parametrize("dic", my_data)
def test_parametrize_case(dic):print(f"测试数据为:\n{dic}")print(f'user:{dic["user"]}, pwd:{dic["pwd"]}')

运行结果:

============================= test session starts =============================
collecting ... collected 2 itemstest_cases08.py::test_parametrize_case[dic0] PASSED                      [ 50%]测试数据为:
{'user': 'AllTests', 'pwd': '123456'}
user:AllTests, pwd:123456test_cases08.py::test_parametrize_case[dic1] PASSED                      [100%]测试数据为:
{'user': 'TestUser', 'pwd': '235689'}
user:TestUser, pwd:235689============================== 2 passed in 0.02s ==============================Process finished with exit code 0

5、标记参数化

pytest.param 可以传三种参数:

  • param values - 参数集值的变量 args,按顺序排列。
  • keyword marks - marks 关键字标记,要应用于此参数集的单个标记或标记列表。
  • keyword str id - 参数集的属性 id。

示例一:
创建test_cases09.py文件。

import pytest@pytest.mark.parametrize("test_input, expected", [("3+5", 8),("2+4", 6),pytest.param("6*9", 45, marks=pytest.mark.xfail),pytest.param("6*6", 50, marks=pytest.mark.skip)
])
def test_case(test_input, expected):assert eval(test_input) == expected

运行结果:

============================= test session starts =============================
collecting ... collected 4 itemstest_cases09.py::test_case[3+5-8] 
test_cases09.py::test_case[2+4-6] 
test_cases09.py::test_case[6*9-45] 
test_cases09.py::test_case[6*6-50] =================== 2 passed, 1 skipped, 1 xfailed in 0.12s ===================
PASSED                                 [ 25%]PASSED                                 [ 50%]XFAIL                                 [ 75%]
test_input = '6*9', expected = 45@pytest.mark.parametrize("test_input, expected", [("3+5", 8),("2+4", 6),pytest.param("6*9", 45, marks=pytest.mark.xfail),pytest.param("6*6", 50, marks=pytest.mark.skip)])def test_case(test_input, expected):
>       assert eval(test_input) == expected
E       AssertionError: assert 54 == 45
E        +  where 54 = eval('6*9')test_cases09.py:11: AssertionError
SKIPPED (unconditional skip)          [100%]
Skipped: unconditional skipProcess finished with exit code 0

示例二:
创建test_cases10.py文件。

import pytest@pytest.mark.parametrize("test_input, expected", [pytest.param("3+5", 8, id="case1"),pytest.param("2+4", 6, id="case2"),pytest.param("6*9", 45, marks=pytest.mark.xfail, id="case3"),pytest.param("6*6", 50, marks=pytest.mark.skip, id="case4")
])
def test_case(test_input, expected):assert eval(test_input) == expected

运行结果:

============================= test session starts =============================
collecting ... collected 4 itemstest_cases10.py::test_case[case1] 
test_cases10.py::test_case[case2] 
test_cases10.py::test_case[case3] 
test_cases10.py::test_case[case4] =================== 2 passed, 1 skipped, 1 xfailed in 0.12s ===================
PASSED                                 [ 25%]PASSED                                 [ 50%]XFAIL                                  [ 75%]
test_input = '6*9', expected = 45@pytest.mark.parametrize("test_input, expected", [pytest.param("3+5", 8, id="case1"),pytest.param("2+4", 6, id="case2"),pytest.param("6*9", 45, marks=pytest.mark.xfail, id="case3"),pytest.param("6*6", 50, marks=pytest.mark.skip, id="case4")])def test_case(test_input, expected):
>       assert eval(test_input) == expected
E       AssertionError: assert 54 == 45
E        +  where 54 = eval('6*9')test_cases10.py:11: AssertionError
SKIPPED (unconditional skip)           [100%]
Skipped: unconditional skipProcess finished with exit code 0

6、解决unicode编码问题

使用 @pytest.mark.parametrize 参数化的时候,加 ids 参数用例描述有中文时,在控制台输出会显示 unicode 编码问题,中文不能正常显示。
解决方法:
使用 pytest_collection_modifyitems 钩子函数,对输出的 item.name 和 item.nodeid 重新编码即可。
示例
创建test_cases11.py文件
脚本代码:

import pytestdef login(username, password):print("登入操作!!!")return {"code": 0, "msg": "success!"}my_data = [({"username": "AllTests", "password": "123456"}, "success!"),({"username": "Admin123", "password": "123456"}, "success!"),({"username": "Admin456", "password": "123456"}, "success!")
]ids = ["输入正确a账号,正确密码,登录成功","输入正确b账号,正确密码,登录成功","输入正确c账号,正确密码,登录成功",
]@pytest.mark.parametrize("input_data, expected", my_data, ids=ids)
def test_login(input_data, expected):print("test_case-----login")result = login(input_data["username"], input_data["password"])assert result["msg"] == expected

打开命令行,输入执行命令

pytest -v .\Pytest_session\fixture_params\test_cases11.py

运行结果:
控制台输出中文时显示unicode编码问题。
在这里插入图片描述

3、解决ids参数用例描述为中文时,控制台输出显示unicode编码问题。
在项目的根目录或与用例同级目录下,创建conftest.py文件

def pytest_collection_modifyitems(items):for item in items:item.name = item.name.encode("utf-8").decode("unicode_escape")# print(item_nodeid)item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape")

重新执行用例,运行结果:
控制台输出中文时显示正常。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/726297.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nginx代理参数proxy_pass

proxy_pass参数用于配置反向代理&#xff0c;指定客户端请求被转发到后端服务器&#xff0c;后端地址可以是域名、ip端口URI 代理后端报错提示本地找不到CSS文件、JavaScript文件或图片 例如&#xff1a; nginx &#xff1a;10.1.74.109 后端服务&#xff1a;http://10.1.74.…

Hive Thrift Server

hive-site.xml配置文件 <property><name>hive.server2.thrift.bind.host</name><value>node1</value> </property>hive.server2.thrift.bind.host: This property determines the host address to which the HiveServer2 Thrift service …

HBase 的安装与部署

目录 1 启动 zookeeper2 启动 Hadoop3 HBase 的安装与部署4 HBase 高可用 1 启动 zookeeper [huweihadoop101 ~]$ bin/zk_cluster.sh start2 启动 Hadoop [huweihadoop101 ~]$ bin/hdp_cluster.sh start3 HBase 的安装与部署 &#xff08;1&#xff09;将 hbase-2.0.5-bin.tar.…

视频压缩会影响画质吗?正确答案在这里!

在当今数字时代&#xff0c;我们生活在一个高清、甚至是4K视频的世界中。随之而来的是巨大的视频文件大小&#xff0c;这在存储、传输和分享方面都带来了一些挑战。为了解决这一问题&#xff0c;许多人转向视频压缩&#xff0c;以便更有效地管理和共享视频内容。 然而&#xf…

嵌入式开发的常用软件、学习资源网站推荐

1、软件推荐 1.1、文本编辑软件 ——Notepad 1、适合编写和查看文本文件&#xff0c;也可以安装插件来查看二进制文件、对比文件 2、参考博客&#xff1a;《Notepad实用小技巧》&#xff1b; 1.2、PDF文件阅读软件——福昕PDF阅读器 福昕PDF阅读器&#xff0c;在官网就可以下载…

终于用上最新的Claude-3-opus和Claude-3-sonnet!

3 月 4 日&#xff0c;被称为 OpenAI 最强竞争对手的大模型公司 Anthropic 宣布推出 Claude3 系列模型&#xff0c;与 Gemini 类似&#xff0c;模型按照大小分为三个&#xff1a;Claude 3 Haiku、Claude 3 Sonnet 和 Claude 3 Opus。Opus 目前在官方发布的测试成绩中全方位超越…

信息安全与阿里云等保三级方案实践总结

信息安全在当今数字化时代变得至关重要&#xff0c;企业和组织需要采取有效措施来保护其数据和信息资产。阿里云作为中国领先的云服务提供商&#xff0c;提供了等保三级方案&#xff0c;帮助用户满足国家信息安全等级保护的要求。本文将探讨信息安全和阿里云等保三级方案的重要…

FPGA——三速自适应以太网设计(1)基本模块

FPGA——以太网设计&#xff08;1&#xff09;基本模块 1. 协议解析&#xff08;1&#xff09;MAC层&#xff08;2&#xff09;IP层 和 ARP层&#xff08;3&#xff09;UDP层 和 ICMP层 2.1 MAC接收模块2.2 MAC发送模块3.1 IP接收模块3.2 IP发送模块4.1 UDP接收模块4.2 UDP发送…

Flask入门三(Flask-session的使用、数据库链接池、wtforms、Flask定制命令、Flask-Cache)

文章目录 一、Flask-session使用1.使用方式一2.使用方式二3.读RedisSessionInterface源码4.flask-session补充 二、数据库连接池1.flask中使用mysql2.上述问题解决 使用数据库连接池1.第三方数据库连接池2.操作数据库不带池版3.池版和非池版压测 三、wtforms四、Flask定制命令1…

Excel中怎么求排名

使用Rank函数 1.在需要显示排名的单元格内&#xff0c;输入“RANK&#xff08;数值&#xff0c;数值列表&#xff0c;排序方式&#xff09;” 2.将“数值”替换为需要计算排名的单元格的地址&#xff0c;例如E2单元格。 3.将“数值列表”替换为排名的数值范围&#xff0c;例…

在win10中下载桌面版的docker并在docker中搭建运行基于linux的容器

在win10中下载桌面版的docker 1.背景 在很多时候需要linux系统部署项目&#xff0c;在win10中安装虚拟机并在虚拟机中安装linux系统比较繁琐&#xff0c;可以利用win10自带的hyper-v的虚拟机管理工具&#xff0c;打开该虚拟机管理工具&#xff0c;安装docker&#xff0c;并在…

如何应对IT服务交付中的问题?看了本文DevOps就懂了

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

vue接入百度地图获取经纬度

通过城市名称和城市中心经纬度来获取当前所在地图&#xff0c;当前经纬度中心获取可以通过后端获取 静态文件包&#xff0c;替换baidu.html中的ak值&#xff0c;ak值通过百度地图官方网站申请 申请&#xff1a;百度地图API申请步骤 - 知乎 代码示例文件&#xff1a; 链接&a…

记录vue3导入并使用echarts自定义主题文件设置统一图表样式

在做数据可视化网站时&#xff0c;有时需要用到多个图表&#xff0c;这时就需要对图表的样式做一个统一的设计使网站外观更整齐。具体步骤如下&#xff1a; 第一步&#xff1a;在echarts官网定制好主题&#xff0c;并下载js文件 第二步&#xff1a;在index.html文件引入该文件…

【MybatisPlus】BaseMapper详解,举例说明

一、BaseMapper 简介 MyBatis-Plus 的核心类 BaseMapper 主要是用于提供基本的 CRUD&#xff08;创建、读取、更新、删除&#xff09;操作的接口定义。它是 MyBatis-Plus 框架中的一个重要组成部分&#xff0c;可以大大简化基于 MyBatis 的数据访问层代码的编写。 BaseMapper…

视频产品介绍:国标28181网关(GB/T28118网关)

目 录 一、概述 二、产品功能 &#xff08;一&#xff09;功能描述 &#xff08;二&#xff09;功能展示 1、国标接入 2、资源绑定 三、产品能力 &#xff08;一&#xff09;接入能力 &#xff08;二&#xff09;多级架构 四、特点优势 &#xff08;一&am…

Rust泛型与trait特性,模仿接口的实现

泛型是一个编程语言不可或缺的机制。 C 语言中用"模板"来实现泛型&#xff0c;而 C 语言中没有泛型的机制&#xff0c;这也导致 C 语言难以构建类型复杂的工程。 泛型机制是编程语言用于表达类型抽象的机制&#xff0c;一般用于功能确定、数据类型待定的类&#xf…

三维GIS的业务导向

的确&#xff0c;目前三维GIS以做特效居多&#xff0c;酷炫、亮眼&#xff0c;从二维转到三维&#xff0c;第一眼就给人眼前一亮的感觉&#xff0c;就凭这一项&#xff0c;很多客户就会买单&#xff0c;GIS的客户以政府、科研院所、特种行业为主&#xff0c;买过一次单后&#…

【QT】定时器事件应用

public&#xff1a;//定时器void timerEvent(QTimerEvent *);private:int id;#include <QTimerEvent> //QWidget 默认不追踪鼠标事件 mylabel::mylabel(QWidget *parent) : QLabel(parent) {this->setMouseTracking(true);//启动定时器//参数1&#xff1a;触发定时器的…

JavaScript基础Ⅱ

目录 第2章 JavaScript基础语法(掌握) 11-JS代码调试 12-JS函数 第3章 JS事件 14-事件的绑定方式 常用事件(了解) 15-常用事件 第4章 JS内置对象(掌握) 16-数组 17-日期 18-数学运算 19-数字 20-全局函数 第2章 JavaScript基础语法(掌握) 11-JS代码调试 12-JS函数…