python模块详解 | unittest(单元测试框架)(持续更新中)
目录:
why unittest?
- unittest的四个重要概念
- 加载测试用例的三个方法
- 自动加载测试用例
- 忽略测试和预期失败
- 生成html测试报告
why unittest?
简介:
Unittest是python自带的单元测试框架,设计灵感来自Java中的Juint,具有和Junit类似的结构
优点:
- 不仅可以用于单元测试,还适用于自动化测试用例的开发与执行
- 可阻止执行测试用例
- 断言预期结果
- 批量执行测试用例
- 最终可生成测试结果
unittest四个重要的概念:
1.1、测试用例(TestCase)
- 测试用例是单元测试中最基本的组成单元
- Unittest使用TestCase类(可自行命名)来表示测试用例,所有执行测试的类继承自该类
- 一个测试用例包括:测试固件、具体测试业务的函数或者方法
- 测试用例中,测试固件可以省略,但是至少有一个以test开头的测试函数testXXX
- Unittest会自动化识别test开头的函数为测试代码,所有的测试函数都要以test开头(如testXXX,注意test是小写),如果函数不以test开头,则Unittest不会执行函数
- 例:
import unittest
# 自定义一个测试实例类,传入unittest的测试实例类TestCase
class TestBaidu(unittest.TestCase):
driver=webdriver.Chrome()
driver.get(bd_url)
def test_1(self):
print(1)
# 断言等于
self.assertEqual(self.driver.title,u'百度一下,你就知道')
def test_2(self):
print(2)
# 断言为真
self.assertTrue(self.driver.find_element_by_id('kw').is_enabled())
if __name__ == '__main__':
unittest.main()
1.2、测试固件(setUp、tearDown)
- setUp()
- 在每个测试用例运行前运行,该方法用于进行测试前的初始化工作
- 一条用例执行一次,若N次用例就执行N次,根据用例的数量来定
- tearDown()
- 在每个测试用例运行后运行,该方法用于执行测试后的清除工作(不管是否执行成功)
- setUp()
- 例:
import unittest
# 自定义一个测试实例类,传入unittest的测试实例类TestCase
class TestBaidu(unittest.TestCase):
def setUp(self):
print('一个测试用例前的初始化工作...')
self.driver = webdriver.Chrome()
self.driver.get(bd_url)
def tearDown(self):
print('一个测试用例前的清除工作...')
self.driver.quit()
def test_1(self):
print(1)
# 断言等于
self.assertEqual(self.driver.title,u'百度一下,你就知道')
def test_2(self):
print(2)
# 断言为真
self.assertTrue(self.driver.find_element_by_id('kw').is_enabled())ps:1、如果setUp()执行成功(没有异常),那么无论测试方法是否通过,tearDown()都会被执行;
2、setUp()和tearDown()方法存在弊端,例如每次执行用例是都会重新打开,导致时间浪费,因此可以使用下面两种方法;
- setUpClass()
- 所有用例执行前只运行一次,在所有用例执行之前准备一次环境
- tearDownClass()
- 所有用例执行完后只运行一次,在所有用例执行结束后再清理环境
- 例:
import unittest
# 自定义一个测试实例类,传入unittest的测试实例类TestCase
class TestBaidu(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
print('所有测试用例前的准备工作...')
cls.driver=webdriver.Chrome()
cls.driver.get(bd_url)
@classmethod
def tearDownClass(cls) -> None:
print('所有测试用例执行后的清理工作...')
cls.driver.quit()
def setUp(self):
print('一个测试用例前的初始化工作...')
self.driver = webdriver.Chrome()
self.driver.get(bd_url)
def tearDown(self):
print('一个测试用例前的清除工作...')
self.driver.quit()
def test_1(self):
print(1)
# 断言等于
self.assertEqual(self.driver.title,u'百度一下,你就知道')
def test_2(self):
print(2)
# 断言为真
self.assertTrue(self.driver.find_element_by_id('kw').is_enabled())
if __name__ == '__main__':
unittest.main()
- 例:
1.3、测试套件(TestSuite)
- 完整的单元测试很少只执行一个测试用例,开发人员通常都需要编写多个测试用例才能对某一软件功能进行完整的测试
- 测试套件是多个测试用例或者测试用例集合聚合组织起来的集合,是针对被测程序对应的功能和模块创建的一组测试,测试套件内的测试用例将一起执行,即批量执行一个测试套件内所有的测试用例
- 在unittest中,测试套件主要通过unittest.TestSuite()类直接构建,或者通过TestSuite实例的addTests、addTest方法构建
- 例:
if __name__ == '__main__':
# 测试套件写法1
suite1=unittest.TestSuite(map(TestBaidu,['test_1','test_2']))
# 测试套件写法2
suite2=unittest.TestSuite()
suite2.addTests(map(TestBaidu,['test_1','test_2']))
# 测试套件写法3
suite3 = unittest.TestSuite()
suite3.addTest(TestBaidu('test_1'))
suite3.addTest(TestBaidu('test_2'))
1.4、测试执行器(TextTestRunner)
- 测试执行器是一个组织安排测试脚本执行活动的组件,即用来加载测试用例并执行用例,且提供测试输出的一个组件
- 测试执行器负责测试执行调试并且通过一些图形界面,文本界面或者返回一些特殊的值来展示测试脚本的测试结果给用户
- 测试的执行也是单元测试中非常重要的一个概念,一般单元测试框架中都会提供丰富的执行策略和执行结果
- 测试执行器可以加载测试用例或者测试套件来执行测试任务,即利用猜测是执行器加载的测试用例,可以是单个测试用例,也可以是套件
- 例:
#测试执行器
runner=unittest.TextTestRunner()
runner.run(suite)
加载测试用例的三个方法
2.1 unittest.main()
- 两个参数(exit、verbosity):
exit | exit=False表示中间有用例失败也继续执行 |
verbosity |
若verbosity=0,则输出简单报告,获得总的测试用例数和总的结果。比如,总共100个,失败20 成功80; 若verbosity=1,则输出一般报告,每个成功的用例前面有个“.”,每个失败的用例前面有个“F”,默认值为1; 若verbosity=2,则输出详细报告,测试结果会显示每个测试用力的所有相关的信息; 添加参数--quite,等效于verbosity=0; 添加参数--version,等效于verbosity=2; 不增加,等效于verbosity=1; |
- 例:
if __name__ == '__main__':
unittest.main()
- 例:
2.2 测试套件(TestSuite)
- 步骤:
- 创建测试套件
- 构建测试套件
- 使用测试执行器运行测试套件
- 参考:测试套件
2.3 unittest.TestLoader()
- 步骤:
- 加载测试用例:unittest.Loader()
- 添加测试用例到测试套件
- 使用测试执行器运行测试套件
- 实例化runner类:runner=unittest.TextTestRunner()
- 运行测试:runner.run(suite)
- unittest.TestLoader()加载测试用例的方法:
TestLoader().loadTestsFromTestCase(testCaseClass) | testCaseClass必须是TestCase的子类(或者孙类) |
TestLoader().loadTestsFromModule(module,pattern=None) | module是测试用例所在的模块 |
TestLoader().loadTestsFromName(name,module=None) | name是测试用例的方法名,使用格式是“module.class.method” |
TestLoader().loadTestsFromNames(names,module=None) |
- 方法图示:
- 例:
#加载测试用例
test_case=unittest.TestLoader().loadTestsFromTestCase(BaiduTest)
#加载测试套件
suite=unittest.TestSuite()
suite.addTest(test_case)
#执行测试
runner=unittest.TextTestRunner()
runner.run(suite)
自动加载测试用例
简介:
unittest的TestLoader类提供了一个discover方法,以递归的方式,实现从指定顶层目录、模块找到指定目录里的测试用例文件,并将查找到的测试用例文件组装到测试套件中,然后运行。
- discover(start_dir,pattern,top_level_dirt):
start_dir | 被测试的模块或测试用例所在的目录 |
pattern | 用例文件名的匹配原则(默认匹配test*.py) |
top_level_dir | 测试模块的顶层目录,如果没有顶层目录,默认为None |
- 步骤:
- 获取目录下满足条件的所有包含测试用例的py文件,构造测试集
- 实例化测试执行器,运行测试用例
- 例:
#discover()方法加载所有测试用例进行测试
discover = unittest.TestLoader.discover(start_dir='./',
pattern='*.py',
top_level_dir=None)
#实例化测试执行器
runner = unittest.TextTestRunner()
#运行测试用例
runner.run(discover)
忽略测试和预期失败
@unittest.skip(reason) | 无条件跳过被装饰的测试方法,并说明跳过测试的原因;miaosureson:理由,描述为什么跳过测试用例 |
@unittest.skipIf(condition,reason) | 条件为真时,跳过被装饰的测试用例,并说明跳过测试的原因 |
@unittest.skipUnless(condition,reason) | 除非条件为真,否则跳过被装饰的测试用例;即条件为假时,跳过装饰的测试用例,并说明跳过测试的原因 |
@unittest.expectedFailure | 将测试用例标记为“预期失败” |
@unittest.SkipTest(reason) | 当需要跳过一个测试方法时,可以在测试方法或setup()中调用该方法 |
例:
class BaiduTest2(unittest.TestCase):
def setUp(self) -> None:
print('\n测试开始...')
self.driver=webdriver.Firefox()
self.driver.get(bd_url)
def tearDown(self) -> None:
self.driver.quit()
print('测试结束...')
@unittest.skip('跳过此测试,没有为什么')
def test1(self):
self.driver.find_element_by_id('kw').send_keys(keywords[0])
self.driver.find_element_by_id('su').click()
time.sleep(1)
print(self.driver.title)
self.assertEqual(self.driver.title,'Python_百度搜索')
@unittest.skipIf(condition=1<2,reason='又跳过了,因为2大于1')
def test2(self):
self.driver.find_element_by_id('kw').send_keys(keywords[1])
self.driver.find_element_by_id('su').click()
time.sleep(1)
print(self.driver.title)
self.assertEqual(self.driver.title,'Selenium_百度搜索')
@unittest.skipUnless(condition=1<2,reason='2大于1,执行此测试')
def test3(self):
self.driver.find_element_by_id('kw').send_keys(keywords[2])
self.driver.find_element_by_id('su').click()
time.sleep(1)
print(self.driver.title)
self.assertEqual(self.driver.title,'TestSuite_百度搜索')
html测试报告
5.1、配置HTMLTestRunner
- 工具:HTMLTestRunner
- 下载:http://tungwaiyip.info/software/HTMLTestRunner.html
- 安装:
Windows:将HTMLTestRunner.py文件移动到python安装目录下的lib文件夹内
Linux:将文件移动到安装目录下的第三方包文件夹(dist-packages)目录下
- 修改HTMLTestRunner.py文件,原因:由于下载的文件是基于python2语法,若使用的是python3,则需要修改
行数 | 修改前 | 修改后 |
94 |
import StringIO |
import io |
539 |
self.outputBuffer = StringIO.StringIO() |
self.outputBuffer = io.StringIO() |
631 |
print >>sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime) |
print(sys.stderr, '\nTime Elapsed: %s' % (self.stopTime-self.startTime)) |
642 |
if not rmap.has_key(cls): |
if not cls in rmap: |
766 |
uo = o.decode('latin-1') |
uo = e |
768 |
uo = o |
uo = o.decode('utf-8') |
772 |
ue = e.decode('latin-1') |
ue = e |
774 |
ue = e |
ue = e.decode('utf-8') |
5.2、生成测试报告
配置htmltestrunner成功后,在测试代码中导入HTMLTestRunner模块,并在测试文件中加入下述代码即可
python模块详解 | unittest(单元测试框架)(持续更新中)的更多相关文章
- python模块详解 | selenium(持续更新中)
目录: 关于selenium Selenium 安装Selenium 安装浏览器驱动 配置环境变量 selenium方法详解 定位元素 元素操作 浏览器操作 鼠标事件 浏览器事件 设置元素等待 多表单 ...
- Python 模块详解及import本质
同在当前目录下的模块和包导入 模块定义 本质就是.py结尾的python文件. 用来从逻辑上组织python代码(变量,函数,类,逻辑) 文件名: test.py; 对应的模块名 : test 模块 ...
- python模块详解 random os
random模块 常用方法 random.random() 随机产生一个小于1的浮点数 import random print(random.random()) #0.4153761818276826 ...
- python爬虫scrapy项目详解(关注、持续更新)
python爬虫scrapy项目(一) 爬取目标:腾讯招聘网站(起始url:https://hr.tencent.com/position.php?keywords=&tid=0&st ...
- python模块详解
什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的代码(.p ...
- python模块详解 sys shutil
sys模块 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sy ...
- python模块详解 | shutil
简介: shutil是python的一个内置模块,提供了许多关于文件和文件集合的高级操作,特别提供文件夹与文件操作.归档操作了支持文件复制和删除的功能. 文件夹与文件操作: copyfileobj(f ...
- 小白的Python之路 day5 python模块详解及import本质
一.定义 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能) 本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test) 包:用来从逻辑上组织模块 ...
- Python模块详解以及import本质,获得文件当前路径os.path.abspath,获得文件的父目录os.path.dirname,放到系统变量的第一位sys.path.insert(0,x)
模块介绍 1.定义: 模块:用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test) 包:用来从逻 ...
随机推荐
- 得物(毒)APP,8位抽奖码需求,这不就是产品给我留的数学作业!
作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...
- Java8新特性探索之新日期时间库
一.为什么引入新的日期时间库 Java对日期,日历及时间的处理一直以来都饱受诟病,尤其是它决定将java.util.Date定义为可修改的以及将SimpleDateFormat实现成非线程安全的. 关 ...
- Idea中Web项目Jsp文件找不到类解决方法
在src下创建package,java代码放到包中,编译时才能在WEB-INFO的classes文件夹中生成可识别的class文件 https://blog.csdn.net/youwanname/a ...
- [日常摸鱼]bzoj1257余数之和
题意:输入$k,n$,求$\sum_{i=1}^n k \mod i$ $k \mod i=k-i*\lfloor \frac{k}{i} \rfloor $,$n$个$k$直接求和,后面那个东西像比 ...
- setfacl命令的基本用法
setfacl命令的基本用法 1.setfacl的用途 setfacl命令可以用来细分linux下的文件权限. chmod命令可以把文件权限分为u,g,o三个组,而setfacl可以对每一个文件或目录 ...
- Clickhouse的特点
1.为什么会有Clickhouse? 实时数据分析数据库 俄罗斯的谷歌开发的. 2.Clickhouse的优点. 真正的面向列的 DBMS ClickHouse 是一个 DBMS,而不是一个单一的数据 ...
- SSRF深入学习
爆出来的直接关于SSRF的漏洞有俩,①是weblogic,②是discuzz SSRF漏洞最主要的部分并不是SSRF 探测内网,而是可以写shell,反弹shell,虽然很多厂家把它归为低危漏洞,仔细 ...
- H3C路由器配置示列一
说明: 如上图所示,192.168.0.0网段是总公司的网络,192.168.3.0和192.168.4.0网段是当前自己分公司的网络,且192.168.3.0是内网不能访问互联网,192.168.4 ...
- mysql数据安全之利用二进制日志mysqlbinlog恢复数据
mysql数据安全之利用二进制日志mysqlbinlog恢复数据 简介:如何利用二进制日志来恢复数据 查看二进制日志文件的内容报错: [root@xdclass-public log_bin]# my ...
- NIO 的工作方式
NIO 的工作方式 BIO 带来的挑战 BIO : BIO 通信模型,通常由一个独立的 Acceptor 线程负责监听客户端的连接,接受到请求之后,为每个客户端创建一个新的线程进行链路处理,处理完成之 ...