文档介绍:第10章面向对象测试
面向对象测试的特点
面向对象的测试策略
面向对象软件的测试用例设计
RUP的测试活动
1
西安交通大学刘海岩
面向对象测试的特点
面向对象测试的整体目标(以最小的工作量发现最大数量的错误)与传统软件测试的目标是一致的。但是OO程序的性质改变了测试策略与战术。
1、传统测试主要是基于程序运行过程的,即选择一组输入数据运行被测程序,通过比较实际结果与预期结果从而判断程序是否有错。而OO程序中的对象通过发送消息启动相应的操作,并且通过修改对象的状态达到转化系统运行状态的目的,同时,在系统中还可能存在并发活动的对象。应此传统的测试方法不再适应。
2、传统程序的复用以调用公共模块为主,运行环境是连续的。而面向对象复用很多是用继承实现的,子类继承过来的同名操作有新的语境,必须要重新测试。随着继承层次的加深,测试的工作量和难度也随之增加。由继承支持的多态的特性同样给测试带来了难度。
2
西安交通大学刘海岩
3、面向对象软件的开发是渐进、演化的开发,从分析、设计到实现使用相同的语义结构(如类、属性、操作、消息)。因此要扩大测试的视角,对分析模型、设计模型进行测试。例如,在分析模型中定义了一个无用的属性,围绕着这个属性可能会带来以下错误:
在分析模型中:
•定义了一个与该属性有关的操作:
•导致了不正确的类关系:
•为共享属性和操作创建了不必要的子类:
•为适应该属性和操作刻画了其类和系统的行为。
如果问题在分析阶段未被发现,再将错误继续传播,使得设计模型可能存在:
•与该类有关的不合适的子系统或任务的划分:
•与该无用属性有关操作的算法设计:
•与该无用属性有关操作的接口及消息模式。
3
西安交通大学刘海岩
如果问题在设计阶段仍未被检测到,并传送到编码活动中,则大量的工作将被花在生成那些实现一个不必要的属性、不必要的操作、不必要的消息通信以及很多其它相关问题的代码。
由于分析设计模型不能被执行,所以不能进行传统意义上的测试。只能通过正式技术复审来检查分析模型和设计模型的一致性。
4、面向对象开发工作的演化性使面向对象测试活动也具有演化性。每个构件产生过程中,单元测试随时进行,迭代的每一个构造都要进行集成测试,后期迭代还包括大量的回归测试,迭代结束时进行系统测试。
是否设计模式的使用将减轻OO系统的繁重测试?Binder认为每次复用是一个新的使用语境,需要重新谨慎的测试。为了获得OO系统的高可靠性,可能需要更多的而不是更少的测试。
4
西安交通大学刘海岩
面向对象的测试策略
传统的测试策略是从小型测试开始,逐步走向大型测试,即从单元测试开始,逐步进入集成测试,最后进行系统测试。在传统测试中,单元测试集中在最小的可编译程序单位(子程序、过程、函数),一旦这些单元都被独立测试后,被集成到程序结构中进行一系列的回归测试,以发现由于模块的接口和新单元加入所导致的副作用而带来的错误。最后,对系统整体进行测试以发现需求中的错误。
1、单元测试(类或对象或组成的小簇)
OO语境中,单元的概念发生了变化。封装驱动了类或对象的定义,即每个类或对象封装了属性和操作这些属性的服务,最小的可测试单位不是个体模块,而是封装的类或对象。类包含一组不同的操作,并且某个特殊操作可能作为类的一部分存在(如子类中继承的操作),因此,单元实际上是类或若干相关的类组成的小簇。
5
西安交通大学刘海岩
单元测试不再孤立的测试单个操作(这是传统的单元测试的视角),而是将操作作为类的一部分。例如:
命令
execute()
粘贴命令
execute()
拷贝命令
execute()
execute由基类定义并被一组子类继承,每个子类的execute被应用于每个子类定义的私有属性和操作的语境内,因此,仅在基类内测试execute是无效的,应该在每个子类的语境内测试execute。
单元测试若用于测试不发生请求的类(如“栈”类,其中操作有:pop(),push(),empty())时,同样要设计驱动程序,封装在一个测试类(包)中,测试类负责运行测试用例并给出结果,每个测试用例用一个操作名表示;单元测试如果测试发生请求的类,则需要设计桩程序,封装在桩类中。
6
西安交通大学刘海岩
单元测试主要使用的图模型是:类图、类的状态图、活动图。
2、集成测试(大簇、构件、子系统)
这里的构件或子系统应该与系统的体系结构相对应。集成测试主要以检查这些构件、子系统的接口为目的。对于类之间的集成,Roger S. Pressman认为传统的自顶向下和自底向上集成的测试策略没有意义。他提出了两种集成测试策略:
(1)基于线程的测试(thread-based testing)