|
面向对象软件的测试与质量
在过去的几年里,面向对象软件的测试给人们留下的总的印象是:发展奇特、变化迅猛。软件测试一直伴随着软件生产的,从软件出世、发展、形成商品的几十年中,软件测试就从未与软件开发分开过。早期的软件测试是无章可循的,每个厂商都有自己的做法,经过几十年的努力,软件测试发展成为学科,形成了一系列理论和方法。单元测试、组合测试、系统测试、白盒测试、黑盒测试等等,都是人们耳熟能详的概念和名词。
虽然软件测试已有其理论、准则和方法,但如何理解并贯彻执行也有相当难度,而且在实现测试工作中由于经费、时间的限定,测试总是难以穷尽的。1992年以前,研究人员、方法学理论家和程序设计大师提出过一些有关面向对象测试的策略,有关人士也进行了先驱性的探索实践,但结果一般都不甚理想。看起来把传统的测试方法一古脑地加到面向对象程序上,押宝或企盼好的测试结果的做法是行不通的。
有一些面向对象的编执狂宣称对于面向对象程序而言,测试是毫无必要也是与面向对象风范相悖的,也有的甚至说:“我们重申:面向对象软件不用测试”。
但是,事实上,软件家族憎恶虚无,在过去的几年中,面向对象测试出版物纷至沓来,其增长态势也是颇具戏剧性。但近两年来,增长率有所下降,可能是显而易见的、容易解决的问题都翻腾过了,能够解决的问题已解决并习诸媒体了的缘故吧。
面向对象的软件测试的起起伏伏也影响着人们对测试面向对象软件的态度。几年前讨论测试时,有关人士总是被告诫说要进行“彻底”测试,但是何谓“彻底”测试?如何才能做到彻底测试?实际上并没有可操作的定义做指导,也没有多少成功先例可援引。时至今日,已有许多技术方法问世,也有许多测试过程中可遵循的策略出台,还有许多有用的工具可选。近期出版的有关面向对象开发的书刊也必辟章节专论测试,尽管有些是很粗略的。可比的是,早几年的出版物中要不就根本不提测试,即使没有完全去除,往往也只是用一两句话轻描淡写地提一提在面向对象软件中测试是极容易,面向对象大大减轻了软件测试的工作量等。由此可见人们对面向对象软件测试的看法及其在软件开发中的地位。
这种改变是令人欢欣鼓舞的,因为“彻底”地测试面向对象系统是非同凡响的挑战,其中至少有三大难点:
第一,对象的典型行为特征就是顺序依赖性,即对象的响应活动是与它所接受到的消息序列密切相关的。因此我们能够用状态机的概念来说明、实现和测试对象。将对象类方法孤立起来加以测试,就如同我们处理传统的例程测试那样,实际上是不充分也无效的。大多数系统化的面向对象测试方法都是基于状态的,这种基于状态的测试又有两种流派:一是有顺序的基于状态的测试,它立足于查找消息序列中暴露出错误的消息。状态定义的是正确的行为和不正确的对象行为,这种方法实际上是基于规格说明的,因为人们事先就用状态定义描述了正确的和错误的操作。二是域方法的基于状态的测试,它根据被测类的实例变量的假定值来安排各个状态,这些状态和消息之间的相互作用可以用来产生测试用例。
有顺序的基于状态的测试方法的优势在于它有40年的发展历史,这种方法40年来一直被人们所研究并应用在电子电路、硬件部件和无线通信协议的测试中,这些领域内的成功经验和知识都可以推广到对面向对象软件的测试中来,这种方法的缺点在于基于状态的测试是极困难的,状态空间极大,意味着不得不用自动化测试。此外,在实际测试中有必要添加内置功能,专门设置和报告对象系统中的状态。
第二,面向对象系统从本质上讲不象传统软件那样能测,虽然面向对象程序设计语言已经去除了容易出错的内容,如弱封装性、全局数据的危险性,类型的错误匹配等,但也还是带来了不少新问题,如局域化和分块化造成程序的可理解性的下降。
在用传统程序设计语言编写的软件中,变量的静态集合对应的就是程序的状态空间。如果程序的结构设计精良,那么其运行时的行为活动也能够跟踪捕捉到。相反,面向对象程序则不然:用面向对象程序设计语言的继承性和多态性常常使源代码或规格说明中的路径和状态变得枝枝蔓蔓、难以弄清。那些所谓的封装性能够减少程序的复杂性的老生常谈,实际上正在灰飞烟灭。面向对象软件测试中的测试用例的设置实际上是极为困难的。对象总是由另一些对象组成,所以为一个对象设定测试用例往往会演变成为该对象嵌套的所有对象设置测试用例。对于面向对象软件而言,在设计开发软件的同时就考虑和设计该软件的可测试性并内置测试例程,必将有助于缓解面向对象软件将面临的测试的紧张局面。
第三个难点是实际存在的问题,重复的和增量式的开发与赶不上趟的管理常常导致类库缺乏正确的功能划分(从原则上讲类库中的每个类在功能上是正交化的),不保留源代码的文档。这些都是老问题了,而在面向对象软件中表现的更加突出,其后果是软件失误的可能性增大、可测试性降低、可重用性降低,同时伴随出现的问题是库规模越来越大,而内容越来越陈旧。 |
|