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

如何用多线程执行 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 多线程执行测试用例 就给大家分享到这里了!喜欢的可以关注我哟,关注我每天给大家带来不同的惊喜。

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

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

相关文章:

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

前言 使用python做过自动化测试的小伙伴,想必都知道unittest和pytest这两个单元测试框架,其中unittest是python的官方库,功能相对于pytest来要逊色不少,但是uniitest使用上手简单,也受到的很多的小伙伴喜爱。一直以来都…...

Ascend310 EP模式下容器内进行推理测试

EP模式下容器内进行推理测试 本文的软硬件环境如下: 机器:x86台式机一台 OS: 5.4.0-26-generic Ubuntu20.04 LTS 推理卡:DLAP200-HP-2(凌华基于atlas200模块打造的两模块推理卡) 1. 推理卡固件和驱动安…...

(el-Transfer)操作(不使用 ts):Element-plus 中 Select 组件动态设置 options 值需求的解决过程

Ⅰ、Element-plus 提供的Select选择器组件与想要目标情况的对比&#xff1a; 1、Element-plus 提供Select组件情况&#xff1a; 其一、Element-ui 自提供的Select代码情况为(示例的代码)&#xff1a; // Element-plus 提供的组件代码: <template><div class"f…...

Java基础之Math与Array类与System

文章目录 一、Math.random&#xff08;&#xff09;二、Arrays.binarySearch()三、asList&#xff08;&#xff09;四、System tip&#xff1a;以下是正文部分 一、Math.random&#xff08;&#xff09; a < num < b int num (int)(Math.random() * (b - a 1)) a二、…...

警告:Hydration attribute mismatch on Note: this mismatch is check-only.(水合不匹配)

vue3Nuxt3运行代码是提示如下警告 [Vue warn]: Hydration attribute mismatch on <ul id​"sub_menu_5_$$_sub1-popup" class​"ant-menu ant-menu-sub ant-menu-inline" data-menu-list​"true" style​"display:​none;​">​…...

【机器学习】CART决策树算法的核心思想及其大数据时代银行贷款参考案例——机器认知外界的重要算法

目录 引言 概述 CART决策树的特点 核心思想 减少不确定性的指标 基尼系数&#xff08;Gini Index&#xff09; 分类错误率 熵 银行实例 背景 数据准备 模型构建 模型评估与优化 应用与结果 代码示例 ✈✈✈✈引言✈✈✈✈ CART算法既可以用于分类问题&#xff0…...

编程软件是由什么编程的

编程软件是由什么编程的 在数字化的世界里&#xff0c;编程软件作为构建数字生态的基石&#xff0c;其背后所蕴含的奥秘往往令人感到困惑。那么&#xff0c;这些编程软件究竟是由什么编程的呢&#xff1f;这背后隐藏着怎样的逻辑与技术&#xff1f;接下来&#xff0c;我们将从…...

如何查看自己本地ip

1.winR 2.cmd 3.ipconfig...

高考分数限制下,选好专业还是选好学校?

高考分数限制下&#xff0c;选好专业还是选好学校&#xff1f; 高考作为每年一度的盛大考试&#xff0c;不仅关乎学生们的未来&#xff0c;更承载了家庭的期望。2004年高考刚刚结束&#xff0c;许多考生和家长已经开始为填报志愿而焦虑。选好学校和专业&#xff0c;直接关系到…...

Django学习(2)项目实战

1、环境及简介 前端开发&#xff1a;HTML、CSS、JavaScript 后端开发&#xff1a;Java、PHP、Python、GO 数据库&#xff1a;MySQL、MSSQL、Oracle、Redis 安装Django pip install Django 或 下载.whl后 pip install D&#xff1a;\xxx.whl 创建Django项目 File--New Projec…...

pdf格式转成jpg图片,pdf格式如何转jpg

pdf转图片的方法&#xff0c;对于许多人来说可能是一个稍显陌生的操作。然而&#xff0c;在日常生活和工作中&#xff0c;我们有时确实需要将pdf文件转换为图片格式&#xff0c;以便于在特定的场合或平台上进行分享、展示或编辑。以下&#xff0c;我们将详细介绍一个pdf转成图片…...

Java的三个接口Comparable,Comparator,Cloneable(浅拷贝与深拷贝)

Comparable 当我们要进行对象的比较的时候&#xff0c;我们是不能直接用>、< 这些符号直接进行比较的。 由于这是引用类型变量也是自定义类型变量&#xff0c;直接进行比较的时候&#xff0c;我们是通过对象的地址进行比较的&#xff0c;我们可以使用、! 进行两个对象的…...

pytorch学习笔记7

getitem在进行索引取值的时候自动调用,也是一个魔法方法,就像列表索引取值那样,一个意思 import torchvision from torch.utils.data import DataLoaderdata_transformtorchvision.transforms.Compose([torchvision.transforms.ToTensor()] ) test_datatorchvision.datasets.C…...

LeetCode热题3.无重复的最长字串

前言: 经过前序的一系列数据结构和算法学习后&#xff0c;开始用leetCode热题练练手。 . - 力扣&#xff08;LeetCode&#xff09; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的最长子串的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为…...

Python武器库开发-武器库篇之SQL注入扫描器(五十九)

Python武器库开发-武器库篇之SQL注入扫描器(五十九) SQL注入漏洞简介以及危害 SQL注入漏洞是一种常见的Web应用程序漏洞&#xff0c;攻击者可以利用该漏洞在应用程序的数据库中执行恶意的SQL查询或指令。这可能导致数据泄露、数据损坏、应用程序崩溃或未经授权的访问。 SQL注…...

图说设计模式:单例模式

更多C学习笔记&#xff0c;关注 wx公众号&#xff1a;cpp读书笔记 5. 单例模式 单例模式 模式动机模式定义模式结构时序图代码分析模式分析实例优点缺点适用环境模式应用模式扩展总结 5.1. 模式动机 对于系统中的某些类来说&#xff0c;只有一个实例很重要&#xff0c;例如…...

探索设计模式——单例模式详解

前言&#xff1a;设计模式的作用主要是为了——利用设计方式的重用来自动地提高代码的重新利用、提高代码的灵活性、节省时间&#xff0c; 提高开发效率、低耦合&#xff0c;封装特性显著&#xff0c; 接口预留有利于扩展。 设计模式的种类有很多种&#xff0c;本篇内容主要讲解…...

建筑垃圾/城市固废倾倒转移乱象:EasyCVR+AI智能视频监控方案助力城市环保监管

近日有新闻记者报道&#xff0c;中央生态环境保护督察组在上海、浙江、江西、湖北、湖南、重庆、云南7省市督察发现&#xff0c;一些地方建筑垃圾处置工作存在明显短板&#xff0c;乱堆乱倒问题时有发生&#xff0c;比如&#xff0c;江西湘东区在杨家田地块违规设置弃土场&…...

C的I/O操作

目录 引言 一、文件与目录操作 1. 打开与关闭文件 2. 文件读写操作 3. 文件定位与错误处理 二、字符流与字节流 1. 字符流处理 2. 字节流处理 三、序列化与反序列化 1. 序列化 2. 反序列化 四、新的I/O&#xff08;NIO&#xff09; 表格总结 文件与目录操作 字符…...

Android Audio实战——声道信息回调(五)

在前面的 AudioTrack 构造中,我们传入了音频的声道信息,这一节我们就来详细介绍一下声道的配置信息。 一、声道介绍 音频中的声道配置从单声道到双声道(立体声)、再到多声道系统(如5.1和7.1),代表了声音录制和回放技术的发展,旨在提供越来越丰富和沉浸式的听觉体验。 …...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制&#xff1a; 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程&#xff0c;创建出来的进程就是子进程&#xff0c;原来的进程为父进程。…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...