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) 包:用来从逻 ...
随机推荐
- Springboot mini - Solon详解(三)- Solon的web开发
Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...
- gunicorn简单配置
Gunicorn配置 # -*- coding: utf-8 -*- import os from multiprocessing import cpu_count bind = "127. ...
- C# 海量数据瞬间插入到数据库的方法
C# 海量数据瞬间插入到数据库的方法 当我们在数据库中进行大量的数据追加时,是不是经常因为数据量过大而苦恼呢?而所谓的海量数据,一般也是上万级的数据,比如我们要添加一百万条数据,应该如何提高它的效率呢 ...
- LLVM程序分析日记之插桩BranchInst
1. splitblockandinsertifthenelse() 一个代码例子:StackOverflow 2. SplitBlockAndInsertIfThen() 或者仅仅想插桩if the ...
- 解决因缺少驱动程序,导致“未在本地计算机上注册microsoft.ace.12.0”异常
写了一个winform程序,功能是选择一个excel表格,把里面的内容写进sqlite数据库中,在本地测试没问题,但是在其他电脑上就会报错"未在本地计算机上注册microsoft.ace.1 ...
- C++ static 数据成员和构造函数
#include<iostream> using namespace std; class Temp { int x; static int y; //y = 4; public: Tem ...
- Open_basedir绕过
Open_basedir绕过 一.基础知识 open_basedir是php.ini中的一个配置选项,它可将用户访问文件的活动范围限制在指定的区域, 假设open_basedir=/home/wwwr ...
- MySQL索引的使用是怎么样的?5个点轻松掌握!
一.前言 在MySQL中进行SQL优化的时候,经常会在一些情况下,对MySQL能否利用索引有一些迷惑. 譬如: MySQL 在遇到范围查询条件的时候就停止匹配了,那么到底是哪些范围条件? MySQL ...
- Sentinel入门学习记录
最近公司里面在进行微服务开发,因为有使用到限流降级,所以去调研学习了一下Sentinel,在这里做一个记录. Sentinel官方文档:https://github.com/alibaba/Senti ...
- 使用@Cacheable注解时,Redis连不上,直接调用方法内部的解决方案
最近redis 域名一致解析错误,导致业务多了很多异常.那么如何在这种情况下直接访问数据库,而不是报错呢 1. 解决方案 其实很简单,在配置 redis 时,只需要多一项配置,继承 CachingCo ...