软测入门(六)pytest单元测试
pytest
pytest是python的一种单元测试框架,同自带的unit test测试框架类似,但pytest更简洁高效。
单元测试:
- 测试 函数、类、方法能不能正常运行
- 测试的结果是否符合我们的预期结果
安装
pip install -U pytest
基本使用
- 通过pytest包使用
import pytestdef test_a():print("test_a")return 1 + 0def test_b():print("test_b")return 1 / 0if __name__ == '__main__':pytest.main()
默认情况下:在main中直接使用pytest
的main()方法,会把文件中所有test_*
开头的方法执行一遍。
- 通过终端的命令使用,到所在目录下执行
# pytest或加参数都可
pytest -s
单量执行测试文件
import pytestdef test_1():print("test_1+++")return 1 + 0def test_2():print("test_2--------")return 1 / 0if __name__ == '__main__':# 只运行 test_py2.py文件中的测试方法pytest.main(["-s", "test_py2.py"])
配置文件
测试自动触发规则:
-
在测试目录中或当前的目录中寻找
-
名称为
test_*.py
或*_test.py
的文件 -
Test开头的类,且没有初始化
__init__
方法 -
以上目录或类中,test开头的函数或方法
-
会执行uinit test的测试用例类
运行pytest时,自动读取所在目录中的配置文件pytest.ini
。在测试文件所在目录下创建一个pytest.ini
内容如下:注意:以下内容请将 中文全部删掉,否则可能出问题,这里只是为了解释配置的。
[pytest]
; ini文件中的英文分号,都是注释
addopts = -s ;选项参数testpaths = ./ ;测试模块所在目录python_files = test_*.py *test.py ;测试文件名称python_classes = Test_* ;测试类名称规则python_functions = test_* ;测试函数或者方法命名规则
假如我把python_functions
修改为demo_*
,那么只有以demo_函数名
命名的函数才会被执行。
断言
import pytestdef test_1():print("test_1+++")assert 20 == 20def test_2():print("test_2--------")assert "a" in "hello"if __name__ == '__main__':pytest.main(["-s", "test_py2.py"])
标记
标记跳过测试
- 标记跳过(装饰器)
- 标记失败(装饰器)
@pytest.mark.skip("跳过")
def test_2():print("test_2--------")return 1 / 0@pytest.mark.xfail(raises=ZeroDivisionError)
def test_3():print("test_3--------")return 1 / 0
参数化
比如写了一个函数需要模拟一些参数进行调用,那么可以使用:
parametrize装饰器
:
- [“a”, “b”],列表中定义的方法参数名
- [(1, 2), (2, 2), (50, 51)],三组测试数据,表示此方法会被调用3次
import pytest@pytest.mark.parametrize(["a", "b"], [(1, 2), (2, 2), (50, 51)])
def test_1(a, b):print("test_1+++++++")assert a + b > 100if __name__ == '__main__':pytest.main(["-s", "test_py3.py"])
夹具
在测试之前和之后执行,用于固定测试环境,及清理回收测试资源。
setup_...
和teardown_...
-
模块的夹具:
setup_module()和teardown_module()
,在python文件加载前和文件内容结束后执行import pytestdef setup_module(args):print("setup_module", args)def teardown_module(args):print("teardown_module", args)def test_fun_a():print("------------", "test_fun_a")def test_fun_b():print("------------", "test_fun_b")class TestOne:def test_1(self):print("------", "test_1")def test_2(self):print("------", "test_2")if __name__ == '__main__':pytest.main(["-s", "test_py4.py"])###################################################结果######################## test_py4.py setup_module <module 'test_py4' from 'D:\\environment\\python-workspace\\androidTest\\pytest\\test_py4.py'> ------------ test_fun_a .------------ test_fun_b .------ test_1 .------ test_2 .teardown_module <module 'test_py4' from 'D:\\environment\\python-workspace\\androidTest\\pytest\\test_py4.py'>
-
函数的夹具:
setup_function()和teardown_function()
,py中函数执行前和执行后执行(注意是函数,不是类中的方法)import pytestdef setup_function(args):print("setup_function", args)def teardown_function(args):print("teardown_function", args)def test_fun_a():print("------------", "test_fun_a")def test_fun_b():print("------------", "test_fun_b")class TestOne:def test_1(self):print("------", "test_1")def test_2(self):print("------", "test_2")if __name__ == '__main__':pytest.main(["-s", "test_py4.py"]) ###################################################结果########################test_py4.py setup_function <function test_fun_a at 0x000001ED1D8C31F8> ------------ test_fun_a .teardown_function <function test_fun_a at 0x000001ED1D8C31F8> setup_function <function test_fun_b at 0x000001ED1D8C3288> ------------ test_fun_b .teardown_function <function test_fun_b at 0x000001ED1D8C3288> ------ test_1 .------ test_2
-
类的夹具:
setup_class()和teardown_class()
,类被加载前和销毁后执行class TestOne:def setup_class(self):print("------", "setup___test_1")def teardown_class(self):print("------", "teardown___test_1")def test_1(self):print("------", "test_1")def test_2(self):print("------", "test_2")if __name__ == '__main__':pytest.main(["-s", "test_py4.py"])###################################################结果######################## ------ setup___test_1 ------ test_1 .------ test_2 .------ teardown___test_1
-
方法的夹具:
setup_method()和teardown_method()
,类被加载前和销毁后执行class TestOne:def setup_class(self):print("------", "setup___test_1")def teardown_class(self):print("------", "teardown___test_1")def setup_method(self, args):print("------", "setup_methods___test_1", args)def teardown_method(self, args):print("------", "teardown_methods___test_1", args)def test_1(self):print("------", "test_1")def test_2(self):print("------", "test_2")if __name__ == '__main__':pytest.main(["-s", "test_py4.py"])###################################################结果######################## setup___test_1 ------ setup_methods___test_1 <bound method TestOne.test_1 of <test_py4.TestOne object at 0x000001D972FB28C8>> ------ test_1 .------ teardown_methods___test_1 <bound method TestOne.test_1 of <test_py4.TestOne object at 0x000001D972FB28C8>> ------ setup_methods___test_1 <bound method TestOne.test_2 of <test_py4.TestOne object at 0x000001D972FB2988>> ------ test_2 .------ teardown_methods___test_1 <bound method TestOne.test_2 of <test_py4.TestOne object at 0x000001D972FB2988>> ------ teardown___test_1
fixture装饰器夹具
import pytest# 设置夹具
@pytest.fixture()
def before():print("before")# 使用夹具
@pytest.mark.usefixtures("before")
def test_1():print("test_1执行")# 设置夹具 有返回值
@pytest.fixture()
def login():print("login")return "user"# 使用夹具 入参
def test_2(login):print("test_2执行")print(login)@pytest.fixture(params=[1, 2, 3])
def init_data(request):# params中有三个元素,那么此方法将执行三遍print("参数:", request.param)return request.paramdef test_data(init_data):assert init_data > 2if __name__ == '__main__':pytest.main(["-s", "test_py5.py"])
###################################################结果################################
test_py5.py 参数: 1
F参数: 2
F参数: 3
.before
test_1执行
.login
test_2执行
user================================== FAILURES ===================================
________________________________ test_data[1] _________________________________init_data = 1def test_data(init_data):
> assert init_data > 2
E assert 1 > 2test_py5.py:24: AssertionError
________________________________ test_data[2] _________________________________init_data = 2def test_data(init_data):
> assert init_data > 2
E assert 2 > 2test_py5.py:24: AssertionError
=========================== short test summary info ===========================
FAILED test_py5.py::test_data[1] - assert 1 > 2
FAILED test_py5.py::test_data[2] - assert 2 > 2
========================= 2 failed, 3 passed in 0.03s =========================
pytest插件
html报告
-
安装插件
pip install pytest-html
-
使用
-
命令行方式
pytest --html=存储路径/report.html
-
配置文件方式
[pytest] addopts = -s --html=./report.html
-
指定运行顺序
-
安装插件
pip install pytest-ordering
-
使用
添加装饰器
@pytest.mark.run(order=x)
到测试函数或者方法上。优先级:
- 0和正整数 > 没有标记 > 负整数标记
- 且在各个阶段,数越小运行优先级越高
import pytest@pytest.mark.run(order=0) def test_1():print("1")@pytest.mark.run(order=-3) def test_2():print("2")@pytest.mark.run(order=3) def test_3():print("3")@pytest.mark.run(order=2) def test_4():print("4")@pytest.mark.run(order=1) def test_5():print("5")if __name__ == '__main__':pytest.main(["-s", "test_py6.py"])###################################################结果############################### test_py6.py 1 .5 .4 .3 .2
失败重试
-
安装插件
pip install pytest-rerunfailures
-
使用
配置,
--reruns 5
重试5次[pytest] addopts = -s --reruns 5
相关文章:
软测入门(六)pytest单元测试
pytest pytest是python的一种单元测试框架,同自带的unit test测试框架类似,但pytest更简洁高效。 单元测试: 测试 函数、类、方法能不能正常运行测试的结果是否符合我们的预期结果 安装 pip install -U pytest基本使用 通过pytest包使用…...
经典分类模型回顾5—DenseNet实现图像分类(matlab)
DenseNet,全称为Densely Connected Convolutional Networks,中文名为密集连接卷积网络,是由李沐等人在2017年提出的一种深度神经网络架构。 DenseNet旨在解决深度神经网络中的梯度消失问题和参数数量过多的问题,通过构建密集连接…...

基于flask+bootstrap+echarts+mysql的鱼村小馆订餐后台管理系统
📋 个人简介 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜📝 个人主页:馆主阿牛🔥🎉 支持我:点赞👍收藏⭐️留言Ὅ…...
Spark使用Log4j将日志发送到Kafka
文章目录自定义KafkaAppender修改log4j.properties配置启动命令配置添加参数启动之后可以在Kafka中查询发送数据时区问题-自定义实现JSONLayout解决自定义JSONLayout.java一键应用可能遇到的异常ClassNotFoundException: xxx.KafkaLog4jAppenderUnexpected problem occured dur…...

c++类与对象整理(上)
目录 1.类的引入 2.类的定义 3.类的访问限定符及封装 1)访问限定符 2)封装 4.类的作用域 5.类的实例化 6.类的对象大小的计算 1)类对象的存储方式 2)内存对齐和大小计算 编辑 7.类成员函数的this指针 1)…...
Docker学习(十九)什么是镜像的元数据?
在 Docker 中,镜像的元数据是指与镜像相关的所有信息,包括镜像的名称和标签、作者、描述、创建日期、环境变量、命令等。这些信息都是通过 Dockerfile 或命令行创建和指定的。 镜像的元数据被存储在 Docker Registry 中,并在使用 docker pull…...

Python如何获取弹幕?给你介绍两种方式
前言 弹幕可以给观众一种“实时互动”的错觉,虽然不同弹幕的发送时间有所区别,但是其只会在视频中特定的一个时间点出现,因此在相同时刻发送的弹幕基本上也具有相同的主题,在参与评论时就会有与其他观众同时评论的错觉。 在国内…...
JAVA- AOP 面向切面编程 Aspect切面工具类 记录特定方法执行时的入参、执行时间、返参等内容
背景:JAVA项目,使用AOP对指定函数进行切面。能够记录特定方法执行时的入参、执行时间、返参结果等内容。 文章目录1、自定义注解类1.1 Target1.2 Retention2、Aspect切面工具2.1 JointPoint2.2 Pointcut2.3 切面中的相关注解3、同一个类里调用AOP4、其他…...

「史上最全的 TCG 规范解读」TCG 规范架构概述(下)
可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强不同计算机平台上计算环境的安全性。TCG 于 2003 年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Allia…...

GDScript 导出变量 (4.0)
概述 导出变量的功能在3.x版本中也是有的,但是4.0版本对其进行了语法上的改进。 导出变量在日常的游戏制作中提供节点的自定义参数化调节功能时非常有用,除此之外还用于自定义资源。 本文是(Bilibili巽星石)在4.0官方文档《GDScr…...
JAVA知识点全面总结6:泛型反射和注解
六.JAVA知识点全面总结6泛型反射和注解 1.什么是泛型?可以用在哪里? 2.泛型擦除机制是什么?为什么擦除? 3.通配符是什么?作用是什么? 未更新 1.注解是什么?有什么用? 2.注解的自定义和实…...
死代码删除(DCE,Dead Code Elimination)和激进的死代码删除(ADCE,Aggressive DCE)
死代码删除(DCE,Dead Code Elimination)和激进的死代码删除(ADCE,Aggressive DCE)死代码删除(DCE,Dead Code Elimination)DCE简介DCE基本算法激进的死代码删除࿰…...

询问new bing关于android开发的15个问题(前景、未来、发展方向)
前言:new bing是基于chat-gpt的新搜索工具,可以采用对话方式进行问题搜索,经过排队等候终于可以使用new bing,询问了目前我最关心的关于android开发几个问题 文章目录1.如何学好android开发?2.android开发能做什么?3.…...

【C++】初识类和对象
🏖️作者:malloc不出对象 ⛺专栏:C的学习之路 👦个人简介:一名双非本科院校大二在读的科班编程菜鸟,努力编程只为赶上各位大佬的步伐🙈🙈 目录前言一、面向过程和面向对象初步认识二…...

EPICS S7nodave手册
第一章:介绍 本手册分为6章(不算次介绍部分)。第一章介绍s7nodave用于EPICS的设备支持的概念和特新。第二章描述启动一个使用s7nodave的IOC项目所需要的几步。第三章描述s7nodave支持的IOC shell命令。之后,第四章解释s7nodave支持的各种记录类型。最后…...

2023最新版本RabbitMQ的持久化和简单使用
上节讲了 RabbitMQ下载安装教程 , 本节主要介绍RabbitMQ的持久化和简单使用。 一、RabbitMQ消息持久化 当处理一个比较耗时得任务的时候,也许想知道消费者(consumers)是否运行到一半就挂掉。在当前的代码中,当RabbitM…...
函数式编程
函数式编程(一) 文章目录函数式编程(一)1. 前言1.1 概念2. Lambda 表达式2.1 概述2.2 基本的格式2.3 触发条件2.4 Lambda表达式2.4.1 无参无返回值2.4.2 有参无返回值2.4.3 无参数有返回值2.4.4 有参有返回值【重点】2.4.4.1 比较…...

【Java 类】001-访问修饰符、命名规范
【Java 类】001-访问修饰符、命名规范 文章目录【Java 类】001-访问修饰符、命名规范一、访问修饰符概述1、是什么2、作用作用问题3、访问修饰符有哪些4、作用对象二、访问修饰符使用演示1、类访问修饰符演示第一步:创建 Dog 类:public第二步:…...

【C++】命名空间
🏖️作者:malloc不出对象 ⛺专栏:C的学习之路 👦个人简介:一名双非本科院校大二在读的科班编程菜鸟,努力编程只为赶上各位大佬的步伐🙈🙈 目录前言一、命名空间产生的背景二、命名空…...

【AutoSAR】【MCAL】Dio
一、结构 二、功能介绍 DIO(数字输入输出)驱动模块主要是对端口(Port),通道(Channel)和通道组(ChannelGroup)进行读写操作。 通道(Channel)&…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...