Python 单元测试框架

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、软件测试

大型软件系统的开发是一个很复杂的过程,其中因为人的因素而所产生的错误非常多,因此软件在开发过程必须要有相应的质量保证活动,而软件测试则是保证质量的关键措施。正像软件熵(software entropy)所描述的那样:一个程序从设计很好的状态开始,随着新的功能不断地加入,程序逐渐地失去了原有的结构,最终变成了一团乱麻(其实最初的"很好的状态"得加个问号)。测试的目的说起来其实很简单也极具吸引力,那就是写出高质量的软件并解决软件熵这一问题。

可惜的是,软件开发人员很少能在编码的过程中就进行软件测试,大部分软件项目都只在最终验收时才进行测试,有些项目甚至根本没有测试计划!随着软件质量意识的增强,许多软件开发组织开始转向UML、CMM、RUP、XP等软件工程方法,以期提高软件质量,并使软件开发过程更加可控,好在这些方法对测试都提出了很严格的要求,从而使得测试在软件开发过程的作用开始真正体现出来。

软件测试作为一种系统工程,涉及到整个软件开发过程的各个方面,需要管理人员、设计人员、开发人员和测试人员的共同努力。作为软件开发过程中的主要力量,现今的程序员除了要编写实现代码外,还承担着单元测试这一艰巨任务,因此必须采用新的工作模式:

∙编写和维护一套详尽的单元测试用例;

∙先构造单元测试和验收测试用例,然后再编写代码;

∙根据构造的测试用例来编写代码。

前,就不该编写程序。而一旦你完成了程序,测试代码也应该完成。除非测试成功,你不能认为你编写出了可以工作的程序。"

测试最基本的原理就是比较预期结果是否与实际执行结果相同,如果相同则测试成功,否则测试失败。为了更好地理解PyUnit这一自动测试框架的作用,先来看一个简单的例子,假设我们要对例1中的Widget类进行测试:

例1. widget.py

# 将要被测试的类

class Widget:

def __init__(self, size = (40, 40)):

self._size = size

def getSize(self):

return self._size

def resize(self, width, height):

if width 0 or height < 0:

raise ValueError, "illegal size"

self._size = (width, height)

def dispose(self):

pass

采用手工方式进行单元测试的Python程序员很可能会写出类似例2的测试代码来,

例2. manual.py

from widget import Widget

# 执行测试的类

class TestWidget:

def testSize(self):

expectedSize = (40, 40);

widget = Widget()

if widget.getSize() == expectedSize:

print "test [Widget]: getSize works perfected!"

else:

print "test [Widget]: getSize doesn't work!"

# 测试

if __name__ == '__main__':

myTest = TestWidget()

myTest.testSize()

稍一留心你不难发现这种手工测试方法存在许多问题。首先,测试程序的写法没有一定的规范可以遵循,十个程序员完全可能写出十种不同的测试程序来,如果每个Python程序员都有自己不同的设计测试类的方法,光维护被测试的类就够麻烦了,谁还顾得上维护测试类。其次,需要编写大量的辅助代码才能进行单元测试,例1中用于测试的代码甚至比被测试的代码还要多,而这毫无疑问将增大Python程序员的工作量。

为了让单元测试代码能够被测试和维护人员更容易地理解,最好的解决办法是让开发人员遵循一定的规范来编写用于测试的代码,具体到Python程序员来讲,则是要采用PyUnit这一自动测试框架来构造单元测试用例。目前PyUnit已经得到了大多数Python开发人员的认可,成了事实上的单元测试标准。如果采用PyUnit来进行同样的测试,则测试代码将如例3所示:

例3. auto.py

from widget import Widget

import unittest

# 执行测试的类

class WidgetTestCase(unittest.TestCase):

def setUp(self):

self.widget = Widget()

def tearDown(self):

self.widget = None

def testSize(self):

self.assertEqual(self.widget.getSize(), (40, 40))

# 构造测试集

def suite():

suite = unittest.TestSuite()

suite.addTest(WidgetTestCase("testSize"))

return suite

# 测试

if __name__ == "__main__":

unittest.main(defaultTest = 'suite')

在采用PyUnit这一单元测试框架后,用于测试的代码做了相应的改动:∙用import语句引入unittest模块。

∙让所有执行测试的类都继承于TestCase类,可以将TestCase看成是对特定类进行测试的方法的集合。

∙在setUp()方法中进行测试前的初始化工作,并在tearDown()方法中执行测试后的清除工作,setUp()和tearDown()都是TestCase类中定义的方法。

相关文档
最新文档