Python unittest单元测试框架总结


Posted in Python onSeptember 08, 2018

什么是单元测试

单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。

比如对于函数abs(),我们可以编写的测试用例为:

(1)输入正数,比如1、1.2、0.99,期待返回值与输入相同

(2)输入复数,比如-1、-1.2、-0.99,期待返回值与输入相反

(3)输入0,期待返回0

(4)输入非数值类型,比如None、[]、{}、期待抛出TypeError

把上面这些测试用例放到一个测试模块里,就是一个完整的单元测试

 unittest工作原理

unittest中最核心的四部分是:TestCase,TestSuite,TestRunner,TestFixture

(1)一个TestCase的实例就是一个测试用例。测试用例就是指一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。

(2)而多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。

(3)TestLoader是用来加载TestCase到TestSuite中的。

(4)TextTestRunner是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法

(5)测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。

 综上,整个流程就是首先要写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块中。

python unittest简介

unittest是python下的单元测试框架,是java JUnit的python版本, 跟其它语言下的单元测试框架风格类似,unittest支持自动化测试、共享setup和teardown代码、测试聚合成集、独立于报告框架。unittest模块提供了一个丰富的工具集用于构建和执行用例,先看一个入门的例子:

import unittest

class TestStringMethods(unittest.TestCase):

def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO') 
  def test_isupper(self):
    self.assertTrue('FOO'.isupper())
    self.assertFalse('Foo'.isupper())

  def test_split(self):
    s = 'hello world'
    self.assertEqual(s.split(), ['hello', 'world'])
    # check that s.split fails when the separator is not a string
    with self.assertRaises(TypeError):
      s.split(2)

if __name__ == '__main__':
  unittest.main()

可以通过继承unittest.TestCase创建一个测试用例TestStringMethods,在这个用例中定义了测试函数,这些函数名字都以”test”开头,在执行测试用例TestStringMethods时,这些方法会被自动调用。每个测试函数中都调用了assertTrue()和assertFalse()方法检查预期结果,或者使用assertRaises()确认产生了一个特定异常。现在来看一下这段代码的运行结果:

...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK

有时我们需要在用例执行前后做一些工作如初始化和清理,这就需要实现setUp()和tearDown()方法

import unittest

class WidgetTestCase(unittest.TestCase):
  def setUp(self):
    print("setUp()")

  def test_1(self):
    print("test_1")

  def test_2(self):
    print("test_2")

  def tearDown(self):
    print("tearDown()")

if __name__ == '__main__':
  unittest.main()

运行结果:

setUp()
.test_1
tearDown()
setUp()
.test_2
tearDown()
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

注:如果setUp()执行成功(没有异常发生),那么无论测试方法是否通过,tearDown()都会被执行
根据所测的特性测试用例被组合在一起,通过调用unittest.main(),unittest测试框架会自动收集所有模块的测试用例然后执行。

import unittest

class WidgetTestCase(unittest.TestCase):
  def setUp(self):
    print("WidgetTestCase setUp()")

  def test_Widget(self):
    print("test_Widget")

  def tearDown(self):
    print("WidgetTestCase tearDown()")

class FuncTestCase(unittest.TestCase):
  def setUp(self):
    print("FuncTestCase setUp()")

  def test_func(self):
    print("test_func")

  def tearDown(self):
    print("FuncTestCase tearDown()")


if __name__ == '__main__':
  unittest.main()

 运行结果:

FuncTestCase setUp()                                                 
test_func                                                            
FuncTestCase tearDown()                                              
.WidgetTestCase setUp()                                              
test_Widget                                                          
WidgetTestCase tearDown()                                            
.                                                                    
----------------------------------------------------------------------
Ran 2 tests in 0.003s                                                

OK  

如果想构建自已的用例集,只需要这么做:

import unittest

class WidgetTestCase(unittest.TestCase):
  def setUp(self):
    print("WidgetTestCase setUp()")

  def test_Widget(self):
    print("test_Widget")

  def tearDown(self):
    print("WidgetTestCase tearDown()")

class FuncTestCase(unittest.TestCase):
  def setUp(self):
    print("FuncTestCase setUp()")

  def test_func(self):
    print("test_func")

  def tearDown(self):
    print("FuncTestCase tearDown()")

def suite():
  suite = unittest.TestSuite()
  suite.addTest(FuncTestCase('test_func'))
  return suite

if __name__ == '__main__':
  runner=unittest.TextTestRunner()
  runner.run(suite())

运行结果:

FuncTestCase setUp()
test_func
FuncTestCase tearDown()
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

unittest中相关类和函数

在unittest中 TestCase类的实例代表逻辑测试单元,这个类通常被当作测试类的基类使用, TestCase类实现了许多测试相关的接口,主要是以下三组方法:

1.执行测试用例的方法

setUp()
#在每个测试方法之前执行,这个方法引发的异常会被认为是错误,而非测试失败,默认实现是不做任何事
tearDown()
#在每个测试方法之后执行,即使测试方法抛出异常tearDown()方法仍会执行,并且只有setUp()成功执行时tearDown()才会执行,
#同样这个方法引发的异常会被认为是错误,而非测试失败。默认实现是不做任何事
setUpClass()
#在一个测试类的所有测试方法执行之前执行,相当于google test中的SetUpTestCase()方法,setUpClass()必须被装饰成一个classmethod()
@classmethod
def setUpClass(cls):
  ...
tearDownClass()
#在一个测试类的所有测试方法执行之后执行,相当于google test中的TearDownTestCase()方法,tearDownClass()必须被装饰成一个classmethod()
@classmethod
def tearDownClass(cls):
  ...

2.检查条件和报告错误的方法

Method Checks that New in
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b 3.1
assertIsNot(a, b) a is not b 3.1
assertIsNone(x) x is None 3.1
assertIsNotNone(x) x is not None 3.1
assertIn(a, b) a in b 3.1
assertNotIn(a, b) a not in b 3.1
assertIsInstance(a, b) isinstance(a, b) 3.2
assertNotIsInstance(a, b) not isinstance(a, b) 3.2
assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) raises exc
assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) raises exc and the message matches regex r 3.1
assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) raises warn 3.2
assertNotAlmostEqual(a, b) round(a-b, 7) != 0
assertGreater(a, b) a > b 3.1
assertGreaterEqual(a, b) a >= b 3.1
assertLess(a, b) a 3.1
assertLessEqual(a, b) a 3.1
assertRegex(s, r) r.search(s) 3.1
assertNotRegex(s, r) not r.search(s) 3.2
assertCountEqual(a, b) a and b have the same elements in the same number, regardless of their order 3.2
assertWarnsRegex(warn, r, fun, *args, **kwds) fun(*args, **kwds) raises warn and the message matches regex r 3.2
assertLogs(logger, level) The with block logs on logger with minimum level 3.4
assertMultiLineEqual(a, b) strings 3.1
assertSequenceEqual(a, b) sequences 3.1
assertListEqual(a, b) lists 3.1
assertTupleEqual(a, b) tuples 3.1
assertSetEqual(a, b) sets or frozensets 3.1
assertDictEqual(a, b) dicts 3.1
Python 相关文章推荐
Python+matplotlib实现计算两个信号的交叉谱密度实例
Jan 08 Python
python 读取文本文件的行数据,文件.splitlines()的方法
Jul 12 Python
两个元祖T1=('a', 'b'),T2=('c', 'd')使用匿名函数将其转变成[{'a': 'c'},{'b': 'd'}]的几种方法
Mar 05 Python
Python3.5 Json与pickle实现数据序列化与反序列化操作示例
Apr 29 Python
详解Python下载图片并保存本地的两种方式
May 15 Python
python selenium登录豆瓣网过程解析
Aug 10 Python
Python实现的微信红包提醒功能示例
Aug 22 Python
在Python中利用pickle保存变量的实例
Dec 30 Python
matplotlib quiver箭图绘制案例
Apr 17 Python
解决redis与Python交互取出来的是bytes类型的问题
Jul 16 Python
python递归函数用法详解
Oct 26 Python
Python OpenCV超详细讲解调整大小与图像操作的实现
Apr 02 Python
tensorflow实现加载mnist数据集
Sep 08 #Python
使用tensorflow实现线性回归
Sep 08 #Python
Python  unittest单元测试框架的使用
Sep 08 #Python
tensorflow实现逻辑回归模型
Sep 08 #Python
Django实现表单验证
Sep 08 #Python
python实现排序算法解析
Sep 08 #Python
TensorFlow实现Logistic回归
Sep 07 #Python
You might like
Zerg兵种介绍
2020/03/14 星际争霸
从康盛产品(discuz)提取出来的模板类
2011/06/28 PHP
一个php生成16位随机数的代码(两种方法)
2014/09/16 PHP
php实时倒计时功能实现方法详解
2017/02/27 PHP
PHP实现登陆并抓取微信列表中最新一组微信消息的方法
2017/07/10 PHP
小程序微信退款功能实现方法详解【基于thinkPHP】
2019/05/05 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
2020/04/05 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
Javascript 圆角div的实现代码
2009/10/15 Javascript
jQuery get和post 方法传值注意事项
2009/11/03 Javascript
限制文本框输入N个字符的js代码
2010/05/13 Javascript
JS target与currentTarget区别说明
2011/08/28 Javascript
js浮点数保留两位小数点示例代码(四舍五入)
2013/12/26 Javascript
javascript中JSON.parse()与eval()解析json的区别
2016/05/19 Javascript
利用JS判断客户端类型你应该知道的四种方法
2017/12/22 Javascript
Vue的elementUI实现自定义主题方法
2018/02/23 Javascript
在 Angular6 中使用 HTTP 请求服务端数据的步骤详解
2018/08/06 Javascript
jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】
2018/08/28 jQuery
vue+VeeValidate 校验范围实例详解(部分校验,全部校验)
2018/10/19 Javascript
React Component存在的几种形式详解
2018/11/06 Javascript
基于vue-cli、elementUI的Vue超简单入门小例子(推荐)
2019/04/17 Javascript
JS简单表单验证功能完整示例
2020/01/26 Javascript
JS的时间格式化和时间戳转换函数示例详解
2020/07/27 Javascript
Python实现霍夫圆和椭圆变换代码详解
2018/01/12 Python
python爬虫框架scrapy实现模拟登录操作示例
2018/08/02 Python
在Qt5和PyQt5中设置支持高分辨率屏幕自适应的方法
2019/06/18 Python
用opencv给图片换背景色的示例代码
2020/07/08 Python
css背景图片的背景裁切、背景透明度、背景变换等效果运用
2012/12/24 HTML / CSS
关于webview适配H5上传照片或者视频文件的方法
2020/11/04 HTML / CSS
法国奢华女性时尚配饰网上商店:Monnier Frères
2016/08/27 全球购物
Pedro官网:新加坡时尚品牌
2019/08/27 全球购物
巴西Mr. Cat在线商店:购买包包和鞋子
2019/09/08 全球购物
初级Java程序员面试题
2016/03/03 面试题
公开致歉信
2019/06/24 职场文书
SONY AN-LP1 短波有源天线放大器
2021/04/22 无线电
Python写情书? 10行代码展示如何把情书写在她的照片里
2022/04/21 Python