如何用多线程执行 unittest 测试用例实现方案

前言

使用python做过自动化测试的小伙伴,想必都知道unittest和pytest这两个单元测试框架,其中unittest是python的官方库,功能相对于pytest来要逊色不少,但是uniitest使用上手简单,也受到的很多的小伙伴喜爱。一直以来都有小伙伴在问我,pytest可以通过相关的插件来实现多线程执行测试用例,为什么unittest没有呢?unittest如何去实现多线程运行呢?那么今天就专门来给大家聊聊如何使用多线程去执行unittest!

一、unittest 测试用例的运行机制

在讲使用多线程去执行uniitest的测试用例之前,我们首先来分析一下,unittest中用例可以通过哪几种方式来执行。这个时候就得去看看unittest的源码了。

虽然 unittest 的底层代码是基于 C 语言实现的,源码中看不到详细的代码,但是我们可以发现 TestCase、TestSuite、TestRnner 三个类中都有 run 方法,而且 run 方法的作用的都是执行测试用例。

  • TestRunner 可以执行单条测试用例以及测试套件中所有的用例
  • TestSuite 是直接执行套件中所有的用例
  • Testcase 中的 run 方法是执行当前这条测试用例

其实不管是 TestRunner 还是 TestSuite 的 run 方法执行用例,最终还是调用了用例本身的 run 方法去执行的。用例执行的方法我们搞清楚了,那么接下来我们就可以采取相关的策略使用多线程来执行了。

二、多线程执行用例的实现思路

  • 思路一:创建多个测试套件,每个套件使用一个线程去执行报告
  • 优缺点:
  • 优点:同一个测试用例类中用例执行的先后顺序能够得到保障
  • 缺点:用例需要自己手动添加到套件,然后分配给各个线程,会出现用例数量分配不均,线程资源浪费,
  • 思路二:所有的用例收集到测试套件,使用多线程去执行套件的测试用例,
  • 优缺点:
  • 优点:多线程共享用例资源,能够充分利用多线程的资源
  • 缺点:用例执行的先后顺序不好控制

三、思路一:具体实现:

1、初步尝试


"""文件1:testcase.py"""import unittestclass TestRegister(unittest.TestCase):"""此处用例代码以省略"""class TestLogin(unittest.TestCase):"""此处用例代码以省略""""""文件2:run_case.py"""import unittest,threadingfrom case_test.test_case import TestLogin, TestRegister# 创建2个套件,每个套件使用一个线程去执行suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(TestRegister)suite2 = unittest.defaultTestLoader.loadTestsFromTestCase(TestLogin)def work1():"""执行套件1"""unittest.TextTestRunner().run(suite1)def work2:"""执行套件2"""unittest.TextTestRunner().run(suite1)t1 = threading.Thread(target=work1)t2 = threading.Thread(target=work2)t1.start()t2.start()t1.join()t2.join()

运行上面的 run_case.py 就会发现两个线程可以同时执行测试用例,但是存在一个问题,用例执行完之后,每个线程得到的结果是独立的,无法整合到一起!于是进行了以下优化。

2、再次尝试:测试结果整合

前面我们在执行测试套件的时候,是通过 TestRunner 去执行的,TestRunner 的 run 方法的参数只能传入测试用例或者测试套件,而 unittest 中 TestSuite,和 TestCase 的 run 方法在调用的时候,可以接收一个叫做 TestResult 的对象。而用例执行的结果就是保存在这个 TestResult 对象中。我们如果要整个测试结果可以自己先创建一个 TestResult 对象,然后执行套件的时候传进入,最后两个套件执行得到的测试结果都会保存在这一个 TestResult 对象中。代码如下


# 创建一个结果保存对象res = unittest.TestResult()# 运行测试套件返回测试结果t1 = threading.Thread(target=suite1.run,kwargs={"result":res})t2 = threading.Thread(target=suite2.run, kwargs={"result": res})t1.start()t2.start()t1.join()t2.join()print(res)

运行上述代码,我们成功的使用多线程运行了测试用例,并且将测试用例执行的结果整合到了一起。

3、封装一个基于线程池来执行的函数

下面的代码封装用到了线程池的相关知识点,大家可以自行扩展


"""============================Author:测试师-万里Time:2020/5/26 10:00E-mail:123456789@qq.comCompany:五百万里信息技术有限公司============================"""import unittestfrom concurrent.futures.thread import ThreadPoolExecutorfrom test_case import TestLogin, TestRegisterdef run_test(suites, thread_count=1):"""多线程执行用例的方法:param suite: list -->包含多个套件的列表[TestSuite,TestSuite]:param thread_count: int ---->执行的线程数量,默认为1:return: TestResult--->测试结果"""res = unittest.TestResult()# 创建一个线程池,执行测试用例with ThreadPoolExecutor(max_workers=thread_count) as ts:for suite in suites:# 将套件的执行提交到线程池中ts.submit(suite .run, result=res)return resif __name__ == '__main__':# 创建两个套件suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(TestRegister)suite2 = unittest.defaultTestLoader.loadTestsFromTestCase(TestLogin)# 将套件放到列表中suite = [suite1, suite2]# 给根据套件的数量,每个套件创建一个线程去执行res = run_test(suite=suite, thread_count=len(suite))# 打印测试结果print(res)

四、思路二、代码封装

思路一实现了之后,思路二再来实现就会非常简单了,封装的代码如下:


"""============================Author:测试师-万里Time:2020/5/26 10:00E-mail:123456789@qq.comCompany:五百万里信息技术有限公司============================"""import unittestfrom concurrent.futures.thread import ThreadPoolExecutorfrom case_test.test_case import TestLogin, TestRegisterdef run_test(suite, thread_count=1):"""多线程执行用例的方法:param suite: 测试套件:param thread_count: int ---->执行的线程数量,默认为1:return: TestResult--->测试结果"""res = unittest.TestResult()# 创建一个线程池,执行测试用例with ThreadPoolExecutor(max_workers=thread_count) as ts:for case in suite:# 将用例的执行任务提交到线程池中ts.submit(case.run, result=res)return resif __name__ == '__main__':# 创建两个套件suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(TestRegister)# 给根据套件的数量,每个套件创建一个线程去执行res = run_test(suite=suite1, thread_count=3)# 打印测试结果print(res)

关于多线程执行 unittest 就给大家分享到这里!看到这里可能有些小伙伴会问,多线程执行如何生成测试报告呢?目前 unittest 生成测试报告使用的几个开源的库,比如 BeautifulReport,HTMLTestRunner 都不支持多线程。不过要想实现的话也不难,对这些模块运行用例的方法进行重写就可以实现。

关于多线程执行 unittest 就给大家分享到这里!看到这里可能有些小伙伴会问,多线程执行如何生成测试报告呢?

那么接下来就这大家介绍一下如何使用 unittestreport 多线程运行用例,并生产测试报告

五、unittestreport 多线程执行用例

使用 unittestreport 来多线程执行用例非常简单,只需要在执行用例时加一个参数 thread_count,指定执行的线程即可。案例如下:


from unittestreport import TestRunner# 加载套件suite = unittest.defaultTestLoader.discover(CASE_DIR)# 执行用例runner = TestRunner(suite,filename=conf.get('report', "filename"),report_dir=REPORT_DIR,title='测试报告',tester='万里',desc="万里执行测试生产的报告",templates=1)# 指定三个线程运行测试用例runner.run(thread_count=3)

关于 unittest 多线程执行测试用例 就给大家分享到这里了!喜欢的可以关注我哟,关注我每天给大家带来不同的惊喜。

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

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

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

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

相关文章

上海交通大学、中科大 开源镜像站停止 Docker Hub 仓库镜像支持后的可用替代源

上海交通大学 Linux 用户组发布公告: 即时起中止对 Docker Hub 仓库的镜像。Docker 相关工具默认会自动处理失效镜像的回退,如果对官方源有访问困难问题,建议尝试使用其他仍在服务的镜像源。 源加速地址 有网友表示百度的 Docker Hub 加速器…

【C语言实现内核链表】

以下是一个使用 C 语言实现简单内核链表的示例代码&#xff1a; #include <stdio.h> #include <stdlib.h>// 定义链表节点结构体 typedef struct ListNode {int data;struct ListNode *next; } ListNode;// 创建新节点 ListNode* createNode(int data) {ListNode*…

关于软件交付质量度量标准 这里是一些建议

在软件交付之后&#xff0c;质量的度量标准是确保软件满足用户需求、运行稳定、易于维护和扩展的关键。以下是一些常见的质量度量标准&#xff1a; 1. 功能性 功能覆盖率&#xff1a;软件实现了需求文档中规定的所有功能。缺陷密度&#xff1a;每千行代码中的缺陷数。缺陷密度…

数据库性能优化

在Java项目中&#xff0c;常见的难点之一是 数据库性能优化。随着应用规模的扩大&#xff0c;数据库的读写压力增大&#xff0c;查询性能下降可能导致系统响应变慢&#xff0c;甚至引发系统崩溃。以下介绍这个难点&#xff0c;并提供相应的解决方案。 难点&#xff1a;数据库性…

我在高职教STM32——GPIO入门之蜂鸣器

大家好&#xff0c;我是老耿&#xff0c;高职青椒一枚&#xff0c;一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次&#xff0c;同行应该都懂的&#xff0c;老师在课堂上教学几乎是没什么成就感的。正因如此&#xff0c;才有了借助 CSDN 平台寻求认同感和成就…

C++语法04 标准输入语句

标准输入 使用格式&#xff1a;cin >> 输入的意思就是把一个值放到变量里面去&#xff0c;也就是变量的赋值&#xff0c;这个值是由我们自己输入的。 (注意:输入变量前要先定义&#xff0c;输入完之后要按Enter键。) 输入多个变量&#xff0c;与输出类似&#xff0c;…

【R语言入门】开启R的会话并大步向前!

R语言入门 – 开启R的会话并大步向前! R Programming Essentials – Launch R Session and Go Forward! By Jackson@ML 名言引述 There are only two kinds of languages: the ones people complain about and the ones nobody uses. –Bjarne Stroustrup 0. R语言的诞生 1…

LabVIEW程序内存泄漏分析与解决方案

维护他人编写的LabVIEW程序时&#xff0c;若发现程序运行时间越长&#xff0c;占用内存越大直至崩溃&#xff0c;通常是内存泄漏导致的。本文从多角度分析内存泄漏的可能原因&#xff0c;包括数组和字符串处理、未释放的资源、循环中的对象创建等&#xff0c;并提供具体的解决方…

前端开发之浏览器垃圾回收机制

前端开发之浏览器垃圾回收机制 V8引擎&#xff0c;作为Chrome浏览器和Node.js等环境下的JavaScript运行引擎&#xff0c;其垃圾回收机制是确保高效内存管理的关键。 V8垃圾回收机制的深度解析与优化 V8 JavaScript引擎采用了高效的垃圾回收机制&#xff0c;其中核心的实现特…

【细胞分割 + 图谱配准】论文综述

文章目录 一、细胞分割1.1、细胞分割&#xff1a;cellposeCellpose3: one-click image restoration for improved cellular segmentationCellpose 2.0: how to train your own modelCellpose: a generalist algorithm for cellular segmentation 1.2、细胞分割与染色 —— Cell…

《c语言》 switch case语句中定义变量

这两种情况涉及到C/C语言中switch语句的一个特殊用法和作用域的规则。关键的区别在于变量声明位置和作用域。 第一种方式 int main() {switch (1){case 1:int a; // 错误&#xff1a;在这里声明变量是不允许的break;} }在第一种方式中&#xff0c;直接在switch语句的第一个{后…

算法体系-19 第十九节 暴力递归到动态规划

一 动画规划的概念 优化出现重复解的递归 一旦写出递归来&#xff0c;改动态规划就很快 尝试策略和状态转移方程是一码事 学会尝试是攻克动态规划最本质的能力 如果你发现你有重复调用的过程&#xff0c;动态规划在算过一次之后把答案记下来&#xff0c;下回在越到重复调用过程…

MySQL中的隐式转换(Implicit Conversion)

MySQL中的隐式转换&#xff08;Implicit Conversion&#xff09;指的是在SQL语句的执行过程中&#xff0c;数据库管理系统&#xff08;DBMS&#xff09;自动进行的数据类型转换。这种转换通常发生在数据类型不匹配但需要进行比较、计算或赋值等操作时。 以下是一些关于MySQL隐…

助力全息通信技术!GPS-Gaussian实现2K实时人体新视点合成

论文标题&#xff1a; GPS-Gaussian: Generalizable Pixel-wise 3D Gaussian Splatting for Real-time Human Novel View Synthesis 论文作者&#xff1a; Shunyuan Zheng, Boyao Zhou, Ruizhi Shao, Boning Liu, Shengping Zhang, Liqiang Nie, Yebin Liu 项目地址&#x…

vscode不能进行go跳转

辗转反侧&#xff0c;弄了好久好久终于出山了 总结&#xff1a;跟vscode版本插件有关 老版本vscode DocsTool修改成godoc 新版本vscode go get golang.org/x/tools/goplslatest setting中 "go.useLanguageServer": true, "[go]": {"editor.snipp…

7.无代码爬虫八爪鱼采集器软件——采集规则/项目的创建与网址输入

接上篇 6.零代码网页爬虫软件基础实操——下载与安装八爪鱼采集器 八爪鱼免费爬虫软件下载&#xff1a; 八爪鱼采集器下载 小白数据采集神器​​https://affiliate.bazhuayu.com/retrieve 直接复制粘贴要采集的网站在这里就可以进入采集规则的设计器 自定义任务 通过这个功能…

移动端浏览器调试工具vconsole

方案一&#xff1a;通过CDN地址引入 步骤一&#xff1a;通过CDN地址引入 <script src"https://cdn.bootcss.com/vConsole/3.2.2/vconsole.min.js"></script> 步骤二&#xff1a;实例化 <script> var vConsole new VConsole(); </script&g…

WebSocket——学习

WebSocket WebSocket 的基本概念什么是 WebSocket&#xff1f;WebSocket 的优点 WebSocket 的工作原理握手过程数据传输 WebSocket APIJavaScript WebSocket API WebSocket 服务器端实现使用 Java 实现 WebSocket 服务器使用 Netty 实现 WebSocket 服务器 WebSocket 应用场景总…

力学中应变的度量01——我好几年的疑惑终于有解了

文章目录 0、背景描述1、拉伸比&#xff08;率&#xff09; λ \lambda λ2、应变的引入3、一维应变概念的拓展4 总结 0、背景描述 在学校里的时候&#xff0c;我就一直很好奇应变的定义为何如此花里胡哨、五花八门&#xff0c;各种教材又都只是定义&#xff0c;从来不解释究竟…

Kylin V10 Server 下TongRDS独立哨兵服务配置手册

一、网络架构设计 部署类型 目录 IP Port 中心节点 /opt/rds/pcenter 10.8.3.34 6300 服务节点 /opt/rds/pmemedb 10.8.3.35 TongRDS 协议端口:6200 Redis 仿真端口:6379 哨兵监听端口:26379 10.8.3.36 二、部署服务节点 1.查看操作系统信息 [root@localhost ~]# cat /etc/.…