面向对象的软件测试
摘 要: 面向对象程序的结构不再是传统的功能模块结构,作为一个整体,原有集成测试所要求的逐步将开发的模块搭建在一起进行测试的方法已成为不可能,传统的测试模型对面向对象软件已经不再适用。
本文总结出着实有效的面向对象的软件测试技术。首先,阐明面向对象软件测试的基本概念;然后,分别讨论分析和设计模型测试技术、类测试技术、对象交互测试技术、类层次结构测试技术、面向对象系统测试技术;最后,对面向对象软件测试的实施进行小结。
关键词:面向对象;软件测试;类测试;对象交互;测试用例
1. 分析和设计模型测试技术
面向对象软件开发的起始步骤是开发分析和设计模型。UML(统一建模语言)能在面向对象技术开发中广泛应用,也是因为构建模型能帮助开发者理解正在解决的问题;构建模型能帮助管理正在开发的系统的复杂性;分析和设计阶段建构的模型最后将对具体地实现起指导作用。如果模型的质量很高对项目来说就很有价值;但是如果模型有错误,那么它对项目的危害就无可估量。
1.1.分析和设计模型测试的内容
分析和设计模型测试的重点是测试模型的完整性和一致性,其主要内容有:
1. 对确定的对象的测试;
2. 对确定的结构的测试;
3. 对确定的主题的测试;
4. 对定义的属性和实例关联的测试;
5. 对定义的服务和消息关联的测试。
1.2.分析和设计模型测试的方法
分析与设计模型的测试主要是对分析与设计模型进行测试,找出模型中的错误,其采用的方法是指导性审查(guided inspection)。指导性审查技术通过使用明确的测试用例为查找工作成果中的缺陷提供了客观的、系统的方法。是一种增强了的专为检验模型的检测技巧,也可用来验证模型是否能符合项目的需求。其基本步骤如下:
1. 定义测试位置。
2. 使用特定的策略从测试位置选择测试值。
3. 将测试值应用到被测试的产品中。
4. 对测试结果以及对模型的测试覆盖率(基于某中标准)进行评估。
采用指导性审查技术对分析和设计产生的文本进行正确性验证,是软件开发前期的关键性测试。
2. 类测试技术
类测试是由那些与验证类的实现是否和该类的说明完全一致的相关联的活动组成的。该类测试的对象主要是指能独立完成一定功能的原始类。如果类的实现正确,那么类的每一个实例的行为也应该是正确的。
2.1. 类测试的内容
类测试的目的主要是确保一个类的代码能够完全满足类的说明所描述的要求.对一个类进行测试以确保他只做规定的事情,对此给与关注的多少,取决于提供额外的行为的类相关联的风险.在运行了各种类的测试后,如果代码的覆盖率不完整,这可能意味着该类包含了额外的文档支持的行为.需要增加更多的测试用例来进行测试。
2.2. 类测试的时间
类测试的开始时间一般在完全说明这个类,并且准备对其编码后不久,就开发一个测试计划——至少是确定测试用例的某种形式。如果开发人员还负责该类的测试,那么尤其应该如此。因为确定早期测试用例有利于开发人员理解类说明,也有助于获得独立代码检查的反馈。
2.3. 类测试的测试人员
类测试通常由他的开发人员测试,让开发人员起到测试人员的作用,就可使得必须理解类说明的人员数量减至最少。
2.4. 类测试的方法
类测试的方法有代码检查和执行测试用例。在某些情况下,用代码检查代替基于执行的测试方法是可行的,但是,和基于执行的测试相比,代码检查有以下两个不利之处:
1. 代码检查易受人为因素影响。
2. 代码检查在回归测试方面明显需要更多的工作量,常常和原始测试差不多。
一旦确定了一个类的可执行测试用例,就必须执行测试驱动程序来运行每一个测试用例,并给出每一个测试用例的结果。
2.5. 构建类测试用例
构建类的测试用例的方法有:根据类说明(用OCL表示)确定测试用例和根据类的状态转换图来构建类的测试用例。
根据类的说明确定测试用例 用OCL表示的类的说明中描述了类的每一个限定条件条件。在OCL条件下分析每个逻辑关系,从而得到由这个条件的结构所对应的测试用例。这种确定类的测试用例的方法叫做根据前置条件和后置条件构建测试用例。其总体思想是:为所有可能出现的组合情况确定测试用例需求。在这些可能出现的组合情况下,可满足前置条件,也能够到达后置条件。根据这些需求,创建测试用例;创建拥有特定输入值(常见值和特殊值)的测试用例;确定它们的正确输出——预期输出值。
根据前置条件和后置条件创建测试用例的基本步骤如下:
1. 确定在表1中与前置条件形成相匹配的各个项目所指定的一系列前置条件的影响。
2. 确定在表2中与后置条件形成相匹配的各个项目所指定的一系列前置条件的影响。
3. 根据影响到列表中各个项目的所有可能的组合情况从而构造测试用例需求。一种简单的方法就是:用第一个列表中的每一个输入约束来代替第二个列表中每一个前置条件。
4. 排除表中生成的所有无意义的条件。
表1 前置条件对测试系列的影响
前置条件 影 响
True (true 、post)
A (A、post)
(not A、exception) *
Not A (not A、post)
(A、exception) *
A and B (A and B、post)
(not A and B、exception) *
(A and not B、exception) *
(not A and not B、exception) *
A or B (A、post)
(B、post)
(A and B、post)
(not A and not B、post)
A xor B (not A and B、post)
(A and not B、post)
(A and B、exception) *
(not A and not B、exception) *
A implies B (not A、post)
(B、post)
(not A and B、post)
(A and not B、exception) *
if A then B
else C endif (A and B、post)
(not A and C、post)
(A and not B、exception) *
(not A and not C、exception) *
注:①.A、B、C代表用OCL表示的组件。
②.假如类说明中的保护性设计方法是隐式的,那么也必须对那些标记有*的测试用例进行阐述。如果保护性设计方法在类的说明中是显式出现的,那么测试用例也就确定了。
表2 后置条件对测试系列的影响
后置条件 影 响
A (pre ;A)
A and B (pre ;A and B)
A or B (pre ;A)
(pre ;B)
(pre ;A or B)
A xor B (pre ;not A or B)
(pre ;A or not B)
A implies B (pre ;not A or B)
if A then B
else C endif (pre and * ;B)
(pre and not * ;C)
注:①.A、B、C代表用OCL表示的组件。
②.对于“if A then B else C endif” 这个后置条件,假如测试用例不会对表达式A产生影响那么在用这个后置条件时,* = A else * 就是使得A为真的一个条件
根据状态转换图构建测试用例 状态转换图以图例的形式说明了与一个类的实例相关联的行为。状态转换图可用来补充编写的类说明或者构成完整的类说明。状态图中的每一个转换都描述了一个或多个测试用例需求。因而,可以用过在转换的每一端选择有代表性的值和边界来满足这些需求。如果转换是受保护的,那么也应该为这些保护条件选择边界。状态的边界值取决于状态相关属性值的范围,可以根据属性值来定义每一个状态。
3.2 抽象类测试
对类基于执行的测试时,需要建构一个类的实例。然而,一个继承体系的根类通常是抽象的,许多编程语言在语义上不允许建构抽象类的实例。这位抽象类的测试带来了很大的困难。在此,提出三种测试抽象类的方法:
1. 需要测试的抽象类单独定义一个具体的子类。通过对具体子类创建的实例测试,来完成对抽象类的测试。这种方法的缺点是,如果不是用多层继承,抽象类的方法的实现就不能轻易的传递给抽象子类。但是大部分面向对象的编程语言都不支持多重继承,而且不提倡将多重继承用在这些方面。
2. 将抽象类作为测试第一个具体子孙的一部分进行测试。这种方法不需要开发额外的用于测试的目的类,但需要考虑到为每一个祖先提供恰当的、正确的测试用例和测试脚本方法,而增加了测试具体类的复杂性。
3. 以对用于测试目的的抽象类的具体版本作直接实现,尝试找到一种为类编写源代码的方法,从而使得该类可以做为一个抽象或具体类而很容易编译。然而,不管是基于编辑遗产方案还是基于条件编译的方案都没有产生好的结果。应为合成代码都很复杂,而且难以阅读,很容易出错。
4.对象交互测试技术
面向对象的软件是由若干对象组成的,通过这些对象的相续协作来解决某些问题。对象的交互和写作方式决定了程序能作什么,从而决定了这个程序执行的正确性。也许可信任的原始类的实例可能不包含任何错误,但是如果那个实例的服务部被其他程序组件正确的使用的话,那么这个程序也就包含了错误。因此,程序中对象的正确协作——即交互——对于程序的正确性是非常关键的。
根据类的类型可以将对向交互测试分为汇集类测试和协作类测试。
4.1.汇集类测试
汇集类指的是这样的一种类,这些类在他们的说明中使用对象,但是实际上从不和这些对象中的任何一个进行协作——即他们从不请求这些对象的服务。相反,他们会表现出以下的一个或多个行为:
1. 存放这些对象的引用(或指针),通常表现程序中的对象之间一对多的关系。
2. 创建这些对象的实例。
3. 删除这些对象的实例。
可以使用测试原始类的方法来测试汇集类,测试驱动程序要创建一些实例,作为消息中的参数被传送给一个正在测试的集合。测试用例的中心目的主要是保证那些实例被正确加入集合和被正确的从集合中移出,以及测试用例说明的集合对其容量有所限制。因此,每个对象的准确的类(这些对象是用在汇集类的测试中)在确定汇集类的正确操作是不重要的,因为在一个集合实例和集合中的对象之间没有交互。假如在实际应用中可能要加入40到50条信息,那么生成的测试用例至少要增加50条信息。如果无法估计出一个有代表性的上限,就必须使用集合中大量的对象进行测试。
4.2.协作类的测试
凡不是汇集类的非原始类(原始累即一些简单的,独立的类,这些类可以用类测试方法进行测试)就是协作类。这种类在它们的一个或多个操作中使用其它的对象并将其作为他们的实现中不可缺少的一部分。当接口中的一个操作的某个后置条件引用了一个协作类的对象的实例状态,则说明那个对象的属性别使用或修改了。由此可见,写作类的测试的复杂性远远高于汇集类或者原始类测试的复杂性。鉴于协助类的测试需要根据具体的情况来定,而具体情况复杂多变,在此,就方便不论述了。
5.面向对象系统测试技术
通过单元测试和集成测试,仅能保证软件开发的功能得以实现。但不能确认在实际运行时,它是否满足用户的需要。为此,对完成开发的软件必须经过规范的系统测试。系统测试应该尽量搭建与用户实际使用环境相同的测试平台,应该保证被测系统的完整性,对临时没有的系统设备部件,也应有相应的模拟手段。系统测试时,应该参考OOA分析的结果,对应描述的对象、属性和各种服务,检测软件是否能够完全"再现"问题空间。系统测试不仅是检测软件的整体行为表现,从另一个侧面看,也是对软件开发设计的再确认。
面向对象测试的整体目标——以最小的工作量发现最多的错误——和传统软件测试的目标是一致的,但是OO测试的策略和战术有很大不同。测试的视角扩大到包括复审分析和设计模型,此外,测试的焦点从过程构件(模块)移向了类。
面向对象软件测试仍处于发展阶段。本论文根据面向对象开发方法过程和特点讨论了面向对象的软件测试,提出了一系列实用的面向软件测试技术。如,分析和设计模型测试技术、类测试技术、对象交互测试技术、类层次结构测试技术、面向对象系统测试技术等。,尽管上面说得很轻松,软件测试是一项非常麻烦的工作。
不论是传统的测试方法还是面向对象的测试方法,我们都应该遵循下列的原则:
1.应当把“尽早和不断地测试”作为开发者的座右铭。
2.程序员应该避免检查自己的程序,测试工作应该由独立的专业的软件测试机构来完成。
3.设计测试用例时,应该考虑到合法的输入和不合法的输入,以及各种边界条件,特殊情况下要制造极端状态和意外状态,比如网络异常中断、电源断电等情况。
4.一定要注意测试中的错误集中发生现象,这和程序员的编程水平和习惯有很大的关系。
5.对测试错误结果一定要有一个确认的过程。一般有A测试出来的错误,一定要有一个B来确认,严重的错误可以召开评审会进行讨论和分析。
6.制定严格的测试计划,并把测试时间安排得尽量宽松,不要希望在极短的时间内完成一个高水平的测试。
7.回归测试的关联性一定要引起充分的注意,修改一个错误而引起更多错误出现的现象并不少见。
8.妥善保存一切测试过程文档,意义是不言而喻的,测试的重现性往往要靠测试文档。
参 考 文 献
[1] McGregor.J.D.等著;杨文宏等译.《面向对象的软件测试》[M].机械工业出版社,2002.8.
[2] 张海藩.软件工程导论[M].北京:清华大学出版社,1998.
[3] 张毅坤.面向对象软件测试的特点及方法[J].西安理工大学学报,2002,18(4):361 365.
面向对象的软件测试
最新推荐文章于 2024-04-01 11:06:37 发布