[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)应运而生,成为人工智能领域最为活跃的…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
