(计算机软件与理论专业论文)类和类簇测试的研究.pdf_第1页
(计算机软件与理论专业论文)类和类簇测试的研究.pdf_第2页
(计算机软件与理论专业论文)类和类簇测试的研究.pdf_第3页
(计算机软件与理论专业论文)类和类簇测试的研究.pdf_第4页
(计算机软件与理论专业论文)类和类簇测试的研究.pdf_第5页
已阅读5页,还剩57页未读 继续免费阅读

(计算机软件与理论专业论文)类和类簇测试的研究.pdf.pdf 免费下载

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

类和类簇测试的研究 【摘要】 面向对象测试是面向对象技术中非常重要的研究内容。与非面向对象语言相 比,面向对象语言中的封装、继承和多态等机制给测试带来了新的问题和困难。 因此,我们需要根据这些机制,对传统的软件测试技术进行改进,或者提出新的 软件测试技术,更好地满足软件开发过程中质量保证的需要。 本文主要对面向对象软件中的类测试和类簇测试进行研究。首先研究类测 试,重点在利用扩展的o s d 图。产生有效的方法调用序列,来进行类内数掘流 的测试。接下来,考虑面向对象技术中继承关系的测试。我们研究了针对面向对 象语言的缺陷故障模型,并从增量式的角度来看待继承关系:根据对继承和多 态关系的故障的分析。提出一些旨在提高软件质量的编码规范。文章的最后,对 类簇坤各个测试级别的测试优先级进行了研究。我们综合考虑了静态依赖,动态 依赖和抽象类对测试优先级的影响,并设计了一个以u m l 类图为输入,自动产 生测试级别并计算他们的优先级的j a v a 实现框架。 【关键字】软件测试,对象状态图继承修饰符,缺陷故障模型,测试级别 测试优先级 r e s e a r c ho n t e s t i n g o fc l a s sa n dc l a s sc l u s t e r 【a b s t r a c t o b j e c t o r i e n t e dt e s t i n g i so n et h em o s ti m p o r t a n tr e s e a r c ha r e ao fo b j e c t o r i e n t e d t e c h n o l o g i e s c o m p a r e dw i t h t r a d i t i o n a lp r o g r a m m i n gl a n g u a g e s ,n e wm e c h a n i s m se l o b j e c t o r i e n t e dt e c h n o l o g i e ss u c h a se n c a p s u l a t i o n ,i n h e r i t a n c ea n dp o l y m o r p h i s m c o n f r o n tu sw i t hn e w p r o b l e m s a n d c h a n l l e n g e s h e n c e w eh a v et o i m p r o v e t r a d i t i o n a ls o f t w a r et e s t i n gm e t h o d so rp r e s e n tn e wt e s t i n gm e t h o d sb a s e do nt h e s e f e a t u r e st om e e tt h er e q u i r e m e n to f q u a l i t ys o f t w a r e t h i st h e s i sf o c u s e so nt h et e s t i n go fc l a s sa n dc l a s sc l u s t e ri n o b j e c t o r i e n t e d t e c h n o l o g i e s f i r s t o fa l l ,w e p r e s e n t a ne f f e c t i v em e t h o dt o p r o d u c e m e t h o d s e q u e n c e sb a s e do ne x t e n d e do s dd i a g r a m t h e s es e q u e n c e s c a l lb eu t i l i z e di n i n t r a - c l a s sd a t af l o w t e s t i n g t h e n ,w e m o v eo nt ot h e t e s t i n g o fi n h e r i t a n c e r e l a t i o n s h i pb e t w e e r ic l a s s e s a no b j e c t o r i e n t e df a u l t f a i l u r er f i o d e l i si n t r o d u c e d ;i n a d d t i o n ,w ea l s oa n a l y z e ds o m et y p i c a l f a u l t s p r o d u c e d d u et oi n h e r i t a n c ea n d p o l y m o r p h i s m a sar e s u l t ,w ep r e s e n ts o m eg o o dc o d i n gp r a c t i c e sa i m i n gt oa v o i d t h e s ed a t aa n o m a l ya n db e h a v i o ra n o m a l y l a t e ro n ,w ei n t r o d u c e dt h ec o n c e p to ft e s t l e v e io fac l a s si nac l u s t e r s t a t i cd e p e n d e n c e ,d y n a m i cd e p e n d e n c ea n da b s t r a c tc l a s s a r ea l lt a k e ni n t oa c c o u n tw h e nt h ep r i o r i t yo ft h et e s tl e v e l sa r ec a l c u l a t e d b a s e do n t h et h e o r e t i c a lr e s u l t ,w ed e s i g na ni m p l e m e n t i o nf r a m e w o r kt od e f i n i t et e s tl e v e l sa n d t h e nc a l c u l a t et h e i rr e l m i v ep r i o r i t y 【k e y w o r d 】s o f t w a r et e s t i n g ,o b j e c t s t a t ed i a g r a m ,m o d i f i e r f a u l t f a i l u r em o d e t e s t i n gl e v e l ,t e s t i n gp r i o r i t y 第一章引言 近十几年来,由于面向对象技术具有易于设计、编程和复用等优点,它得到 了越来越广泛的应用。在面向对象分析、设计技术以及面向对象的程序设计语言 方面,均获得了很丰富的研究成果,与之相比,面向对象软件测试技术的研究还 相对薄弱。 封装、继承、多态是面向对象程序设计语言与其它语言相比最为有利之处, 它使程序具有很大的灵活性,特别是当用户需求变动时,设计良好的面向对象程 序变动很小。与传统软件相比,面向对象软件的这些新特征虽然可以提高软件的 开发效率,但是它们引起的信息分散性,使得控制和数据跟踪更加复杂,增加了 软件质量保证的难度,为测试带来了新的挑战。 软件测试是为了发现软件中的错误,使用一定的输入组合,执行代码的过程。 测试的范围必须是一个可执行体。在面向对象程序中,个类的对象是埕小的可 执行单元,因此,类测试是面向对象测试中最基本的部分,很多人也把它称为单 元测试。传统的单元测试是指对一个函数或一个过程的测试。但是,类测试却比 传统的单元测试包括更多的内容,它包含三个级别的测试:方法内的测试,方法 间的测试,以及类内测试【h a r r o l d + 9 4 1 。 本文主要对类和类簇的测试进行研究。研究的内容包括以扩展的o s d ( 对象 状态图) 为基础进行方法闻的数据漉烈试;对继承与多态的增量式测试;产生类 簇中类的测试级别并计算各个测试级别的优先级。研究的范围,从小到大依次为: 类,继承和多态关系中的类,类簇。文章的具体组织结构如下: 在第二章,我们首先介绍了一些与软件测试紧密相关的概念,然后分析了面 向对象的特征以及它们对软件测试带来的挑战,最后根据后文的需要,对当前面 向对象测试研究的现状进行了有选择性的介绍。在第三章,首先对对象的状态进 行了介绍,并给出了一个严格的定义,随后以对象的状态转换图为模型,对基于 责任的测试和基于数据流的测试进行研究。给出了一个产生用于类内数据流测试 的方法调用序列的算法。在第四章,对继承关系的类测试进行了研究。首先提出 了一个针对实现继承和多态的缺陷故障模型,然后用增量式的方式对继承关系 进行了分析。接着研究了一些由继承和多态引起的缺陷,最后根据这个缺陷模型, 以j a v a 语言为例,提出了与多态和继承紧密相关的一些编码规范。在第五章中 首先提出了类簇中类的测试级别和他们的测试优先级的概念,并且定义了不同测 试级别之间的一个拟序关系:为了更好地处理可能存在的抽象类,我们为测试级 别中每个类提供了详细的信息,表明该类在测试级别中的角色;以此为基础,对 抽象类在测试级别的角色进行分析,删除所有不可行的测试级别:这章的最后 详细介绍了对该过程进行自动化的实现框架。 第二章测试和面向对象软件 2 1 软件测试的相关定义 1 9 7 2 年在美国的北卡罗来纳大学召开了首次软件测试的正式会议。会后, 软件测试的研究进入了一个重要时期。j b ,g o o d e n o u g h 和s l g e r h a r t 【g o o d e n o u g h + 7 5 】率先提出了软件测试的理论,从而把软件测试这一实践性 很强的学科提高到理论的高度,被认为是软件测试技术发展过程中最有开创性的 工作之一。e j w e y a k e r 【w e y u k e r8 3 】修正了上述理论中的缺陷:w e h o w d e n 【h o w d e n8 7 】等对它们加以进一步的孝i 充和完善。 遵从i e e e a n s i 标准,软件测试是为了发现错误,选择一定的输入和状态的 组合,势执行被测试代码的过程。它分析被测试系统,判断怎样可能是错误的。 测试的实现必须结合被测系统的实际接口、结构以及系统的运行环境进行设计。 一个测试的范围是要被验证的软件的集合。因为测试必须在一个可执行的软件实 体上运行,因此,它所定义的范围一般应当与某个可执行的构件或者构件系统相 对应。被测试的代码称为被测实现( i u t ) ,被测方法( m u t ) ,被测对象( o u t ) , 被测类( c u t ) ,被测系统( s u t ) 等等。软件测试一般根据i u t 的范围及测试 设计方法来分类。传统上一般将范围指定为单元( u n i t ) ,集成 i n t e g r a t i o n ) 或系统 ( s y s t e m ) 。 一个单元测试的范围通常是由一个相对小的可执行体组成。在面向对象的程 序设计中,一个类的对象是一个最小的可执行单位。一个测试单元可由一个类, 若干个相关类( 类簇) ,或一个可执行的二进制文件组成。典型情况下,它是一 个相互依赖的类簇。 一个集成测试的范围是软件和硬件单元的一个完整系统或者子系统。所包括 的单元实际上是相互依赖或必须共同合作以满足某种需求的单元。集成测试检测 的是在特定范围内单元之间的接口,以证明这些单元都是集体可操作的。由于一 个类可以由其它类的对象组成并继承其父类的特征,集成测试在面向对象软件的 编程中应尽早地开始。从集成测试的定义我们可以看出,在面向对象中,单元测 试和集成测试的区分并不是十分严格,例如类簇的测试就既可看成单元测试也可 看成集成测试。 一个系统测试的范围是一个完全集成了的应用。测试的焦点集中在整个系统 的能力和特性上。被测试系统的边界通常包含实际支持它的虚拟机以及其它有直 接或者间接接口的应用系统。在系统范围内的测试可根据它们试图需要建立的适 应环境的类型来分类:功能测试( 输入输出) ,性能测试( 响应时洲和资源利用 率) ,强度或负载测试( 在最大情况下或超负载时的响应) 。 根据测试目的的不同,通常将测试分为故障制导( f a u l t d i r e c t e d ) n i j 试和一致性 制导( c o n f o m a a n c e d i r e c t e d ) 测试。当测试的目的是从失败中发现故障时,测试是 故障制导的。当其目的是证明符合要求的能力时,测试是一致性制导的。这些目 标并不是相互排斥的,许多测试设计技术是二者兼顾的。单元测试和集成测试通 常更趋向于故障制导,而系统测试更趋向于一致性制导。 测试实例详细说明了i u t 的预测试状态及其环境,测试的输入、条件以及 预期结果。预期结果详细说明了i u t 根据测试输入应该产生的结果。这种详细 说明包括由i u t 产生的消息,异常,返回值和i u t 的结果状态及其环境。测试 实例也可用来说明构成i u t 及其环境的其它对象的初始条件和终止条件。 测试点是值域空间中的一个“点”,是测试实例输入和状态变量的一个特定 值。一个测试点可能用在许多测试实例中。值域是i u t 可以取得的输入变量或 状态变量的值的集台。一些著名的启发式的选择测试点的方法包括:等价类法、 边界值分析法以及特殊值测试法【m e y e r 7 9 】 测试包是测试实例的集合。通常这些测试实例是与一个测试目标或实现依赖 相关。测试运行是测试包的执行。测试计划是为进行测试所准备的文档,它解释 了测试方法,工作计划,一般过程,对测试设计的解释等。 当一个测试实例应用于i u t 是,i u t 将产生实际结果。这些结果包含了由 i u t 产生的消息,异常,返回值以及i u t 及其环境的结果状态。一个测试的实际 结果如果与预期结果相同,我们就说通过了测试,否则说未通过测试。一个未通 过的测试揭示了错误的存在因而是成功的测试,尽管实际结果代表了应用的失 败。 测试驱动器( d r i v e r ) 是一个类或者是一个将测试实例应用于一个i u t 的应 用程序。一个测试桩是一个软件实体,例如一个类或对象,部分的、暂时的执行。 它可能被当作一个不完善的软件实体的代替者或实现测试支持的代码。测试消息 是测试驱动器中的代码,在测试的时候它被发送给某个对象的一个方法。两个或 多个连续的测试消息组成了一个测试序列。测试脚本是一个用过程脚本语言( 通 常是解释的语言) 编写的程序,该程序用来执行一个测试包。 2 。2 面向对象软件特征对软件测试的影响 面向对象技术的本质是定义了类的抽象,将变量和与作用于它的操作封装到 一块。然后用不同的类和方法组合成一个对象系统。面向对象软件将传统软件中 4 一个过程或一个方法内的复杂性转移到对象之间的交互中。从测试角度来看,面 向对象软件的方法通常由较少的代码组成,所以控制流的错误可能更少;封装防 止了一些非面向对象语言中由于全局数据域和模块问的副作用而导致的错误。但 是,在减少了一些错误的同时,它也增加了一些其它错误的可能;面向对象语言 一些本质特征形成了如下的一些新的故障、错误风险: 2 2 1 封装对测试的影响 封装是指在词法单位之中或之间决定名字可见性的访问控制机制。访问控制 隐藏了一些信息,使客户类不必依赖于服务类的实现。这就支持了信息的隐蔽和 模块化,有助于防止全局变量访问的问题。 尽管封装不会直接促成错误的发生,它却给测试带来了障碍。由于面向对象 的软件系统由一组协调工作的对象组成,对象具有一定的状态,所以对面向对象 的程序测试来说,对象的状态是必须考虑的因素,测试应涉及对象的初始状态、 输入参数、输出参数以及对象的终态【d o o n g + 9 3 】。通常对象的行为是被动的, 它往往在接收到有关消息之后才被激活来进行所请求的工作,并将结果返回给消 息发送对象,在工作过程中对象的状态可能被修改,产生新的状态。面向对象软 件测试的基本工作就是创建对象( 包括初始化) ,向对蒙发送一系列消息然后检 查结果对象的状态,看其是否处于正确的状态。问题是对象的内部状态往往是隐 蔽的,如果类中未提供足够的存取函数来表明对象的实现方式和内部状态,则测 试者必须添加这样的函数。因此,类的信息隐蔽机制给测试带来困难。 2 2 2 继承对测试的影响 继承也是面向对象语言中的一个本质特征。继承可用于一般与特殊关系,并 且方便编码。但是,继承削弱了封装性,产生了类似于非面向对象语言中全局数 据的错误风险。由于继承的作用,一个函数可能被封装在具有继承关系的多个类 中,子类中还可以对继承的特征进行覆盖或称为重定义。问题是,未重新定义的 继承特征是否还需要进行测试昵? 重新定义的特征需要重新测试是显然的。但应 该如何测试重新定义的特征呢? w e y u k e r 曾经提出了l1 条基于程序的测试数据集的充分性公理【w e y u k e r 8 6 】。他提出的非外延性公理认为若有两个功能相同而实现不同的程序,对其中 一个是充分的测试数据集未必对另一个是充分的。这一公理表明若我们在子类中 重新定义了某一继承的方法,即使两个函数完成相同的功能,对被继承方法是充 分的测试数据集未必对重新定义的方法是充分的。 一般多重修改公理认为若两个程序具有相同的语法结构,对一个程序是充分 的测试数据集未必对另一个是充分的。这一公理告诉我们,在多重继承的情况下, 从两个不同的父类中所定义的同名的特征中按不同的优先级( 或选择方式) 在子 类中仅选择保留一个版本时,即使所得到的子类的结构与父类相同,但仍然可能 需要不同的测试数掘集。这里必须指出的是,在w e y u k e r 原来的公理中,两个程 序具有相同的语法结构是将一个程序中的若干关系运算符、常数和算术运算符替 换后得到的一个语法正确的程序。 不可分解性公理认为个程序进行过充分的测试,并不代表其中的成分都得 到了充分的测试。因此,若一个类得到了充分的测试,当其被子类继承后,继承 的方法在子类的环境中的行为特征需要重新测试。 非复合性公理认为一个测试数据集对于程序中的各种程序单元而言都是充 分的并不表示它对整个( 集成后的) 程序是充分的。这一公理表明,若我们对父 类中某种方法进行了重定义,仅对该方法自身或其所在的类进行重新测试是不够 的,还必须重新测试其他相关的类( 如子类和引用类) 。 在【p e r r y + 9 2 】,p e r r y 和k a i s e r 认为封装和继承并未简化测试问题,反而使 测试更加复杂。 2 2 3 多态对测试的影响 多态性是指一个引用可以与多个对象绑定豹能力。多态服务类能减少客户类 代码的复杂性和规模,同时还可以实现动态绑定。因此,它可以带来紧密、精美、 可扩展的代码。但是它往往也是面向对象测试中问题的所在。 依赖于不规则的类层次的动态绑定可能产生编程人员没有想到的结果。多态 消息中每个可能的绑定都是一个单独的计算。某一些绑定能正确地工作并不能保 证所有的绑定都能正确地运行。以后绑定的对象可能很容易将消息发送给错误的 类,执行错误的功能。此外,它还可能导致一些与消息序列和状态相关的错误。 作者将在第四章对该问题进行更详细的研究。 2 3 面向对象软件测试研究现状 软件测试一般需要经过阻下步骤:选择合适的测试模型、定义合适的测试覆 盖模型、利用该覆盖准则构造测试用例、测试和测试结果的评估、修改错误、进 行回归测试。面向对象软件测试的有效性,必须由三条基本原则来指导: - 特有的错误风险测试设计必须基于错误风险,这种错误风险对于面向 对象的范型来说是特有的。 6 一面向对象的测试自动化特定应用的测试工具必须是面向对象的,而且 对面向对象编程范型可测试性方面的障碍进行了弥补。 测试过程的有效性测试过程必须适合于重复和增量的开发以及新模块 的嵌入。面向对象范型的本质结构要求测试设计应同时考虑方法、类和 类簇的范围。 鉴于论文后面的需要,作者只对它们进行有选择性的介绍。 2 3 1 用于测试的模型 测试可以看成一个搜索问题。我们要在数百万计的输入以及各个对象的状态 组合中,寻找那些极少数的能够发现错误的状态及其组合。在这种规模下,蛮干 是无能为力的。我们的查找必须是系统的,集中的和自动的。基于模型的测试满 足上述三点【b e i z 6 r9 0 】【b i n d e r9 9 】。 测试设计在最大抽象上是对被测系统必须保持的关系的确定、分析和说明。 一个测试模型对这些关系进行了记录,它是无二义性的并且和可能的错误相联 系,此外它还支持简洁测试包的自动产生。面向对象的建模技术的介绍可以在 【w i l k e9 3 】中找到,更详细的研究在 g r a b a m9 4 1 中。 目前常用于测试的模型有三种:组合模型,状态机,u m l 图。 许多应用必须根据输入条件的组合来确定输出动作。这种要求可能出现在方 法、类、簇、子系统和测试用例中。组合模型对这种条件一动作关系提供了一个 有效的测试模型。 基于状态的测试非常适合于面向对象软件。将实例变量和方法包装成一个类 是面向对象编程的基础。在消息序列中发生的交互作用,依赖和约束总称为行为。 在实际应用中,虽然消息序列和实例变量值的组合是无限的,但是状态机完全可 以对行为提供一个简洁的有预测性的模型。对复杂行为的设计和测试,状态机是 一个有效的基本技术。 测试设计在最大抽象上是对被测系统必须保持的关系的确定、分析和说明。 一个测试模型应该记录这些关系。这个模型应该是无二义性的,并支持简洁测试 包的自动生成。除了组合逻辑模型和状态机以外,经过扩展的u m l 图也是满足 这些需求的【b i n d e r9 9 】。 2 3 2 基本的测试方法 1 ) 基于责任的测试方法 通过分析软件的需求和功能规约来选择和产生数据。这中方法又称为基于规 格说明的测试、基于规约的测试、功能测试、黑盒测试。 类责任的概念第一次使用是为了对面向对象系统进行分析和设计而提出来 的,这种观点认为,通过想办法组织对象的行为达到设计。这个过程设想对象作 为独立的代理而被简化。这些代理相互合作完成总体的系统需求。这样,每个代 理负责了解某些事情,响应其它代理的请求,向其它代理发送请求。 一个责任经常是作为一个简单的动词短语来叙述,并通过一个方法或者一个 特殊的方法序列实现。 一 在面向对象中,“责任”的概念意味着任何由类提供的公共服务都可被定 义而不用关心特定的实现。在一介类中,责任的聚合称为类契约。一个 ,类契约通过在方法中和类中的断言、继承的断言和异常来定义。 一每个服务方法有一个前置条件断言,它检查客户发的消息。满足前置条 件是客户类的责任。 每个服务方法有一个后置条件断言,它检查对象的结果状态和对象提供 给客户的响应,一个后置条件断言定义服务在完成某请求后应该允诺什 么。满足该标准是服务类的责任。 _ 每个类有一个不变量,它定义该类产生对象的变量值的合法组合。该不 变量在每个前、后置条件中都应该被检查。满足该不变量是服务类的责 任。 从父类的客户类角度来看,一个子类的契约必须与它的所有父类的契约 一致,这样一个子类对象可替换父类的对象,而不会导致错误或者要求 客户端特殊的分情形代码。 _ 服务类期望客户处理异常是类契约的一部分。 面向对象系统由一组协调工作的对象组成,对象具有一定的状态,因此,对 于面向对象软件的测试,对象的状态是必须考虑的因素。在【k u n g 十9 3 】中, d k u n g 等通过一个很有启发意义的例子非正式地介绍了类的状态和基于类的状 态的测试的概念。基于状态的测试就是一种基于规约的测试,它可以用有限状态 机作为测试模型。 。 b i n d e r 在【b i n d e r9 9 1 中对有限状态机可能产生的错误进行了分析,他们包括控制错误 和不正确的复台行为。一个控制错误允许一个不正确的时间序列被接受或产生一个 不正确的输出动作序列。对任意给定的规约,虽然有大量的错误实现存在,但相 对来说一般只有几种控制错误。如果不在设计和实现阶段采取谨慎的措施,个 子类很容易与它的一个或几个超类的顺序要求发生冲突。如果测试被限制在一个 类的局部范围内,子类和超类的相互作用而产生的错误是不可能被发现的。详细 情形见【b i n d e r9 9 】。 2 ) 基于实现的测试 基于实现的,以源程序为基础的测试通过对源程序的分析来产生或选择测试 数据。基于实现的面向对象测试大多是建立在传统的测试技术之上的,并结合面 向对象技术的特点加以改进的。考虑到本文的需要,我们仅介绍数据流的测试。 在【h a r r o l d + 9 4 】中,h a r r o l d 和r o t h e r m e l 把对类的数据流测试分成三个级 别: 方法内的测试i n t r a m e t h o dt e s t i n g 对单个的成员方法内的数据流测试。这个 级别的测试相对于传统的对过程性测试中的单元测试。因此,在此对它不作过多 研究。 方法间的测试i n t e r m e t h o dt e s t i n g 对类中方法和它直接或间接调用的方法之 间的数据流进行测试。这种在传统的测试中,它已属于集成测试的一部分。 类内测试i n t m c l a s st e s t i n g 对类中各个方法之问的交互进行测试。这种交互 是由客户代码对该类对象的连续调用而引起的。例如,如果类c 有公有方法 m 0 ,n 0 ,即便它们之间没有相互调用关系,由于客户代码在产生了c 的一个对象 o 后,可能连续调用了o m ( ) 和o n 0 ,此时我们要对m ( ) 和n o 之间的交互进行 测试。与方法间的测试不同的是这种交互是不确定的。由于用户对对象的调用的 不确定性,这部分的测试是非常复杂的。这也超出了传统测试所覆盖的范围。这 个级别的测试是为了确保方法调用序列能够恰当的交互。 类的测试大部分的工作集中于基于规格说明的黑盒测试,而黑盒测试并不能 保证充分的代码覆盖,因此我们需要基于代码的方法对它们进行补充。数据流分 析就是这样的一种方法,其核心是对定义一引用对的分析。相对类的三个测试级 融亳三个皱烈镪定义一弓鼠对:方法内的定义一弓f 屠对,方法闽的定义一引雳对 类力移毫逆一罗f 够秽 h a r r o l d + 9 4 】。我们将对它们进行定义。 定义一应用对:设v 是程序中某一变量,d 是在程序中对变量v 进行赋值( 定 义) 的语句,u 是程序中引用变量v 的语句,并且从定义点d 存在一条执行干净 路径可以到达引用点u ,则称有序对( d ,u ) 是变量v 的一个定义一引用对。所 谓干净路径是指在这条路径上没有对v 进行重新赋值。 方法内的定义一引用对:m 是类的一个公共方法,d “都在m 中,存在客 户程序p 调用m ,并且满足在p 对m 的一次调用过程中,“,“) 是一个被执行的 定义一引用对。 方法间的定义一引用对:m 。是类的一个公共方法,设 m 。,m 。,m m , 为m 。被调用时直接或间接调用的类中的私有方法集,d m ,u m ,其中m , m ,fm 。,m l ,m 。m 。) 。如果存在程序p 调用m 。,使得p 对m 。的一次调用 中甜,“j 是一个被执行的定义一引用对,并且或者m ,m ,或者m ,、m ,为对 同一方法的不连续的两次调用。 类内的定义一引用对:m 。、n 。是类中两个公共方法,设( m l ,m :,m ,j , n 。n ,n 。 分别为m 。、n 。被调用时直接或间接调用的私有方法集,d ,u 分 别属于 m 。,m l ,m 。m 。 , n 。,n l ,n ,。, 中的某个方法。如果存在p 调用m 。n 。,使得口,“) 为p 中的定义一引用对,并且在d 执行后在u 执行 前,对m 。的调用已经终止。 2 3 3 测试覆盖准则 测试覆盖准则是根据被测试软件在有限测试数据上的行为来判断它在所有 的输入数掘上的行为的逻辑基础。是决定被测试软件的测试集是否充分的准则。 如果测试集不充分,必须向测试集中增加更多的测试数据。经过测试后的软件就 可以交付使用。在过去的二十多年中,测试数据充分性准则直是软件测试研究 的重点。1 9 8 6 年w e y u k e r 在其开创性工作中,提出了八条公理【w e y u k e r 8 6 】, 并于1 9 8 8 年在对这些公理分析的基础上补充了三条公理,这1 1 条测试充分性公 理如下: 1 ) 可作用性:对任意的程序均存在充分的测试数据集: 2 ) 单调性:如果测试数据集对一个软件系统来说是充分的,那么再增加一些测 试数据该测试数据集也是充分的; 3 ) 复杂性;软件越复杂,需要的测试用例就越多; ) 甫阻n j 1 “川汁:刘 t :童f 2r j :均f r m 允分的洲试敬甜- ;集: 5 1 非外延性;语义相同的两个程序必须进行不同的测试: 6 ) 非复合性:即使一个测试数据集对软件的所有组成部分是充分的,也不能保 证对整个软件的测试是充分的; 7 ) 重命名性:充分测试的软件被系统地重新命名后,也是充分测试; 8 1 空集不充分性:空测试对任何程序都是不充分的; 9 1 非穷尽可作用性:一些程序存在有限的测试数据集; l0 ) 一般多重修改性:存在语法结构相同的程序p 和q ,它们具有相同的流图, 且流图上的数据流特征也相同,存在测试数据集t 使得t 对于测试p 来说是 充分的,而对于测试q 来说却不充分: 1 1 ) 可分解性:如果一个软件系统整体得到充分测试,并不保证系统各个部分都 已经得到充分测试。 这些原则和公理便于相关测试覆盖准则的比较。目前。通常用测试覆盖准则 来度量测试的充分性。到目前为止,已经提出了许多针对程序内部结构的测试覆 o 盖准则,主要包括控制流测试覆盖准则和数据流测试覆盖准则。控制流测试覆盖 准则包括语句覆盖、分支覆盖、多条件覆盖、路径覆盖和决策覆盖等。数据流覆 盖准则包括定义全部覆盖、引用全部覆盖和定义引用全部覆盖准则等。这些准 则不仅可以定量地规定软件测试需求,指导测试数据的选择,而且可以度量某个 测试集发现软件特定的质量特性的能力,对测试结果和软件可靠性评估具有重要 的意义。 特别地,在 a l e x a n d e r + 9 9 1 中,作者们提出了四个关于数据流测试的覆盖 标准。 调用耦合( c a l lc o u p l i n g ) :测试集所执行的路径必须覆盖被测软件中的所有调 用点。 所有耦合定义( a l l c o u p l i n g - d e f s ) :对一个变量的每个定义点,测试集所执行的 路径必须至少覆盖一条到迭某个可达引用点的路径。 所有耦合引用( a l l - c o u p l i n g - u s e s ) :对一个变量的每个定义点矛nn - j 达引用点,测 试集所执行的路径必须至少覆盖它们之间的一个干净路径。 所有耦合路径( a l l c o u p l i n g - p a t h s ) :对个变量的每个定义点和引用点,测试 集所执行的路径必须覆盖所有的耦合路径。 2 4 小结 本章作为全文的基础,首先介绍了软件测试的一些基本概念,然后讨论了面 向对象技术给测试带来的一些新的问题和挑战。为了便于后面章节的研究,作者 还对软件测试的方法、测试的覆盖准则进行了介绍。 第三章:类的测试 尽管在面向对象技术中,对类的测试的重要性已经不如集成测试,但是作为 面向对裂测试中最基本的单元,类测试还是有着举足轻重的作用。首先它是集成 测试的基础:其次,即使集成测试能够发现类的一些与状态相关的错误,它的难 度和费用也比在类测试中发现这样的错误高多了;两且,得到良好测试的类是类 库、软件重用的基础。 通常情况下,单独的测试一个类是不可行的,因此,i u t 往往包括被测类的 父类和服务对象。为了研究的方便,在本章中作者并没有考虑继承、多态、抽象 类等情形。对它们的讨论和研究将在以后的章节进行。 3 1 对象的状态 面向对象的类测试的一个非常重要的特点就是在进行测试时必须考虑到类 的对象的当前状态对类的成员方法的执行情况的影响。由于执行前对象状态的不 同,同样的一个成员方法可能执行完全不同的功能,在 k u n g + 9 3 】中,d k u n g 等通过一个很有启发意义的例子非正式的介绍了类的状态的概念。 3 1 1 对象状态的概念 我们通过d k u n g 的例子来说明对象状态的有关概念。我们把这个示例程序 放到了本章的附录中。该程序的成员方法,e u r n o t r s 0 中有一个小的错误,正 确的程序应该添加一条语句:a l l o w v e n d = o 。 状态测试是面向对象软件测试的一个非常重要的方面。它与通常的控制流测 试和数据流测试的不同在于它着重于对象的状态依赖于行为而不是控制结构和 个体数据。传统的功能测试和结构测试能够发现一个方法内部的错误,但是对于 在面向对象中常见的由于对象之间或同一个对象内部成员方法的交互所引起的 错误,它们往往是无能为力的。例如在附例的程序中,要发现我们前面提到的错 误必须测试各个成员方法的交互情况。 大家都知道类的本质是属性,成员方法只是定义在这些属性上的操作。在一 个类中,成员方法往往是依赖于某一个或某些数据成员的,可能因为数据成员 的取值不同。同一个方法可能执行完全不同的功能。像这样的能对一个或多个方 法的具体执行路径造成影响的数据成员称为状态变量,如附例中的 2 a l l o w v c l l d c t l l q t r s 。胁像1 0 【1j q l r s 就4 i 足一个状念变量,凶为任何一个成员方 法的具体执行情况都不依赖于它。 那么什么是一个对象的状态昵? 它经常意味着“一个类的组合值的集合中的 一个特定成员”或者仅仅是“一个对象的当前内容”。但是,对实际测试来说, 这个定义过于颓粒化了。即使是一个简单的类,也会产生具有几兆状态的模型。 因此,我们需要给出一个能够体现状态本质的定义。首先我们来研究一个变量的 状态。 一个变量的状态就是该变量值域的一个子集。一个变量的所有状态的集合就 是根据成员方法的行为而对变量定义域进行了一个分划( p a r t i t i o n ) 。假设我们讨 论的类为c ,v 是它的一个变量,v 的定义域为d ,s 。,s s 。为d 的子集。那么 我们称is :s s 。;为v 的状态集当且仅当: 1 s l ,s s 。为d 的一个分划。即对于任意的自然数i , j ( 1 j i k ) 有s ,n s ,= 并且s lu ,s ,u ,u s 。= d 2 对于任意的自然数i j ( k , i k ) ,v 取s ,中的任意两个不同值时, 对象当前可以接收的消息序列是完全一样的;而当v 分别取s ,、s 中 的值时,对于其它所有状念变量而言,必然存在状态使得对象可以接 收的消息序列不同。 其中条件1 就是数学中的分划的概念,而条件2 则是我们作这个分划的依 据。有了这个依据,我们就能够保证在当前状态确定的情况下,任一个成员方法 的执行效果都是唯一被确定的。 一个对象的当前状态指的就是各个状态变量的当前状态的组合。回到附例 中,我们可以看到一个售货机有四种状态( 0 ,o 】, o ,o ) ,( o ,o 】, 1 ,m 】) ,( 1 ,m , o ,0 1 ) , ( 1 ,m 1 ,m ) 。其中,变量的顺序为( a l l o w v e n d ,e u r q t r s ) ,m 表示实现语言里顽 对非负整数的最大值。 一般而言,一个对象的状念的改变是由成员方法的调用所引起的。我们可以 通过确定成员方法执行前的状态( p r e s t a t e ) 和执行后的状态( p o s t s t a t e ) 对它进行 分析。从而可以得到类的状态和状态转化图,附录程序的状态和状态转化图如下: 幽3 i 投币箱的状态和状态转换圈 注意到,如果一个类有k 个状态变量,每个变量又分别有l 。、l ,l 。个状 态,那么该类就有l 。x l ,x l 。个状态。随着变量数以及每个变量状态数的 增加。类的状态的数目的增加是非常快的,实际经验表明在这时使用类状态和状 态转换图基本上是不可行的。因此在【k u n g + 9 3 】中,作者们提出了a o s d ( 原 子对象状态图) ,c o s d ( 复合对象状态图) 的概念。 从传统观点来看,一个状态转换图通常是指对象方法对其状态的改变,而一 个a o s d 可以看成是一个具体的变量的状态和状态转换图,c o s d 是多个具有 并发关系的a o s d 的组合,附例的c o s d 如图3 2 所示。具体构造a o s d 和c o s d 的过程包括符合执行确定一个变量的状态、利用逆向工程确定状态转换等 【k u n g + 9 3 】。 图3 2 投币箱的c o s d 图 在这,我们不对c o s d 的语义进行形式化的定义,只是通过一个例子来解释 它。考虑如图3 3 的c o s d ,它包括三个并发的a o s d 。 , 图3 3 一个o o 系统的并发c o s d 图 假设a 处于状态b ,d 处于状念f ,h 位于处于状态j ,记为( b ,f j ) 。现在 如果变量h 发生一个从j 到i 的转换,那么系统的下一状态将是( c ,g ,i ) 。因为, 在 f 状态转换的过程中,相应的e 方法将得到执行,e 的执行将导致变量d 从状 态f 转到状态g ,变量a 从状态c 转到状态b 。这个时候如果在发生转换n , a o s dh 将会从状态i 变到j ,并且触发a o s d a 中的转换f g ,f g 又触发d 中 的转换g 。 3 。2 基于责任测试的故障分析 在2 3 2 中。我们已经对基于责任的测试的基本概念进行了介绍。在本节中, 我们将针对类的模态性来对它们进行进一步研究。 某些类被设计为接受任何状态下的任何消息,另外一些类基于以前的消息或 者当前状态限制以后的消息顺序。因此,在测试过程中必须认识到这些差异并支 持有侧重点地产生测试实例。模态性是在内容和可接受顺序上对消息序列进行限 制的结果。按照模式对类进行分类有利于注意到很有可能发生的错误。对于测试, 有四种有益的模态性【b i n d e r9 9 】。 非模态性( n o n m o d a l ) 类对接受的消息序列不强加任何限制。例如, d a t e t i m e 类的一个对象会接受任何s e t g e t 的交叉消息。实现基本数据类 型的类通常是非模态的。 单模态性( u n i m o d a l ) 类对可接受的消息序列有限制,但不管消息的内容。 最典型的例子就是t r a f f i c s i g n a l 类了。就测试而言,这是最简单的种 模念,因此,在下文中作者并没进步对它进行讨论。 一准模态( q u a s i m o d a l ) 类随着对象状态的改变对可接受的消息序列进行限 制。例如,一个栈已满,s t a c k 类对象将拒绝一个入栈消息,但在其它情 况下会接受它。 - 模态( m o d a l ) 类对可接受的消息进行顺序和内容的限制。例如,如果帐户 的余额小于等于0 ,a c c o u n t 类对象将不接受一个取款消息。表示问题域 实体的类通常是模态的。 3 2 1 非模态类的故障分析 对消息不进行顺序限制,这样状态控制模型就不那么重要了。因此,基于状 态的测试对模态类并不十分合适。然而,许多与顺序相关的错误还是可能的。通 常的缺陷有: 一拒绝一个合法的顺序。 _ 一个合法的顺序产生一个错误的值 报告抽象状态的方法不一致 拒绝合法的修改消息 _ 接受非法的修改参数,导致错误状态 一个访问方法有更改或破坏对象状态的不正确的副作用。 一错误的计算导致类不变量被破坏。 3 2 2 准模态类的故障分析 一个准模态类有一个顺序限制,这种限制反映了该类所使用的信息组织。有 效的测试必须区别决定行为的内容和不影响行为的内容。它可以作为模态类的一 个特例来处理。 3 2 3 模态类的故障分析 模态类对可接受的消息有消息和内容两方面的限制。当消息序列被限制时, 我们需要验证所有合法状态:在这些状态将要被接受的消息被接受:在这些状态 下非法的消息被拒绝;对接受或拒绝消息所得到的结果状态是正确的:对每个测 试消息的响应是绝对正确的。绝对正确意味着响应与期望的消息相匹配,并且参 数值也落入正常的范围内。通常有以下5 种途径可能导致个类无法实现其状态 模型: _ 遗漏转换:在合法状态下有消息被拒绝。 不丁f 确的动作:对接受的状态和方法选择了错误的响应。 一非法

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论