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 模拟登陆的两种实现方法
Aug 10 Python
python中实现k-means聚类算法详解
Nov 11 Python
python kmeans聚类简单介绍和实现代码
Feb 23 Python
Python实现迭代时使用索引的方法示例
Jun 05 Python
Python绘制KS曲线的实现方法
Aug 13 Python
Python基础学习之函数方法实例详解
Jun 18 Python
使用python+whoosh实现全文检索
Dec 09 Python
Python字符串的修改方法实例
Dec 19 Python
Python flask框架端口失效解决方案
Jun 04 Python
详解Python 函数参数的拆解
Sep 02 Python
python利用 keyboard 库记录键盘事件
Oct 16 Python
Python实现socket库网络通信套接字
Jun 04 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
php递归方法实现无限分类实例代码
2014/02/28 PHP
页面利用渐进式JPEG来提升用户体验度
2014/12/01 PHP
浅析php-fpm静态和动态执行方式的比较
2016/11/09 PHP
php使用函数pathinfo()、parse_url()和basename()解析URL
2016/11/25 PHP
jQuery 工具函数学习资料
2010/04/29 Javascript
js的写法基础分析
2011/01/17 Javascript
jQuery 获取和设置select下拉框的值实现代码
2013/11/08 Javascript
表格奇偶行设置不同颜色的核心JS代码
2013/12/24 Javascript
jquery中的ajax方法怎样通过JSONP进行远程调用
2014/05/04 Javascript
基于NodeJS的前后端分离的思考与实践(一)全栈式开发
2014/09/26 NodeJs
Javascript进制转换实例分析
2015/05/14 Javascript
基于BootStrap Metronic开发框架经验小结【六】对话框及提示框的处理和优化
2016/05/12 Javascript
JS正则截取两个字符串之间及字符串前后内容的方法
2017/01/06 Javascript
Vue插件写、用详解(附demo)
2017/03/20 Javascript
Angular.js组件之input mask对input输入进行格式化详解
2017/07/10 Javascript
Node.js实现连接mysql数据库功能示例
2017/09/15 Javascript
JavaScript 高性能数组去重的方法
2018/09/20 Javascript
JavaScript箭头函数中的this详解
2019/06/19 Javascript
Python3.2中Print函数用法实例详解
2015/05/19 Python
在Python的Django框架下使用django-tagging的教程
2015/05/30 Python
Windows安装Python、pip、easy_install的方法
2017/03/05 Python
对python判断是否回文数的实例详解
2019/02/08 Python
python数据处理之如何选取csv文件中某几行的数据
2019/09/02 Python
Django Form设置文本框为readonly操作
2020/07/03 Python
BAILEY 44官网:美国制造的女性服装
2019/07/01 全球购物
客服主管岗位职责
2013/12/13 职场文书
岗位职责风险防控
2014/02/18 职场文书
遥感技术与仪器求职信
2014/02/22 职场文书
学雷锋演讲稿汇总
2014/05/10 职场文书
志愿者活动总结报告
2014/06/27 职场文书
好人好事演讲稿
2014/09/01 职场文书
成人成长感言如何写?
2019/08/16 职场文书
导游词之山东八大关
2019/12/18 职场文书
Python Socket编程详解
2021/04/25 Python
PyQt5爬取12306车票信息程序的实现
2021/05/14 Python
实现一个简单得数据响应系统
2021/11/11 Javascript