[Python]unittest-单元测试
目录
unittest的大致构成:
Test Fixture
Test Case-测试用例
Test Suite-测试套件
Test Runner
批量执行脚本
makeSuite()
TestLoader
discover()
用例的执行顺序
忽略用例执行
skip
skipIf
skipUnless
断言
HTML测试报告
错误截图
unittest是python中的单元测试框架
大致作用:
- 提供用例的组织与执行-组织大量的测试用例
- 提供丰富的比较方法-断言
- 提供丰富的日志-总执行时间,失败用例数,成功用例数
unittest的大致构成:
Test Fixture
对一个测试用例环境的搭建与销毁,就是一个Test Fixture(设备,固定之物).通过覆盖setUp()和tearDown()方法来实现
setUp()是测试环境的搭建,比如获取待测浏览器的驱动,或者如果测试中需要访问的数据库,可以在setUp()中建立数据库的连接来进行初始化.
tearDown()进行测试环境的销毁,关闭浏览器,关闭数据库等操作
Test Case-测试用例
一个TestCase的实例就是一个测试用例,测试用例就是一个完整的测试流程,包括测试环境的搭建(setUp),实现测试代码的过程,测试环境的销毁,还原(tearDown())
一个测试用例就是一个完整的测试单元
Test Suite-测试套件
将多个测试用例集合在一起
Test Runner
测试的执行,unittest框架中,通过TextTestRunner类提供的run方法执行testCase或testSuite
感受单元测试
from selenium import webdriver
import unittest
import time
from selenium.webdriver.common.by import Byclass Baidu2(unittest.TestCase):def setUp(self): # 测试环境的构建print("-----setUp-----呜啦啦")self.driver = webdriver.Edge()self.driver.implicitly_wait(30)self.url = "https://www.baidu.com/"self.driver.maximize_window()time.sleep(3)def tearDown(self): # 测试环境的销毁print("-----tearDown-----")self.driver.quit()def test_baidu(self): # 脚本1driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.ID, "kw").send_keys("我的世界")driver.find_element(By.ID, "su").submit()time.sleep(2)print(driver.title)# self.assertNotEqual(driver.title, "百度一下_百度搜索", msg="不相等")# self.assertTrue("beautiful"=="beauty", msg="Not Equal!")time.sleep(2)def test_findB(self): # 脚本2driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.ID, "kw").send_keys("B站")driver.find_element(By.ID, "su").submit()driver.find_element(By.LINK_TEXT, "哔哩哔哩(b站) - 哔哩哔哩 (゜-゜)つロ 干杯~-bi...").click()time.sleep(2)print(driver.title)time.sleep(2)if __name__ == "__main__":# unittest提供的全局main()方法,能够使一个单元测试模块轻松的变成可直接运行的测试脚本# 在main方法中搜索包含在此模块下的,以test命名的测试方法,并执行他们unittest.main()
在Baidu2这个类中,
- setUp + test_baidu + tearDown -> 第1个Test Case
- setUp + test_findB + tearDown -> 第2个Test Case
尝试将代码跑一下,可以发现.在每次执行被测试代码时,setUp与tearDown都会对应的执行一遍.
批量执行脚本
我们把一个web的每个功能模块都分成一个单元测试,那该怎么将每个模块的单元测试一起执行呢.
就要用到我们上面所提到的Test Suite(测试套件),其是一个集合,集合里装载着Test Case(测试用例)
使用测试套件的大致流程为:
- 创建一个测试套件 suite = unittest,TestSuite() #创建一个实例
- 把多个测试用例放入测试套件中 suite.addTest() #添加测试方法
- 执行测试套件 TextTestRunner的run方法启动suite
其中步骤2的addTest一次只能添加一个测试方法
下面介绍批量执行脚本的三种方式
makeSuite()
由unittest框架中提供的makeSuite()方法,能够把测试用例类内的所有测试用例组成一个TestSuite(测试套件),在使用此方法的时候只要把测试类名传入即可.
def createSuite1(): # makeSuitesuite1 = unittest.TestSuite() # 创建一个测试套件# 将MyUnitTest01中的Baidu1类中所有的test方法集合成Suite# 再将集合成的Suite通过addTest方法添加到我们所创建的Suite实例suite1中suite1.addTest(unittest.makeSuite(case.MyUnitTest01.Baidu1)) suite1.addTest(unittest.makeSuite(case.MyUnitTest02.Baidu2))return suite1if __name__ == "__main__":suite = createSuite0()# verbosity表示测试结果的信息复杂度,有0,1,2三个级别,复杂度随级别递增runner = unittest.TextTestRunner(verbosity=2) # 创建TextTestRunner实例runner.run(suite)
TestLoader
使用TestLoader,测试加载器将测试用例批量的加载到测试套件中
需要用到TestLoader的实例方法:loadTestsFromCase
def createSuite2():# 使用TestLoader加载器的实例方法,加载Baidu1类中的测试方法以suite类型返回a = unittest.TestLoader().loadTestsFromTestCase(case.MyUnitTest01.Baidu1)b = unittest.TestLoader().loadTestsFromTestCase(case.MyUnitTest02.Baidu2)# 将加载好的两个suite整合一下thesuite = unittest.TestSuite([a, b])return thesuite
discover()
上面的两种方式都要提前把类给导入
使用discover就不用添加类了,可以直接根据路径来匹配相应的文件
def createSuite3():# 根据所给出的路径,找到匹配正则表达式的文件中的test方法,并将找到的所有test方法以suite的形式返回# top_leve_dir一般设置None,默认值即可discover = unittest.defaultTestLoader.discover('./case', pattern='MyUnit*.py', top_level_dir=None)print(discover)return discover
用例的执行顺序
在unittest框架中默认加载测试用例的顺序是根据ASCII码的顺序
在一个模块中,命为TestA的方法会比TestB的方法优先执行.
而在suite中,会根据addTest()添加的顺序来执行
suite1中含有:
- testB
- testA
suite2中含有:
- test9
- test2
------------------------------
suite.addTest(suite2)
suite.addTest(suite1)
------------------------------
则最终的执行顺序为:
test2->test9->testA->testB
忽略用例执行
在unittest中想要把test方法进行跳过,可以使用unittest提供的skip标签
这里介绍三个标签:
- skip([原因])-无条件跳过标签
- skipIf([条件,原因])-有条件跳过标签
- skipUnless([条件,原因])-有条件跳过标签
skip
@unittest.skip("暂时跳过此方法")
def test_hao(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.LINK_TEXT, "hao123").click()time.sleep(2)
skipIf
比skip多了一个参数,布尔值.
如果为true,则跳过
@unittest.skipIf(2 < 1, "满足条件")
def test_hao(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.LINK_TEXT, "hao123").click()time.sleep(2)
skipUnless
与skipIf差不多,但与其相反
如果为false,则跳过
这里就不举例介绍啦~
断言
unittest框架的目的是对代码进行测试,查看结果是否符合我们的预期.
断言就起到了前面后半句的作用,查看结果是否符合我们的期望.
unittest中:
- 如果某一个case的断言不符合预期测试就会立即停止当前正在执行的case并生成错误信息(并不会影响其他case执行),
- 如果断言通过则继续执行下一个case
在unittest的单元测试库中提供了许多断言的方法,下面是一些常用的方法.
序 号 | 断言方法 | 断言描述 |
1 | assertEqual(arg1, arg2, msg=None) | 验证arg1=arg2,不等则fail |
2 | assertNotEqual(arg1, arg2, msg=None) | 验证arg1 != arg2, 相等则fail |
3 | assertTrue(expr, msg=None) | 验证expr是true,如果为false,则fail |
4 | assertFalse(expr,msg=None) | 验证expr是false,如果为true,则fail |
5 | assertIs(arg1, arg2, msg=None) | 验证arg1、arg2是同一个对象,不是则fail |
6 | assertIsNot(arg1, arg2, msg=None) | 验证arg1、arg2不是同一个对象,是则fail |
7 | assertIsNone(expr, msg=None) | 验证expr是None,不是则fail |
8 | assertIsNotNone(expr, msg=None) | 验证expr不是None,是则fail |
9 | assertIn(arg1, arg2, msg=None) | 验证arg1是arg2的子串,不是则fail |
10 | assertNotIn(arg1, arg2, msg=None) | 断言描述验证arg1不是arg2的子串,是则fail |
11 | assertIsInstance(obj, cls, msg=None) | 验证obj是cls的实例,不是则fail |
12 | assertNotIsInstance(obj, cls,msg=None) | 验证obj不是cls的实例,是则fail |
msg是自己定义给断言如果发生错误显示的信息
HTML测试报告
下载HTMLTestRunner.py,并将其扔到python的lib当中
import unittest
import HTMLTestRunner
import time
import os,sys
if __name__ == "__main__":curpath = sys.path[0] # 获取当前的根目录print(curpath)# 取当前时间now = time.strftime("%Y-%m-%d-%H %M %S", time.localtime(time.time()))# 查看是否有文件夹/resultreport,如果没有则创建if not os.path.exists(curpath + '/resultreport'):os.makedirs(curpath + '/resultreport')# 创建报告文件的名称: 根目录+resultreport(报告文件夹)+时间+html格式文件filename = curpath + '/resultreport/' + now + 'resultreport.html'# 写入创建的html文件中# 打开文件,模式为二进制写wb,文件变量名为fpwith open(filename, 'wb') as fp:runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=u'测试报告',description=u'用例执行情况',verbosity=2)suite = createSuite1()# verbosity表示测试结果的信息复杂度,有0,1,2三个级别,复杂度随级别递增runner.run(suite)
错误截图
在断言没通过的时候,我们可以设置自动截图来查看当时的web情况如何,这样就能方便我们对测试用例的观察
def savescreenshot(driver, file_name):if not os.path.exists('./image'):os.makedirs('./image')cur = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time()))# 截图保存driver.get_screenshot_as_file('./image/'+cur+'-'+file_name)time.sleep(1)
def test_baidu(self):driver = self.driverurl = self.urldriver.get(url)driver.find_element(By.ID, "kw").send_keys("蜡笔小新")driver.find_element(By.ID, "su").submit()time.sleep(2)try:self.assertEquals("haha", "wowo")except:savescreenshot(driver, 'wow.png')time.sleep(2)
相关文章:

[Python]unittest-单元测试
目录 unittest的大致构成: Test Fixture Test Case-测试用例 Test Suite-测试套件 Test Runner 批量执行脚本 makeSuite() TestLoader discover() 用例的执行顺序 忽略用例执行 skip skipIf skipUnless 断言 HTML测试报告 错误截图 unittest是python中的单元测…...

Jetpack:021-Jetpack中的滑动列表
文章目录 1. 概念介绍2. 使用方法2.1 函数参数2.2 列表成员 3. 示例代码4. 内容扩展5. 内容总结 我们在上一章回中介绍了Jetpack中底部导航栏相关的内容,本章回中主要介绍 滑动列表。闲话休提,让我们一起Talk Android Jetpack吧! 1. 概念介绍…...

基于单片机的空气质量检测系统
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 技术交流认准下方 CSDN 官方提供的联系方式 文章目录 概要 一、主要内容二、系统方案设计2.1 系统方案设计2.2 主控制器模块选择 三、 系统软件设计4.1 程序结构分析4.2系统程序…...

论文阅读——InstructGPT
论文:Training_language_models_to_follow_instructions_with_human_feedback.pdf (openai.com) github:GitHub - openai/following-instructions-human-feedback 将语言模型做得更大并不能从本质上使它们更好地遵循用户的意图。例如,大型语…...

【表面缺陷检测】铝型材表面缺陷检测数据集介绍(含xml标签文件)
一、铝型材介绍 铝型材是一种由铝合金材料制成的,具有固定截面形状和尺寸的条形建材。由于其优良的物理性能和广泛的应用领域,铝型材在现代工业和生活中发挥着重要的作用。 1、铝型材的分类 根据截面形状的不同,铝型材可分为角铝、槽铝、工…...
我的学习:从本科到研究生的认识与实践经验总结
学习实践经历 18年 上大学以后,因为对计算机的喜爱和对未知编程技术的好奇和探索,选择了从零开始学习程序设计,经过实践,选择了转专业到计算机科学与技术,开始了我的计算机学习之路。 19年 因为想要拓宽自己的专业能力…...

云游长江大桥,3DCAT实时云渲染助力打造沉浸化数字文旅平台
南京长江大桥是中国第一座自主设计建造的双层公路铁路桥,也是世界上最早的双层公路铁路桥之一。它不仅是一座桥梁,更是一座历史文化的见证者和传承者。它见证了中国人民的智慧和奋斗,承载了中国社会的变迁和发展。 如何让这座不可移动的文物…...

【音视频|PCM】PCM格式详解
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
行为型模式-行为型模式
在模板模式中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。 意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类…...

openpnp - Warning - Unknown firmware
文章目录 openpnp - Warning - Unknown firmware概述笔记https://github.com/openpnp/openpnp/wiki/Motion-Controller-Firmwares备注END openpnp - Warning - Unknown firmware 概述 接上飞达控制板后, 显示未知固件的警告 开始没看源码之前, 总以为是回答的版本号不合适, …...

Android 中如何使用 App Links
1. 简介 什么是 App Links呢?App Links 是 Android 6.0 (API 级别23) 引入的新功能,它是基于 DeepLinking,允许应用自动处理网站的 URL,而无需提示用户启动相应的应用。 例如:如果你在手机浏览器中输入了某个网站&am…...

7 款好用的 PDF 密码删除工具
这是最佳 PDF 密码删除工具列表。该列表包括免费和付费软件。将要在线完成的所有事情都需要密码才能感到安全。数据传输也是如此。大多数数据是通过文件传输的,PDF有自己的标志。PDF是一种灵活的文件格式,因此也可以专业使用。 有多种PDF 编辑器软件&am…...
你一般什么时候会用到GPT?
GPT(Generative Pre-trained Transformer)是一种自然语言处理技术,它在各种领域和场景中都有广泛的应用。下面将详细介绍一些常见的情况,人们在这些情况下通常会使用GPT: 自然语言生成: GPT可以用于生成文本…...

YUV编码格式解析
YUV 颜色编码 YUV 颜色编码采用的是 明亮度 和 色度 来指定像素的颜色。 其中,Y 表示明亮度(Luminance、Luma),而 U 和 V 表示色度(Chrominance、Chroma)。 而色度又定义了颜色的两个方面:色…...
mysql-面试50题-5
一、查询数据 ymysql-面试50题-2-CSDN博客 二、问题 41.按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一 mysql> select student.SId as 学生编号,student.Sname as 学生姓名, -> TIMESTAMPDIFF(YEAR,student.Sage,CURDATE(…...

微服务初始和Nacos安装
一)初始微服务: 微服务是将一个大型的,单一的应用程序拆分成多个小型服务,每一个服务负责于特定的业务功能,并且可以通过网络来和其他服务进行通讯,是一个思想,将一个大的项目拆分成多个小的项目,多个小的项…...

YouTube博主数据信息资源
YouTube博主数据信息资源 🔥我是一位拥有10年编程经验的程序猿,为你带来一个全新的优质资源 🔍您是否在寻找最新、最活跃的YouTube博主数据,以助力你的项目、营销或研究? 我们的数据,您的优势:…...

算法通过村第十七关-贪心|黄金笔记|跳跃游戏
文章目录 前言跳跃游戏最短跳跃游戏总结 前言 提示:曾走过山,走过水,其实只是借助他们走过我的生命;我看着天,看着地,其实只是借助它们确定我的位置;我爱这她,爱着你,其实…...

【精选】VMware部署ESXI6.5 vCenter Server详解
VMware部署ESXI6.5 vCenter Server 一、ESXi主机介绍1、虚拟机的好处2、为什么要使用虚拟机 二、虚拟化服务器概述1、VSphere物理架构2、体系架构3、VMware vSphere 组件 三、ESXi安装环境1、安装步骤2、使用VMware新建ESXi主机3、初始环境安装 四、创建虚拟机五、安装部署VMwa…...

如何借助数据集更好的评估NLP模型的性能?
随着信息时代的迅猛发展,每天有无数文本、声音、图片和视频不断涌入互联网。如何从海量数据中提炼有意义信息成为学术界和工业界迫切需要解决的问题。在此背景下,自然语言处理(NLP)应运而生,成为人工智能领域最为活跃的…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...