当前位置: 首页 > news >正文

Unittest单元测试框架之unittest构建测试套件

构建测试套件

在实际项目中,随着项目进度的开展,测试类会越来越多,可是直到现在我 们还只会一个一个的单独运行测试类,这在实际项目实践中肯定是不可行的,在 unittest中可以通过测试套件来解决该问题。

测试套件(Test Suite)是由多个测试用例(Test Case)组成的,当然也 可以由多个子测试套件组成

在unittest中,把测试用例加载到测试套件的方式有如下方法:(推荐方式六)

方式一、用unittest.TestSuite()实例化测试套件对象后,内部的addTest()方法对测试类内部的测试案例进行逐一添加。

注:使用addTest()方法,不是以test开头的用例也可以执行

代码示例:

# 1,一条一条添加测试用例
import unittestclass Test_Case(unittest.TestCase):def setUp(self):print("我是setup方法:进行测试前的初始化工作")def tearDown(self) -> None:  # 表示该方法没有返回值print("我是tearDown方法:执行测试后的清除工作")print("------------执行结束----------------")def test_aaa(self):print("我是case:test_aaa")def test_bbb(self):print("我是case:test_bbb")def ccc(self):print("我是case:ccc")# 测试套件
# 一条一条用例通过addTest方法添加
# 方法一:
# if __name__ == '__main__':
#     suite = unittest.TestSuite()  # 创建测试套件对象
#     suite.addTest(test_case("test_bbb"))  # addTest(类名(“方法名称”))
#     suite.addTest(test_case("ccc"))  # 不是以test开头的用例也可以执行
#     unittest.main(defaultTest="suite")# 方法二:
def suite():suite = unittest.TestSuite()suite.addTest(Test_Case("test_bbb"))  # addTest(类名(“方法名称”))suite.addTest(Test_Case("ccc"))return suite
if __name__ == '__main__':unittest.main(defaultTest="suite")

查看执行结果

方式二、用unittest.TestSuite()实例化测试套件对象后,内部的makeSuite()方法对整个测试类进行添加。

注:使用makeSuite()方法,不是以test开头的方法不会被添加进测试套件中

代码示例:

# 添加整个测试类
import unittestclass Test_Case(unittest.TestCase):def setUp(self):print("我是setup方法:进行测试前的初始化工作")def tearDown(self) -> None:  # 表示该方法没有返回值print("我的tearDown方法:执行测试后的清除工作")print("------------执行结束----------------")def test_aaa(self):print("我的case:test_aaa")def test_bbb(self):print("我的case:test_bbb")def ccc(self):print("我的case:ccc")# 能否添加整个测试类?
if __name__ == '__main__':# 注意:此时不是以test开头的方法不会被添加进测试套件中# 注意:makeSuite 可能需要手动添加suite = unittest.TestSuite(unittest.makeSuite(Test_Case))  # 里面是类名unittest.main(defaultTest="suite")

查看执行结果

方式三、使用TestLoader()方法添加整个测试类

注:unittest.TestLoader().loadTestsFromTestCase() 不是以test开头的方法不会被执行

代码示例:

# 3,添加整个测试类
# unittest中提供一个TestLoader类用于自动创建一个测试类,并且把单个测试自动放入测试集中
# TestLoader 类会自动运行以test开头的测试方法
import unittestclass Test_Case1(unittest.TestCase):def setUp(self):print("我是setup方法:进行测试前的初始化工作")def tearDown(self) -> None:  # 表示该方法没有返回值print("我是tearDown方法:执行测试后的清除工作")print("------------执行结束----------------")def test_aaa(self):print("我是case1:test_aaa")def test_bbb(self):print("我是case1:test_bbb")def ccc(self):print("我是case1:ccc")class Test_Case2(unittest.TestCase):def setUp(self):print("我是setup方法:进行测试前的初始化工作")def tearDown(self) -> None:  # 表示该方法没有返回值print("我是tearDown方法:执行测试后的清除工作")print("------------执行结束----------------")def test_aaa(self):print("我是case2:test_aaa")def test_bbb(self):print("我是case2:test_bbb")def test_ccc(self):print("我是case2:test_ccc")if __name__ == "__main__":suite = unittest.TestLoader().loadTestsFromTestCase(Test_Case1) # 填 类名unittest.main(defaultTest='suite')

查看执行结果

方式四、添加整个模块下所有的测试类

注:unittest.TestLoader().loadTestsFromName() 不是以test开头的方法不执行

代码示例:

# 4,添加整个模块下所有的测试类
import unittestclass Test_Case1(unittest.TestCase):def setUp(self):print("我是setup方法:进行测试前的初始化工作")def tearDown(self) -> None:  # 表示该方法没有返回值print("我的tearDown方法:执行测试后的清除工作")print("------------执行结束----------------")def test_aaa(self):print("我是case1:test_aaa")def test_bbb(self):print("我是case1:test_bbb")def ccc(self):print("我是case1:test_ccc")class Test_Case2(unittest.TestCase):def setUp(self):print("我是setup方法:进行测试前的初始化工作")def tearDown(self) -> None:  # 表示该方法没有返回值print("我的tearDown方法:执行测试后的清除工作")print("------------执行结束----------------")def test_aaa(self):print("我是case2:test_aaa")def test_bbb(self):print("我是case2:test_bbb")def test_ccc(self):print("我是case2:test_ccc")if __name__ == "__main__":# 通过TestLoader中字符串的方法加载用例;不以test开头的方法不执行# 1,增加一个测试用例  模块名称.类名.方法名称# suite = unittest.TestLoader().loadTestsFromName("demo11_测试套件4.test_case1.test_aaa")# 2,增加整个测试类# suite = unittest.TestLoader().loadTestsFromName("demo11_测试套件4.test_case1")# 3,增加整个.py模块下所有的测试类suite = unittest.TestLoader().loadTestsFromName("demo11_测试套件4")  # 填 py文件名unittest.main(defaultTest='suite')

查看执行结果

方式五、将多个子测试集进行整合到一个大的测试套件中

代码示例:

# 将多个子测试集进行整合到一个大的测试套件中
import unittest
from unittest框架 import  demo11_测试套件4  # 导入其他模块
from unittest框架 import  demo08_测试套件1  # 导入其他模块# 依次创建多个套件
# 1,单个用例套件
suite01 = unittest.TestLoader().loadTestsFromName('demo08_测试套件1.Test_Case.test_aaa')
# 2,整个类
suite02 = unittest.TestLoader().loadTestsFromName("demo08_测试套件1.Test_Case")
# 3,整个.py模块
suite03 = unittest.TestLoader().loadTestsFromName("demo11_测试套件4")main_suite = unittest.TestSuite()  # 主套件
main_suite.addTest(suite01)  # 添加子套件到主套件中
main_suite.addTest(suite02)
main_suite.addTest(suite03)unittest.main(defaultTest="main_suite")

查看执行结果

方式六、使用discover()来实现添加执行整个目录下所有的测试用例  (=====推荐=====)

当测试用例存放在多个不同子目录下,我们用之前的把用例加载到测试集合中的方 式还是不太方便,需要不断的去导入和添加测试用例模块,此时可以通过discover()方法 来实现

方法如下:
discover(start_dir,pattern ='test *.py', top_level_dir = None)

start_dir:要测试的模块名或测试用例目录

pattern="test*.py":表示用例文件名的匹配原则,例子中匹配文件名为以"test"开头的".py"文件,星号"*"表示任意多个字符;

top_level_dir=None:测试模块的顶层目录,如果没有顶层目录,默认为None。

该方法通过从指定的开始目录递归到子目录中查找所有测试模块,并返回包含它们的TestSuite对象,只要与模式匹配测试文件和可导入的模块名称才会被加载。

如果一个测试文件的名称符合pattern,会自动查找该文件中派生自TestCase 的类包含的 test 开头的方法作为测试方法

代码示例:

# 使用discover()来实现添加执行整个目录下所有的测试用例
import os
import unittest
import HTMLTestRunner
import time# 获取当前路径
curren_path = os.path.dirname(__file__)
# 获取测试用例目录的路径
case_path = os.path.join(curren_path,"all_case")# 从当前路径回到上一层路径
# case_path = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))# 匹配测试用例路径下的所有的测试方法
discover = unittest.defaultTestLoader.discover(start_dir=case_path,  # 用例路径pattern="*_case*.py",top_level_dir=None)   # 文件类型
# 创建主套件
main_suite = unittest.TestSuite()
# 把测试用例路径添加到主套件中
main_suite.addTest(discover)
# 执行主套件里的测试用例
unittest.main(defaultTest="main_suite")

查看执行结果

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

相关文章:

Unittest单元测试框架之unittest构建测试套件

构建测试套件 在实际项目中,随着项目进度的开展,测试类会越来越多,可是直到现在我 们还只会一个一个的单独运行测试类,这在实际项目实践中肯定是不可行的,在 unittest中可以通过测试套件来解决该问题。 测试套件&…...

Django回顾4

一.过滤器 1.过滤器格式 {{变量|过滤器名字}} 2.怎么使用 1.注册app 2.在app下创建templatetags模块(模块名只能是templatetags) 3.在包下写一个py文件,随便命名 4.在py文件中写入:from django import template …...

Apache APISIX 体验指南

APISIX 体验指南 所有的 sh 脚本通过 git bash 执行。 出现错误仔细核对文档。 github 地址: 使用 docker 安装 apisix 确保本地安装 Docker 和 Docker-compose 如未安装参开以下文档安装: Docker:https://docs.docker.com/engine/install/c…...

Promise的resolve和reject方法(手写题)

1.resolve 2.reject 3.手写 1.resolve //构造函数上添加 resolve 方法 Promise.resolve function (value) {return new Promise((resolve, reject) > {if (value instanceof Promise) {value.then((val) > {resolve(val)},(err) > {reject(err)})} else {resolve(v…...

关于wiki的Unlink攻击理解--附例题BUUCTF-hitcontraining_bamboobox1

堆机制我研究了很久,一直没有什么很大的进展。堆相较于栈难度大的多。利用手法也多。目前还没有怎么做过堆题。这次就把理解了很久的Unlink写一写。然后找一题实践一下。 在glibc中,堆管理都是用一个个chunk去组织的。这个就不过多阐述。Unlink是glibc一…...

【linux】日志有哪些

Linux系统日志主要有以下几种类型: 内核及系统日志:这种日志数据由系统服务rsyslog统一管理,根据其主配置文件/etc/rsyslog.conf中设置决定内核消息及各种系统程序消息记录到什么位置。/var/log/message:该日志文件存放了内核消息…...

Redis主从复制实现RCE

文章目录 前置知识概念redis常用命令redis module 利用条件利用工具思路例题 [网鼎杯 2020 玄武组]SSRFMe总结 前置知识 概念 背景是多台服务器要保存同一份数据,如何实现其一致性呢?数据的读写操作是否每台服务器都可以处理?这里Redis就提供…...

Flutter应用程序的加固原理

在移动应用开发中,Flutter已经成为一种非常流行的技术选项,可以同时在Android和iOS平台上构建高性能、高质量的移动应用程序。但是,由于其跨平台特性,Flutter应用程序也面临着一些安全风险,例如反编译、代码泄露、数据…...

Centos7部署NFS

搭建NFS存储服务器--基于CentOS7系统 - jianmuzi - 博客园 在CentOS中搭建NFS - 陌上荼靡 - 博客园 NFS简介 NFS 是 Network FileSystem 的缩写,顾名思义就是网络文件存储系统,它最早是由 Sun 公司发展出来的,也是 FreeBSD 支持的文件系统…...

我已经开了一个融资融券的账户了,还可以再在别的券商开两融(信用账户)吗?

融资融券交易又称“证券信用交易”或保证金交易,是指投资者向具有融资融券业务资格的证券公司提供担保物,借入资金买入证券(融资交易)或借入证券并卖出(融券交易)的行为。 简单说就是融资做多,…...

Spring Cloud 版本升级记:OpenFeignClient与Gateway的爱恨交织

Spring Cloud 版本升级记:OpenFeignClient与Gateway的爱恨交织 近日,在负责的项目中,我对 Spring Boot、Spring Cloud 以及 Spring Cloud Alibaba 进行了版本升级。原以为会一切顺利,没想到却遭遇了 Spring Cloud Gateway 无法正…...

华为OD机试 - 最多购买宝石数目(Java JS Python C)

题目描述 橱窗里有一排宝石,不同的宝石对应不同的价格,宝石的价格标记为 gems[i] 0 ≤ i < nn = gems.length宝石可同时出售0个或多个,如果同时出售多个,则要求出售的宝石编号连续; 例如客户最大购买宝石个数为m,购买的宝石编号必须为:gems[i],gems[i+1],...,ge…...

【LeetCode】挑战100天 Day17(热题+面试经典150题)

【LeetCode】挑战100天 Day17&#xff08;热题面试经典150题&#xff09; 一、LeetCode介绍二、LeetCode 热题 HOT 100-192.1 题目2.2 题解 三、面试经典 150 题-193.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站&#xff0c;提供各种算法和数据结构的题目&…...

正则表达式的基本语法

1.正则表达式基本语法 两个特殊的符号^和$。他们的作用是分别指出一个字符串的开始和结束。例子如下&#xff1a; "^The"&#xff1a;表示所有以"The"开始的字符串&#xff08;"There"&#xff0c;"The cat"等&#xff09;&#xff1…...

使用visual Studio MFC 平台实现对灰度图添加椒盐噪声,并进行均值滤波与中值滤波

平滑处理–滤波 本文使用visual Studio MFC 平台实现对灰度图添加椒盐噪声&#xff0c;并进行均值滤波与中值滤波 关于其他MFC单文档工程可参考 01-Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线 02-visual Studio MFC 绘制单一颜色三角形、渐变颜色边…...

Django HMAC 请求签名校验与 Vue.js 实现安全通信

概要 在 Web 应用的开发过程中&#xff0c;确保数据传输的安全性和完整性是一个不容忽视的问题。使用 HMAC&#xff08;Hash-based Message Authentication Code&#xff09;算法对请求内容进行签名校验&#xff0c;是一种常见且有效的安全策略。本文将详细介绍如何在 Django …...

深度学习之循环神经网络

视频链接&#xff1a;6 循环神经网络_哔哩哔哩_bilibili 给神经网络增加记忆能力 对全连接层而言&#xff0c;输入输出的维数固定&#xff0c;因此无法处理序列信息 对卷积层而言&#xff0c;因为卷积核的参数是共享的&#xff0c;所以卷积操作与序列的长度无关。但是因为卷积…...

与原有视频会议系统对接

要实现与原有视频会议系统对接&#xff0c;需要确保通信协议的一致性。连通宝视频会议系统可与第三方视频会议系统对接。实现与第三方会议系统对接还可以使用会议室连接器&#xff0c;可以确保不同系统之间的数据传输和交互。 具体对接流程可能因不同品牌和类型的视频会议系统而…...

C# Serilog--可记录异常完整路径

1.Serilog安装 2.控制台代码 --设置日志记录器的最小级别为 Debug&#xff0c;即只记录 Debug 级别及以上的日志信息 --.WriteTo.File("logs\\log.txt", rollingInterval: RollingInterval.Day)&#xff1a;将日志信息写入到指定路径的文件中&#xff08;这里的路径…...

鉴源实验室 | 汽车网络安全攻击实例解析(三)

作者 | 张璇 上海控安可信软件创新研究院工控网络安全组 来源 | 鉴源实验室 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 引言&#xff1a;随着现代汽车技术的迅速发展&#xff0c;车辆的进入和启动方式经历了显著的演变。传统的物理钥匙逐渐被无钥匙进…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

恶补电源:1.电桥

一、元器件的选择 搜索并选择电桥&#xff0c;再multisim中选择FWB&#xff0c;就有各种型号的电桥: 电桥是用来干嘛的呢&#xff1f; 它是一个由四个二极管搭成的“桥梁”形状的电路&#xff0c;用来把交流电&#xff08;AC&#xff09;变成直流电&#xff08;DC&#xff09;。…...

Vue3中的computer和watch

computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...