unittest单元测试框架使用

news2025/1/23 5:00:15

什么是unittest
这里我们将要用的unittest是python的单元测试框架,它的官网是 25.3. unittest — Unit testing framework — Python 2.7.18 documentation,在这里我们可以得到全面的信息。

当我们写的用例越来越多时,我们就需要考虑用例编写的规范与组织,以便于后期的维护,而unittest正是这样一款工具。我们这里用一个示例来展示用unittest脚本是什么样子的

 1 # -*- coding: utf-8 -*-
 2 from selenium import webdriver
 3 from selenium.webdriver.common.by import By
 4 from selenium.webdriver.common.keys import Keys
 5 from selenium.webdriver.support.ui import Select
 6 from selenium.common.exceptions import NoSuchElementException
 7 from selenium.common.exceptions import NoAlertPresentException
 8 #导入unittest包
 9 import unittest, time, re
10 
11 #SearchTest类继承自unittest.TestCase,表明这是一个测试案例
12 class SearchTest(unittest.TestCase):
13     #setUp用于初始化工作
14     def setUp(self):
15         self.driver = webdriver.Firefox()
16         self.driver.implicitly_wait(30)
17         self.base_url = "https://www.baidu.com/"
18         self.verificationErrors = []
19         self.accept_next_alert = True
20 
21     #以test开头的是我们的测试脚本    
22     def test_search(self):
23         driver = self.driver
24         driver.get(self.base_url + "/")
25         driver.find_element_by_id("kw").click()
26         driver.find_element_by_id("kw").clear()
27         driver.find_element_by_id("kw").send_keys("selenium2")
28         driver.find_element_by_id("su").click()
29 
30     def is_element_present(self, how, what):
31         try: self.driver.find_element(by=how, value=what)
32         except NoSuchElementException as e: return False
33         return True
34 
35     def is_alert_present(self):
36         try: self.driver.switch_to_alert()
37         except NoAlertPresentException as e: return False
38         return True
39 
40     def close_alert_and_get_its_text(self):
41         try:
42             alert = self.driver.switch_to_alert()
43             alert_text = alert.text
44             if self.accept_next_alert:
45                 alert.accept()
46             else:
47                 alert.dismiss()
48             return alert_text
49         finally: self.accept_next_alert = True
50 
51     #在每个测试方法后执行,完成清理工作
52     def tearDown(self):
53         self.driver.quit()
54         self.assertEqual([], self.verificationErrors)
55 
56 #整个测试过程集中在unittest的main()模块中,其默认执行以test开头的方法
57 if __name__ == "__main__":
58     unittest.main()

通过这个我们大概对unittest有个直观的了解了。unittest.main():使用它可以将一个单元测试模块变为可直接运行的测试脚本,main()方法使用TestLoader类来搜索所有包含在该模块中以“test”命名开头的测试方法,并自动执行。执行方法的默认顺序是:根据ASCII码的顺序加载测试用例,数字与字母的顺序为:0-9,A-Z,a-z。所以以A开头的测试用例方法会优先执行,以a开头会后执行。

unittest中的概念
TestCase
一个Testcase的实例就是一个测试用例,测试用例就是一个完整的测试流程,包括初始化setUp、运行run、测试后的还原tearDown。unittest.TestCase类,所有测试用例类继承的基本类。此类提供了很多assert方法用于检查比较,部分如下:

多数方法都可以见其名知其意,使用的门槛很低。

TestSuite
对一个功能的测试往往需要多测试用例的,可以把多的测试用例集合在一起执行,这就是TestSuite的概念。常用addTest()方法将一个测试用例添加到测试套件中。

TextTestRunner
是用来执行测试用例的,其中的run(test)用来执行TestSuite/TestCase。测试的结果会保存在TextTestResult实例中。

TestFixture
测试准备前要做的工作和测试执行完后要做的工作.包括setUp()和tearDown()。通过覆盖TestCase的setUp和tearDown来实现。

知道了这几个主要的概念,我们就可以把上面的脚本中的最后一行unittest.main(),改为以下代码:

1  #构造测试套件
2     suite = unittest.TestSuite()
3     suite.addTest(SearchTest("test_search"))
4     #执行测试
5     runner = unittest.TextTestRunner()
6     runner.run(suite)

执行之后发现和之前用unittest.main()的结果一样。

用例组织
这里我们假设,脚本当中有多个TestCase如test_case1,test_case2…,那我们应该怎样去控制它们的执行顺序呢?

执行测试用例方案一
直接用

unittest.main()
执行,这里它搜索所有以test开头的测试用例方法,按照ASCII的顺序执行多个用例。

执行测试用例方案二
先实例化测试套件,将用例加载进去,再用TextTestRunner去执行用例:

1  suite=unittest.TestSuite()
2  suite.addTest(Test('test_case2'))
3  suite.addTest(Test('test_case1'))
4  runner=unittest.TextTestRunner()
5  runner.run(suite)

执行的顺序是用例的加载顺序,比如这里是先执行2后执行1。

执行测试用例方案三

在方案2中,如果我们有成百上千个用例的话,一个一个add进去,是不太现实的,那么我们可以用defaultTestLoader来加载:

1     test_dir = './'
2     discover = unittest.defaultTestLoader.discover(test_dir, pattern='*test.py')
3     runner = unittest.TextTestRunner()
4     runner.run(discover)

这里用./指定了当前目录,指定了*test.py文件,对其当中的用例进行执行,顺序和方案一相同。

如果这里指定的目录下面有多个经pattern匹配上的.py文件呢?调用discover方法,首先通过test_dir定义查找目录,如果文件名满足定义的pattern,那么我们要用for循环来找出所有被筛选出来的用例,并将其循环加到套件中,主要代码如下:

1  for test_suite in discover:
2         for test_case in test_suite:
3             test_unit.addTests(test_case)

由上面组织用例的方式我们可以知道,在实际的测试用脚本开发中,我们可以在目录下创建xx.py的文件,当用例稳定运行后,可以修改成test_xx.py,以便于添加到测试套件中。注意,文件名的匹配规则,我们可以随便由pattern参数定义。

如果要执行多级目录结构的用例呢?要想被discover读取执行,我们要在目录下加_ init _.py文件

一个例子
下面简单的介绍一个用unittest组织的用例结构,先建立D:\Test_Project目录,下面放上test_case和test_report来分别存放用例和报告。

编写测试用例
在test_case下面编写用例,如下简单的示范了在百度上搜索关键字和点击设置的操作:

 1 文件名为:test_baidu.py
 2 
 3 # -*- coding: utf-8 -*-
 4 from selenium import webdriver
 5 import unittest, time, re
 6 
 7 class MyTest(unittest.TestCase):
 8 
 9     def setUp(self):
10         self.driver = webdriver.Firefox()
11         self.driver.implicitly_wait(30)
12         self.base_url = "https://www.baidu.com"
13         self.accept_next_alert = True
14 
15     def test_02baidu_search(self):
16         u''' 测试百度搜索'''
17         driver = self.driver
18         driver.get(self.base_url + "/")
19         driver.find_element_by_id("kw").click()
20         driver.find_element_by_id("kw").clear()
21         driver.find_element_by_id("kw").send_keys("selenium-test")
22         driver.find_element_by_id("su").click()
23         print("test_baidu__test_02baidu_search")
24 
25     def test_01baidu_setting(self):
26         u''' 测试百度首页设置 '''
27         driver = self.driver
28         driver.get(self.base_url + "/")
29         driver.find_element_by_css_selector("div#u1 a.pf").click()
30         driver.find_element_by_class_name("setpref").click()
31         driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click()
32         driver.switch_to_alert().accept()
33         print("test_baidu__test_01baidu_setting")
34 
35     def tearDown(self):
36         self.driver.close()
37 
38 #从all_test中调用时,可以不要这个
39 if __name__ == "__main__":
40     unittest.main()

为了显示出组织测试用例的效果,我们将此文件再复制一份,把文件名和方法名等修改一下:

 1 文件名为:test_baidu2.py
 2 
 3 # -*- coding: utf-8 -*-
 4 from selenium import webdriver
 5 import unittest, time, re
 6 
 7 class MyTest(unittest.TestCase):
 8     u''' 测试baidu的第二个用例'''
 9     def setUp(self):
10         self.driver = webdriver.Firefox()
11         self.driver.implicitly_wait(30)
12         self.base_url = "https://www.baidu.com"
13         self.accept_next_alert = True
14 
15     def test_02baidu_search(self):
16         u''' 测试baidu的第二个用例的test_02baidu_search'''
17         driver = self.driver
18         driver.get(self.base_url + "/")
19         driver.find_element_by_id("kw").click()
20         driver.find_element_by_id("kw").clear()
21         driver.find_element_by_id("kw").send_keys("selenium-test")
22         driver.find_element_by_id("su").click()
23         print("test_baidu2__test_02baidu_search")
24 
25 
26     def test_01baidu_setting(self):
27         u''' 测试baidu的第二个用例的test_01baidu_setting'''
28         driver = self.driver
29         driver.get(self.base_url + "/")
30         driver.find_element_by_css_selector("div#u1 a.pf").click()
31         driver.find_element_by_class_name("setpref").click()                        driver.find_element_by_css_selector("div#gxszButton>a.prefpanelgo").click()
32         driver.switch_to_alert().accept()
33         print("test_baidu2__test_01baidu_setting")
34 
35     def tearDown(self):
36         self.driver.close()
37 
38 if __name__ == "__main__":
39     unittest.main()
美化报告样式和发送结果邮件

上面我们写了 两个测试用例作为示例,我们也可以添加更多的进去。接着我们使用HTMLTestRunner这个开源模块来美化测试报告。然后,我们可以在代码中写上运行完成之后自动发送测试邮件出来,便于我们查看。请参看以下代码:

 1 #coding=utf-8
 2 import unittest
 3 import smtplib
 4 from email.mime.text import MIMEText
 5 from email.header import Header
 6 import time
 7 import HTMLTestRunner
 8 from email.mime.application import MIMEApplication
 9 
10 #---发送邮件---
11 def send_email(report_file):
12     sender = "XXXXXX@qq.com"
13     receiver = "XXXXXX@qq.com"
14     smtpserver = "smtp.qq.com"
15     #发送邮箱的账号密码,此处使用的是qq邮箱和第三方登录的授权码
16     username = "XXXXXX@qq.com"
17     password = "gfomcomojtuudijc"
18 
19     #定义邮件正文
20     file = open(report_file,"rb")
21     mail_body = file.read()
22     file.close()
23 
24     msg = MIMEText(mail_body, _subtype="html", _charset="utf-8")
25     msg["Subject"] = u"自动化测试报告"
26 
27     smtp = smtplib.SMTP_SSL("smtp.qq.com")
28     smtp.login(username, password)
29     smtp.sendmail(sender, receiver, msg.as_string())
30     smtp.quit()
31     print("Email has send out !")
32 
33 #---将用例添加到测试套件---
34 def creatsuite():
35     testunit=unittest.TestSuite()
36     test_dir = "D:\\Test_Project\\test_case"
37     discover = unittest.defaultTestLoader.discover(test_dir, pattern="test*.py",
38                                                  top_level_dir = None)
39     for test_suite in discover:
40         for test_case in test_suite:
41             testunit.addTest(test_case)
42             print (testunit)
43     return testunit
44 
45 if __name__ == "__main__":
46     current_time = time.strftime("%Y-%m-%d-%H-%M")
47     report_dir = "D:\\Test_Project\\test_report\\"
48     report_file = report_dir + current_time + "-Test_Result.html"
49     report_stream = open(report_file, "wb")
50     # runner = unittest.TextTestRunner()
51     # 注意HTMLTestRunner只支持python2
52     runner = HTMLTestRunner.HTMLTestRunner(stream=report_stream,title=u"自动化测试报告",  description=u"用例执行情况如下:")
53     runner.run(creatsuite())
54     report_stream.close()
55     send_email(report_file)

在上面的代码中我们使用了runner = HTMLTestRunner.HTMLTestRunner()方法来代替runner = unittest.TextTestRunner(),是为了使用HTMLTestRunner这个模块来美化和输出美观的报告。然后调用方法来发送邮件。运行此文件后,可以得到以下输出的报告:

可以看见使用这个可以清晰的看到用例的执行情况, 也便于查看失败用例的原因去调试它,同时在们输入的收件箱也会收到一份通知邮件,我们可以将此输出报告添加到正文或附件中,以便于查看

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

文档获取方式:

这份文档,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!

以上均可以分享,只需要你搜索vx公众号:程序员雨果,即可免费领取

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

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

相关文章

油猴(篡改猴)学习记录

第一个Hello World 注意点:默认只匹配了http网站,如果需要https网站,需要自己添加match https://*/*代码如下 这样子访问任意网站就可以输出Hello World // UserScript // name 第一个脚本 // namespace http://tampermonkey.net/ // version 0.1 // descri…

2023/9/26 -- ARM

【计算机相关理论】 1.计算机的组成 输入设备、输出设备、存储器、运算器、控制器 1.输入设备:将编写好的软件代码以及相关的数据输送到计算机中。转换成计算机可以识别、存储 和处理的数据。 例如:鼠标、键盘、复印机、传感器 2.输出设备&a…

结构型设计模式——组合模式

摘要 组合模式(composite pattern): 允许你将对象组合成树形结构来表现"整体/部分"层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合。 一、组合模式的意图 将对象组合成树形结构来表示“整体/部分”层次关系,允许用户以相同的方式处理单独…

【Java SE】Lambda表达式

目录 ♫什么是Lambda表达式 ♫Lambda表达式的语法 ♫函数式接口 ♫Lambda表达式的使用 ♫变量捕获 ♫ Lambda表达式在集合中的使用 ♪Collection的foreach(): ♪List的sort(): ♪Map的foreach() ♫什么是Lambda表达式 Lambda 表达式是 Java SE 8中一个…

Socks5代理IP是什么?有什么优点及如何使用?

随着网络威胁和数据泄露的数量不断增加,在浏览互联网时保护个人信息并保持匿名变得至关重要。实现此目的的一种有效方法是使用Socks5代理IP。如今Socks5代理被广泛应用于跨境电商/社媒平台、SEO业务、网络抓取等领域,在这篇文章中,我们将讨论…

服务好的CMDB运维管理平台的服务优势

随着公司信息化程度的不断提高,IT基础设施也越来越复杂。为了方便这些基础设施的管理和维护,CMDB(配置管理数据库)运维管理平台应运而生。本文将介绍一个服务好、价格实惠的CMDB运维管理平台,帮助读者更好地了解和使用…

扫地机器人经营商城小程序的作用是什么

扫地机器人对人们生活大有帮助,近些年也有不少企业开创品牌,在电商平台每年销量也非常高,同行竞争激烈及私域化程度加深情况下,虽然第三方平台或线下方式也有生意,但互联网电商发展也为商家们带来了诸多痛点。 那么通…

CRM软件系统如何选择部署方式

CRM的部署方式是选型的主要衡量标准,云部署CRM系统指应用程序在技术商的公有云上,本地化部署将应用程序架设在本地基础设施上,享有应用的所有权。那么CRM系统选择云部署还是本地化部署? 1.云部署CRM系统性价比更高 我们知道本地…

HTTP 跨域名请求(CORS)

同源策略 出于安全考虑,浏览器会限制脚本中发起的跨域请求。比如,使用 XMLHttpRequest 对象和Fetch发起 HTTP 请求就必须遵守同源策略。 具体而言,Web 应用程序通过 XMLHttpRequest 对象或Fetch能且只能向同域名的资源发起 HTTP 请求&#x…

python通过csv库处理CSV文件

CSV库还有其他处理CSV的方法,这里只是介绍几个常用的,后面如果用到别的会进行更新 目录 1 生成一个新的csv文件,并向其中写一点东西 2 单纯往里面写几行 3 读取csv文件 1 生成一个新的csv文件,并向其中写一点东西 import…

工作中Git管理项目和常见问题处理

工作中Git管理项目和常见问题处理 Git仓库的管理方式为什么会出现无法push到线上处理方法 Git仓库的管理方式 共用统一仓库,不同开发人员使用不同分支 步骤 下载代码 git clone <url>查看分支 git branch创建并切换分支 git checkout -b dev分支名称保持和远程分支一…

crypto:Rabbit

题目 根据题目下载压缩包后解压&#xff0c;可得到文本提示 知识盲区&#xff0c;去了解一下Rabbit加密的密文特征 AES、DES、RC4、Rabbit、Triple DES&#xff08;3DES&#xff09; 这些算法都可以引入密钥&#xff0c;密文特征与Base64类似&#xff0c;明显区别是秘文里​​…

使用U3D、pico开发VR(一)——将unity的场景在设备中呈现

最近srtp项目在赶进度&#xff0c;自己之前是在电脑端进行的开发。但是项目是VR端&#xff0c;因此需要重新学习&#xff0c;在此记录一下自己的学习经历。 首先&#xff0c;如何将unity的场景在自己的眼镜中进行呈现呢&#xff1f; 对此&#xff0c;我也找了很多教程&#xff…

关于redis的一主三从三哨兵的实现

关于redis的一主三从三哨兵的实现 前言docker相关的docker-compose.ymlsentinel.conf重点解释一下上面的语句 前言 当谈到数据库管理系统时&#xff0c;Redis就像是那个充满魔法的巫师&#xff0c;能够让你的应用程序变得更快、更可靠&#xff0c;就像是施了魔法一样。而今天&…

HONEYWELL 05704-A-0145

HONEYWELL 05704-A-0145电源模块通常用于为其他设备或系统提供电力供应&#xff0c;以确保它们正常运行。HONEYWELL 05704-A-0145电源模块的应用领域可以非常广泛&#xff0c;包括但不限于以下几个领域&#xff1a; 工业自动化&#xff1a;HONEYWELL 05704-A-0145电源模块用于工…

NEON优化:性能优化经验总结

NEON优化&#xff1a;性能优化经验总结 1. 什么是 NEONArm Adv SIMD 历史 2. 寄存器3. NEON 命名方式4. 优化技巧 Reference: NEON优化&#xff1a;性能优化经验总结NEON官方内联函数Arm NEON programming quick referenceLearn the architecture - Neon programmers’ guide …

Windows server 2022(2023年9月 映像更新 - 20348.1970)安装测试

本文记录了Windows server 2022(2023年9月 映像更新 - 20348.1970)的安装测试过程。 一、检查ISO 简体中文 - Windows Server 2022&#xff08;2023年9月更新 - 20348.1970&#xff09; 内含版本&#xff08;Windows Server 2022 Standard、Windows Server 2022 Standard (D…

期权定价模型系列【6】:欧式期权、百慕大期权、美式期权的定价模型与对比【蒙特卡洛模拟、二叉树模型】

期权定价模型系列第6篇文章 1. 前言 对于欧式期权&#xff0c;最常用的是BS模型&#xff0c;此外&#xff0c;也可也用蒙特卡洛模拟方法求解欧式期权的价格。当然&#xff0c;对于美式期权&#xff0c;也同样可以用蒙特卡洛模拟方法来求解&#xff0c;一般对美式更多用的是二叉…

Kubernetes(K8s):未来云原生应用的引擎

文章目录 Kubernetes的核心概念和架构为什么K8s是构建云原生应用的首选工具&#xff1f;云原生应用的好处和挑战容器编排的重要性&#xff1a;Docker和KubernetesKubernetes生态系统&#xff1a;核心组件和附加工具实际应用&#xff1a;企业如何在生产环境中使用K8s未来展望&am…

基于大语言模型扬长避短架构服务

秘诀&#xff1a; 扬泛化之长&#xff0c; 避时延之短