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(热题面试经典150题) 一、LeetCode介绍二、LeetCode 热题 HOT 100-192.1 题目2.2 题解 三、面试经典 150 题-193.1 题目3.2 题解 一、LeetCode介绍 LeetCode是一个在线编程网站,提供各种算法和数据结构的题目&…...
正则表达式的基本语法
1.正则表达式基本语法 两个特殊的符号^和$。他们的作用是分别指出一个字符串的开始和结束。例子如下: "^The":表示所有以"The"开始的字符串("There","The cat"等)࿱…...

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

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

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

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

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

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

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
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也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)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.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
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封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...