python单元测试unittest实例详解


Posted in Python onMay 11, 2015

本文实例讲述了python单元测试unittest用法。分享给大家供大家参考。具体分析如下:

单元测试作为任何语言的开发者都应该是必要的,因为时隔数月后再回来调试自己的复杂程序时,其实也是很崩溃的事情。虽然会很快熟悉内容,但是修改和调试将是一件痛苦的事情,如果你在修改了代码后出现问题的话,而单元测试可以帮助我们很快准确的定位到问题的位置,出现问题的模块和单元。所以这是一件很愉快的事情,因为我们知道其它修改或没有修改的地方仍然是正常工作的,而我们目前的唯一问题就是搞定眼前这个有点问题的“家伙”。所以工作会在轻松中开始,并且很快将会结束,因为你已经知道很多信息了。
 
单元测试自然是对程序中最小的可测试模块--函数来进行测试;因为单元测试的对象是函数,也就是说你得被测试对象一定要有输出结果,哪怕就是异常输出,也得有输出,以便单元测试模块能够捕获返回值,并且与预期值进行比较,从而得出测试通过与否。
 
单元测试的加载方式有2种:一种是通过unittest.main()来启动单元测试的测试模块;一种是添加到testsuite集合中再加载所有的被测试对象,而testsuit里存放的就是单元测试的用例,下面分别列出了2种方法的使用。

1.1 测试模块中的函数:

被测模块:

#!/usr/bin/env python 
#encoding: utf-8 
def sum( x, y): 
    return x+y 
def sub( x, y): 
    return x-y

单元测试模块:

#!/usr/bin/env python 
#encoding: utf-8 
import unittest 
import myclass 
class mytest(unittest.TestCase): 
  ##初始化工作 
  def setUp(self): 
    pass 
  #退出清理工作 
  def tearDown(self): 
    pass 
  #具体的测试用例,一定要以test开头 
  def testsum(self): 
    self.assertEqual(myclass.sum(1, 2), 2, 'test sum fail') 
  def testsub(self): 
    self.assertEqual(myclass.sub(2, 1), 1, 'test sub fail')   
if __name__ =='__main__': 
  unittest.main()

测试结果:【F表示一个fail, F前的点表示一个通过,有E的话表示程序自身异常】

.F
======================================================================
FAIL: testsum (__main__.mytest)
----------------------------------------------------------------------
Traceback (most recent call last):
 File "C:\Users\xiaowu\workspace\mypython\unitTest.py", line 19, in testsum
  self.assertEqual(myclass.sum(1, 2), 2, 'test sum fail')
AssertionError: test sum fail
----------------------------------------------------------------------
Ran 2 tests in 0.001s 
FAILED (failures=1)

1.2 测试模块类中的函数:

被测模块:

#!/usr/bin/env python
#encoding: utf-8
class myclass:
  def __init__(self):
    pass
  def sum(self, x, y):
    return x+y
  def sub(self, x, y):
    return x-y

单元测试模块:

#!/usr/bin/env python 
#encoding: utf-8 
import unittest 
import myclass 
class mytest(unittest.TestCase): 
  ##初始化工作 
  def setUp(self): 
    self.tclass = myclass.myclass()
    ##实例化了被测试模块中的类 
  #退出清理工作 
  def tearDown(self): 
    pass 
  #具体的测试用例,一定要以test开头 
  def testsum(self): 
    self.assertEqual(self.tclass.sum(1, 2), 3) 
if __name__ =='__main__': 
  unittest.main()

运行结果:

.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK

这种方式执行单个测试文件时使用-v参数可以获得更多的测试结果信息。如:mytest.py -v 
 
2 加载测试套件

好吧,在运用测试套件进行单元测试之前,我想还是稍微研究一下unittest模块的内容有哪些,其大概的运行方式是什么样的。而后在给出根据各种情况如何制定单元测试套件。

首先,自然是查看unittest模块有哪些成员啦!

>>import unittest 
>>dir(unittest) 
['FunctionTestCase', 'TestCase', 'TestLoader', 'TestProgram', 'TestResult', 'Tes 
tSuite', 'TextTestRunner', '_CmpToKey', '_TextTestResult', '_WritelnDecorator', 
'__all__', '__author__', '__builtins__', '__doc__', '__email__', '__file__', '__ 
metaclass__', '__name__', '__package__', '__unittest', '__version__', '_makeLoad 
er', '_strclass', 'defaultTestLoader', 'findTestCases', 'getTestCaseNames', 'mai 
n', 'makeSuite', 'os', 'sys', 'time', 'traceback', 'types']

可以看到其自身的成员也不是很多,大概包括有:

['FunctionTestCase', 'TestCase', 'TestLoader', 'TestProgram', 'TestResult',
 'TestSuite','TextTestRunner', '_CmpToKey', '_TextTestResult', '_WritelnDecorator',
 'defaultTestLoader','findTestCases', 'getTestCaseNames', 'main', 'makeSuite']

好吧,我们大概看看具体都是干什么的

>>memblist = ['FunctionTestCase', 'TestCase', 'TestLoader', 'TestProgram', 'TestResult',\ 
'TestSuite','TextTestRunner', 'defaultTestLoader','findTestCases', 'getTestCaseNames', \ 
'main', 'makeSuite'] 
>>for memb in memblist: 
.. cur = getattr(unittest, memb) 
.. print help(cur)

'FunctionTestCase':函数测试用例,即给一个函数作为参数,返回一个testcase实例,可选参数有set-up,tear-down方法
'TestCase':所有测试用例的基本类,给一个测试方法的名字,返回一个测试用例实例
'TestLoader':测试用例加载器,其包括多个加载测试用例的方法。返回一个测试套件
loadTestsFromModule(self, module)--根据给定的模块实例来获取测试用例套件
loadTestsFromName(self, name, module=None)
--根据给定的字符串来获取测试用例套件,字符串可以是模块名,测试类名,测试类中的测试方法名,或者一个可调用的是实例对象
这个实例对象返回一个测试用例或一个测试套件
loadTestsFromNames(self, names, module=None) --和上面功能相同,只不过接受的是字符串列表
loadTestsFromTestCase(self, testCaseClass)--根据给定的测试类,获取其中的所有测试方法,并返回一个测试套件
'TestProgram':命令行进行单元测试的调用方法,作用是执行一个测试用例。其实unittest.main()方法执行的就是这个命令,
而这个类实例时默认加载当前执行的作为测试对象,
原型为 __init__(self, module='__main__', defaultTest=None, argv=None, testRunner=xx, testLoader=xx)
其中module='__main__'就是默认加载自身
'TestResult':测试用例的结果保存实例,通常有测试框架调用
'TestSuite':组织测试用例的实例,支持测试用例的添加和删除,最终将传递给testRunner进行测试执行
'TextTestRunner':进行测试用例执行的实例,其中Text的意思是以文本形式显示测试结果。显示测试名称,即完成的测试结果,其过同执行单元测试脚本时添加-v参数
'defaultTestLoader':其实就是TestLoader
'findTestCases', 'getTestCaseNames':这个2个就不用解释了
'main': 其实就是TestProgram
'makeSuite':通常是由单元测试框架调用的,用于生产testsuite对象的实例
 
至此,我们知道了。其实整个单元测试框架的逻辑出来了。分三步走:第一步testloader根据传入的参数获得相应的测试用例,即对应具体的测试方法,
然后makesuite在把所有的测试用例组装成testsuite,最后把testsiute传给testrunner进行执行。
而我们通常执行的unittest.main(),其实就是unittest.testprom方法,其执行的功能就是上面分析的三步,在第一步中其传入的参数是自身的模块__main__;
在第二步中把自身模块中的所有测试类中中的测试方法提取出来,并生成测试套件;最后再把测试套件传递给testrunner进行具体的测试。

最后给出一个完整的单元测试组织代码,把该代码放到单元测试用例文件的同一个目录后执行该脚本,即可执行所有的测试用例文件。

【测试用例文件必须为test开头,如:testxxx.py, 当然这个文件本身是一个单元测试的文件】

#!/usr/bin/env python
#encoding: utf-8
#该代码源自深入python
import unittest
import myclass
import re
import os
import sys
def testAllinCurrent():
  path = os.path.abspath(os.path.dirname(sys.argv[0]))
  files = os.listdir(path)
  test = re.compile("test\.py{1}quot;, re.IGNORECASE)
  files = filter(test.search, files)
  filenameToModuleName = lambda f: os.path.splitext(f)[0]
  moduleNames = map(filenameToModuleName, files)
  modules = map(__import__, moduleNames)
  load = unittest.defaultTestLoader.loadTestsFromModule
  return unittest.TestSuite(map(load, modules))
if __name__ == "__main__":
  unittest.main(defaultTest="regressionTest")

希望本文所述对大家的Python程序设计有所帮助。

Python 相关文章推荐
Python构造函数及解构函数介绍
Feb 26 Python
Python最基本的数据类型以及对元组的介绍
Apr 14 Python
Python3通过Luhn算法快速验证信用卡卡号的方法
May 14 Python
尝试用最短的Python代码来实现服务器和代理服务器
Jun 23 Python
Python Flask 搭建微信小程序后台详解
May 06 Python
django使用xadmin的全局配置详解
Nov 15 Python
Python实现中值滤波去噪方式
Dec 18 Python
python实现超级马里奥
Mar 18 Python
Python logging模块原理解析及应用
Aug 13 Python
通过代码实例了解Python异常本质
Sep 16 Python
python使用requests库爬取拉勾网招聘信息的实现
Nov 20 Python
Python OpenCV实现图像模板匹配详解
Apr 07 Python
Python使用MYSQLDB实现从数据库中导出XML文件的方法
May 11 #Python
Python生成不重复随机值的方法
May 11 #Python
Python解析nginx日志文件
May 11 #Python
Python字符串替换实例分析
May 11 #Python
Python使用django获取用户IP地址的方法
May 11 #Python
总结Python编程中三条常用的技巧
May 11 #Python
python求解水仙花数的方法
May 11 #Python
You might like
受疫情影响 动画《Re从零开始的异世界生活》第二季延期至7月
2020/03/10 日漫
php数组函数序列之array_intersect() 返回两个或多个数组的交集数组
2011/11/10 PHP
thinkphp中ajax与php响应过程详解
2014/12/08 PHP
利用PHP抓取百度阅读的方法示例
2016/12/18 PHP
PHP多种序列化/反序列化的方法详解
2017/06/23 PHP
走出JavaScript初学困境—js初学
2008/12/29 Javascript
JavaScript异步调用定时方法并停止该方法实现代码
2012/03/16 Javascript
Javascript自定义排序 node运行 实例
2013/06/05 Javascript
动态标签 悬停效果 延迟加载示例代码
2013/11/21 Javascript
Highcharts使用简例及异步动态读取数据
2015/12/30 Javascript
jQuery实现Select下拉列表进行状态选择功能
2017/03/30 jQuery
jquery+css3实现熊猫tv导航代码分享
2018/02/12 jQuery
js实现省级联动(数据结构优化)
2020/07/17 Javascript
vue插件--仿微信小程序showModel实现模态提示窗功能
2020/08/19 Javascript
使用js获取身份证年龄的示例代码
2020/12/11 Javascript
动态实现element ui的el-table某列数据不同样式的示例
2021/01/22 Javascript
Python中decorator使用实例
2015/04/14 Python
Python操作串口的方法
2015/06/17 Python
python处理Excel xlrd的简单使用
2017/09/12 Python
Python星号*与**用法分析
2018/02/02 Python
python数据分析:关键字提取方式
2020/02/24 Python
Python reversed函数及使用方法解析
2020/03/17 Python
python 实现倒计时功能(gui界面)
2020/11/11 Python
CSS3属性选择符介绍
2008/10/17 HTML / CSS
Perfumetrader荷兰:香水、化妆品和护肤品在线商店
2017/09/15 全球购物
Blue Nile蓝色尼罗河香港官网:世界最大在线钻石珠宝销售商
2020/05/07 全球购物
师范生自荐信
2013/10/27 职场文书
学校就业推荐信范文
2014/05/19 职场文书
小学生九一八纪念日83周年演讲稿500字
2014/09/17 职场文书
先进教师事迹材料
2014/12/16 职场文书
万里长城导游词
2015/01/30 职场文书
重温经典:乔布斯在斯坦福大学的毕业演讲(双语)
2019/08/26 职场文书
浅谈怎么给Python添加类型标注
2021/06/08 Python
Java Socket实现多人聊天系统
2021/07/15 Java/Android
关于python中模块和重载的问题
2021/11/02 Python