相关知识点-面象对象(=Object Oriented)技术
1. 对象和类
l 面象对象的编程语言:以对象为中心,以消息为驱动,程序=对象+消息
l 类是一种新的数据类型,是设计的核心,是通过抽象数据类型的方法来实现的一种数据类型
l 类是对某一对象的抽象,对象是某一类的实例,两者密切相关
2. 封装、继承和多态性
(1) 封装:把数据和操作结合一体,使程序结构更加紧凑,避免了数据紊乱带来的调试与维护的困难
(2) 继承:可以从一个类派生到另一个类,派生类继承了父类和祖先类的数据成员和函数,增加了软件的可扩充性,并为代码重用提供了强有力的手段
(3) 多态性:多种表现形式,可以用‘一个对外接口,多个内在实现方法’表示。
一.面向对象测试模型
1. 面向对象测试的分类
依据面向对象开发模型(面向对象分析、面向对象设计、面向对向编程),分为:
(1) 面向对象分析的测试(OOA Test)、面向对象设计的测试(OOD Test):是对分析结果和设计结果的测试,主要对分析设计产生的文本进行的,是软件开发前期的关键性测试
(2) 面向对象编程的测试(OOP Test):对编程风格和程序代码实现进行测试,主要的测试内容在OO Unit Test和OO Integrate Test中体现
(3) 面向对象单元测试(OO Unit Test):对程序内部具体单一的功能模块的测试,主要对类成员函数的测试,是OO Integrate Test的基础
(4) 面向对象集成测试(OO Intergrate Test):对系统内部的相互服务进行测试,如成员函数间的相互作用,类间的消息传递。不仅要基于OO Unit Test,还要参考OOD、OOD Test的结果
(5) 面向对象确认测试(OO System Test)、面向对象系统测试(OO System Test):最后阶段的测试,以用户需求为测试标准,借鉴OOA 、OOA Test的结果
2. 面向对象测试模型
2005-4-25
二. 面向对象软件的测试策略
1. 面向对象分析的测试
(1) 面向对象分析
是把E-R图和语义网络模型,即信息造型中的概念,与面向对象程序设计语方中的重要概念结合在一起而形成的分析方法。通常以问题空间的图表的形式进行描述
(2) 分析方法
直接映射问题空间,全面地将问题空间中实现功能的现实抽象化。将问题空间中的实例抽象为对象,用对象的结构反映问题空间的复杂实例和复杂关系,用属性和服务表示实例的特性和行为。
(3) 面向对象分析缺点
对问题空间分析抽象的不完整,会影响软件的功能实现,导致软件开发后期产生大量原本可避免的修补工作;一些冗余的对象或结构类的选定,程序的整体结构和增加程序员不必要的工作量,因此 OOA测试的重点在其完整性和冗余性
(4) OOA测试划分的五个方面
对认定的对象的测试、对认定的结构的测试、对认定的主题的测试、对定义的属性和实例关联的测试、对定义的服务和消息关联的测试
测试内容 |
概述 |
测试考虑方面 |
|
认定的对象的测试 |
认定的对象:对问题空间中的结构、其他系统、设备、被记忆的事件、系统涉及的人员等实际实例的抽象 |
(1) 是否全面,问题空间中的实例是否都反映在认定的抽象对象中了 (2) 是否具有多个属性,只具有一个属性的对象不抽象为为独立的对象 (3) 对认定为同一对象的实例是否有共同的、区别于其他实例的共同属性 (4) 对认定为同一对象的实例是否提供或需要相同的服务,如果服务随着实例的不同而变化,认定的对象就需要分析或利用继承性来分类表示 (5) 如果系统没有必要始终保持对象代表的实例信息,提供或者得到关于它的服务、认定的对象也无必要 (6) 认定的对象的名称要尽量准确、适用 |
|
认定的结构的测试 |
认定的结构:多种对象的组织方式,用来反映问题空间中的复杂实例和复杂关系,认定的结构分为两种:分类结构 组装结构 |
分类结构:体现问题空间中实例的一般与特殊的关系 |
(1) 结构中一种对象尤其是高层对象,是否存在不同于下一层对象的特殊的可能性,即是否能派生出下一层对象 (2) 结构中一种对象尤其是同一低层对象,是否能抽象出在现实中有意义的更一般的上层对象 (3) 对所有认定的对象,是否能向上层抽象出现实中有意义的对象 (4) 高层的对象的特性是否完全体现下层的共性 (5) 低层的对象是否有高层特性基础上的特殊性 |
组装结构:体现问题空间中实例的整体与局部的关系 |
(1) 整体对象和部件对象的组装关系是否符合现实的关系 (2) 整体对象和部件对象是否在考虑的问题空间中有实际关系 (3) 整体对象是否遗漏了在问题空间中有用的部件对象 (4) 部件对象是否能够在问题空间中组装成新的有意义的的整体对象 |
||
认定的主题的测试 |
主题:在对象和结构的基础上更高一层的抽象,是为了提供OOA 分析结果的可见性,如同文章中各章的摘要 |
(1) 贯彻George Miller的‘7+2’原则。如果主题个数超过7个,对有较密切属性和服务的主题归并 (2) 主题所反映的一组对象和结构是否具有相同或相近的属性和服务 (3) 认定的主题是否是对象和结构更高一层的抽象,是否便于理解OOA 结果的概括 (4) 主题间的消息联系(抽象)是否代表了主题所反映的对象和结构之间的所有关联 |
|
对定义的属性和实例关联的测试 |
属性:用来描述对象或结构所反映的实例的特性 实例关联:反映实例集合间的映射关系 |
(1) 定义的属性是否对相应的对象和分类结构的每个现实实例都适用 (2) 定义的属性在现实世界是否与这种实例关系密切 (3) 定义的属性在问题空间是否与实种实例关系密切 (4) 定义的属性是否能够不依赖于其他属性被独立理解 (5) 定义的属性在分类结构中的位置是否恰当,低层对象的共有属性是否在上层对象属性中体现 (6) 在问题空间中每个对象的属性是否定义完整 (7) 定义的实例关联是否符合现实 (8) 在问题空间中实例关联是否定义完整,特别需要注意‘一对多’、‘多对多’的实例关联 |
|
对定义的服务和消息关联的测试 |
定义的服务:定义的每一种对象和结构在问题空间所要求的行为 消息关联:问题空间中实例之间必要的通信,需要定义相应的消息关联 |
(1) 对象和结构在问题空间中的不同状态是否定义相应的服务 (2) 对象和结构所需的服务是否都定义了相应的消息关联 (3) 定义的消息关联所指引的服务是否正确 (4) 沿着消息关联执行的线程是否合理,是否符合现实过程 (5) 定义的服务是否重复,是否定义了能够得到的服务 |
2. 面向对象设计(OOD)的测试
(1) 面向对象设计(OOD)
采用‘造型的观点’,以OOA为基础归纳出类,并建立类结构或进一步构造类库,以实现分析结果对问题空间的抽象。OOD归纳的类即可以是对象的简单延续,也可以是不同对象的相同或相似的服务
(2) OOD与OOA
OOD是OOA的进一步细化和更高层的抽象,所以OOD、OOA的界限很难区分,OOD确定类和类结构不仅是满足当前需求分析要求,更重要是通过重新组合或加以适当的补充,方便实现功能重用和扩增。因此,对OOD的测试,建议针对功能的实现和重用以及OOA结果的分析
(3) OOD测试划分的三个方面
测试名称 |
概述 |
测试考虑方面 |
认定的类的测试 |
认定的类:可以是OOA中认定的对象,或对象所需要的服务的抽象、对象所具有的属性的抽象。认定的类尽量具有基础性,便于维护和重用 |
(1) 是否涵盖了OOA中所有认定的对象 (2) 是否能体现OOA中定义的属性 (3) 是否能实现OOA中定义的服务 (4) 是否对应着一个含义明确的数据抽象 (5) 是否尽可能少地依赖其他类 (6) 类中的方法是否是单用途 |
构造的类层次结构的测试 |
类层次结构:通常基于OOA中产生的分类结构的原则来组织,着重体现父类和子类一般性和特殊性,在当前问题空间中,主要要求是能在解空间中构造全部功能的结构框架 |
(1) 类层次结构是否涵盖了所有定义的类 (2) 是否体现了OOA中所定义的实例关联 (3) 是否实现了OOA中所定义的消息关联 (4) 子类是否具有父类没有的新特性 (5) 子类间的共同特性是否完全在父类中得以体现 |
类库的支持的测试 |
类库的支持:也属于类层次结构的组织问题,但重点是再次软件开发的重用。作为高质量类层结构的评估 |
(1) 一组子类中关于某种含义相同或基本相同的操作,是否有相同的接口 (2) 类中方法的功能是否较单纯,相应的代码行是否较少(<30) (3) 类的层次结构是否是深度大,宽度小 |
因为OOA、OOD阶段分析和设计的模型不能进行测试,不能被执行,所以每次迭代后要进行评审,针对两个方法:正确性、一致性 |
正确性:主要在于分析和设计模型表示所使用的符号语法是否正确,语义是否正确以及类的关联(实例间的联系)是否正确地反映了真实世界对象间的关联 |
|
一致性:OOD和OOA模型(分析、设计和编码层次即类、属性、操作、消息)要一致,可以用模型内各实体之间的关联性判断;评估方法:检查每个类与其他类的连接,采用CRC(类-责任-协作者)模型和对象-关系图 CRC模型:由CRC索引卡片构成,卡片中列出类名、类的操作、以及其他协作类,类完成的责任 对象-关系图:提供了类之间连接(关系)的图形表示 |
||
评估类模型,采用步骤 (1) 再次考察CRC模型和对象-关系模型,进行交叉检查,保证OOA模型所包含的协作都能体现 (2) 检查每个CRC索引卡片的描述,以确定是否某被授权的责任是协作者定义的一部分 (3) 反转该连接,保证每个被请求的服务的协作者正在接收来自合理源的请求 (4) 使用在(3)的反转连接,确定是否可能需要其他的类,或责任是否被合适地在类间分组 (5) 确定是否被广泛请求的责任可被组合为单个的责任 (6) 步骤(1)~(5)被迭代地应用到每个类,并贯穿于OOA模型的每次演化中 |
||
创建设计模型,应对系统设计和对象设计进行复审 系统设计:描述构成产品的子系统、子系统分配到处理器的方式,类到子系统的分配;通过检查在OOA阶段开发的对象-行为模型,和映射需要的系统行为到被设计用于完成该行为的子系统来进行复审。在系统行为语境中复审并发性和任务分配,评估系统的行为状态以确定哪些行为为并发存在 对象模型:表示了每个类的细节和实现类间的协作所必须的消息序列活动;针对对象-关系网络来测试,以保证所有设计对象包含为实现每张CRC索引卡片定义的协作所必须的属性和操作 |
3. 面向对象编程(OOP)的测试
(1) 面向对象程序
把功能的实现分布在类中,能正确实现功能的类,通过消息传递来协同实现设计要求的功能。将出现的错误精确的确定在某一具体的类上。
(2) 测试重点
忽略类功能实现的细则,将测试的目光集中在类功能的实现和相应的面向对象程序风格上
(3) 测试方面(c++为例)
测试方面 |
概述 |
数据成员是否满足娄据封装的要求 |
数据封装:是数据和数据操作的集合 基本原则:检查数据成员是否被外界(数据成员所属的类或子类以外的调用)直接调用。当改变数据成员的结构时,是否影响了类的对外接口,是否会导致相应的外界必须改动 |
类是否实现了要求的功能 |
类所实现的功能是通过成员函数执行的,应首先保证成员函数的正确性 单独看待成员函数,可以使用面向对象单元测试方法 类成员函数间的作用和类之间的服务调用,需要进行面向对象集成测试 注:测试类的功能,不能仅满足于代码能无错地运行或被测试类所提供的功能无错,应该以所做的OOD结果为依据,检测类提供的功能是否满足设计的要求,是否有缺陷,必要时还应该参照OOA的结果,以之为最终标准 |
4. 面向对象软件的单元测试
(1) 可以将一些传统的单元测试方法在面向对象软件的单元测试中使用,如等价类划分、因果图、边界值分析法、逻辑覆盖法、路径分析法、程序插桩法,单元测试一般建议由程序员完成
(2) 单元级测试的测试分析和测试用例,规模和难度均远小于对整个系统的测试分析和测试用例,并且对语句应该有100%的代码执行覆盖率。
(3) 设计测试用例选择输入数据的两个假设:
l 如果函数(程序)对某一类输入中的一个数据正确执行,对同类中的基他输入也能正确执行(等价类)
l 如果函数(程序)对某一复杂度的输入正确执行,对更高复杂度的输入也能正确执行
(4) 针对继承性,Brian Marick两方面的考虑
l 继承的成员函数是否都不需要测试:当继承的成员函数在子类中做了改动;成员函数调用了改动过的成员函数的部分这两种情况需要对子类重新测试
l 对父类的测试是否能照搬到子类:可以重新测试或在父类原有的测试要求和测试用例上增加新的测试要求和测试用例,主要针对子类中变动的部分进行测试
5. 面向对象软件的集成测试
(1) 传统的自顶向下或自底向上的集成测试策略在面向对象软件的集成测试中无意义,OO软件的集成测试需要在整个程序编译完成后进行,面向对象程序具有动态特性,程序的控制流无法确定,只能对编译完成的程序做基于黑盒子的集成测试
(2) 面向对象软件的集成测试两种策略
l 基于线程的测试(Thread based testing):集成对响应系统的一个输入或事件所需的一组类,每个线程分别进行集成和测试,应用回归测试以保证没有产生副作用。
l 基于使用的测试(Use based testing):通过测试那些几乎不使用服务器类的的类(独立类)而开始构造系统,在独立类测试完成后,下一层中使用独立类的类(依赖类)被测试,这个依赖类层次的测试序列一直持续到构造完整个系统。
(3) 测试目的
能够检测出相对独立的,单元测试无法检测出的,那些类相互作用时才会产生的错误,只关注于系统的结构和内部的相互作用
(4) 面向对象软件的集成测试过程
l 第一步:静态测试 针对程序的结构进行,检测程序结构是否符合设计要求。通过使用测试软件的‘可逆性工程’功能,得出源程序的类系统图和函数功能调用关系图,与OOD结果相比较,检测程序结构和实现上是否有缺陷,检测OOP是否达到了设计要求
l 第二步:动态测试 根据静态测试得出的函数功能调用关系图或类关系图作为参考,按照如下步骤设计测试用例,达到如下测试覆盖标准
v 设计测试用例步骤:选定检测的类,参考OOD分析结果,确定出类的状态和相应的行为;确定覆盖标准;利用结构关系图确定待测类的所有关联;根据程序中类的对象构造测试用例,确认使用什么输入激发类的状态,使用类的服务和期望产生什么行为等,还要设计一些类禁止的例子,确认类是否有不合法的行为产生
v 覆盖标准:达到类所有的服务要求或服务提供的一定覆盖率;依据类间传递的消息,达到对所有执行线程的一定覆盖率;达到类的所有状态的一定覆盖率等
6. 面向对象软件的确认和系统测试
(1) 系统测试:需要测试它与系统其他部分配套运行的表现,以确保在系统各部分协调工作的环境下软件也能正常运行
(2) 要求:测试环境尽量与用户实际使用环境相同,保证被测系统的完整性,对暂时没有的系统设备部件,应采取相应的模拟手段。参考OOA分析结果,检测软件是否能够完全‘再现’问题空间
(3) 不仅是检测软件的整体行为表现,另一方面对软件设计开发的确认。OO软件的确认和系统测试具体的测试内容与传统的系统测试基本相同,包括:功能测试,强度测试,性能测试,安全测试,易用性测试,恢复测试,安装/卸载测试
三.OO软件测试用例设计原则(Berard)
关注于设计合适的操作序列以测试类的状态
1. 对每个测试用例应当给予特殊的标识,并且还应当与测试的类有明确的联系
2. 测试目的应当明确
3. 应当为每个测试用例开发一个测试步骤列表,列表包含内容
l 列出所要测试对象的说明
l 列出将要作为测试结果的消息和操作
l 列出测试对象可能发生的例外情况
l 列出外部条件,为了正确对软件进行测试所必须有的外部环境的变化
l 列出为了帮助理解和实现测试所需要的附加信息
四.OO软件测试的方法
1. 基于故障的测试
(1) 具有较高的发现可能故障的能力
(2) 从分析模型开始,考察可能发生的故障,设计用例去执行设计和代码
(3) 可用于集成测试,发现消息联系中‘可能的故障’(可能的故障指意料之外的结果、错误地使用了操作/消息、不正确地引用等)
(4) 除用于操作测试外,还可用于属性测试,用以确定其对于不同类型的对象行为是否赋予了正确的属性值
(5) 是从客户对象(主动)上发现错误
(6) 不能发现的错误:不正确的规格说明,用户不需要的功能或缺少用户需要的功能;没有考虑子系统间的交互作用
2. 基于场景的测试
(1) 主要关注用户需要做什么,不是产品能做什么,即从用户任务(使用用例)中找出用户要做什么及如何去执行
(2) 有助于在一个单元测试情况下检查多重系统,比基于故障的测试更实际,更复杂一点
3. OO类的随机测试
如果一个类有多个操作(功能),这些操作(功能)序列有多种排列,这种不变化的操作序列可随机产生,用这种可随机排列来检查不同类实例的生存史,称为随机测试
4. 类层次的分割测试
(1) 可以减少用完全相同的方式检查类测试用例的数目,类似于等价类划分
(2) 分类:基于状态的分割、基于属性的分割、基于类型的分割
l 基于状态的分割:按类操作是否会改变类的状态进行分割(归类)
l 基于属性的分割:按类操作所得到的属性来分割(归类)
l 基于类型的分割:按完成的功能分割(分类),如初始操作、计算操作、查询操作
5. 由行为模型(状态、活动、顺序和合作图)导出的测试
状态转换图(STD)可以用来帮助导出类的动态行为的测试序列,以及这些类与之合作的类的动态行为测试用例,根据状态转换图,设计出最小测试用例,加入其他测试序列到最小测试序列中,保证类所有行为被充分检查
总结:
本章主要讲述了面向对象软件的测试方法,依据面向对象软件开发模型划分面向对象测试模型,其中单元测试、集成测试、确认测试和系统测试通过与传统的单元测试、集成测试和确认测试、系统测试进行比较,得出面向对象软件的测试内容