面向对象软件的实现与测试课件_第1页
面向对象软件的实现与测试课件_第2页
面向对象软件的实现与测试课件_第3页
面向对象软件的实现与测试课件_第4页
面向对象软件的实现与测试课件_第5页
已阅读5页,还剩66页未读 继续免费阅读

下载本文档

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

文档简介

第八章

面向对象软件的实现与测试8.1类级关系8.2类的实现8.3应用的实现8.4测试一个面向对象的应用1软件工程在开发过程中,类的实现是核心问题。在只用面向对象风格所写的系统中,所有的数据都被封装在类的实例中而整个应用则被封装在一个更高级的类中。

2软件工程8.1类级关系当实现类的时候就会遇到类级的关系。一个类的实现常常在某些方面依赖于其它类的实例。类级关系可以是应用级关系的实现,也可以是类内属性的实现。消息组装继承3软件工程1.消息(messaging)在应用程序中,应用级关系大多是以类的实例之间的消息连接方式实现通信的。在消息的参数表中指定消息的接受者(一个类的实例)。还可以通过参数表向接收者提供信息。消息指定一个属于接收者的服务,这个服务应实现该类共有界面规定的行为。看Dictionary类设计的例子4软件工程一个Dictionary是包含一些可按关键码的值排序和检索对象的部件。对于存储在Dictionary内的一个实例来说,类必须提供一个操作来取得关键码。

Dictionaryprivate:contents–aHashTablepublic:add(anItem)词典私有域散列表共有域方法add5软件工程关系

refersto

表示了“一个类引用另一个类”,后者的实例可当作参数在前者发送的消息中使用。由消息构成的流图形成了面向对象系统结构的核心。DictionaryuseraddsDictionaryItemreferto发送消息add,同时把Item的一个实例当作参数发送消息getKey,得到散列所需的关键码6软件工程例如,Dictionary类有一个操作add,该操作将把一个属于Item类的对象item当作参数,把这个对象加入到Dictionary的一个对象中。具体地,add操作首先发送一个消息给做为参数的对象item,再利用它的关键码,到该对象所在的Item类中引用(refersto)相应的实例,把它加入到词典中去。在设计阶段,在两个类之间建立消息连接要求协调这些类的共有界面的定义。7软件工程2.组装(Composition)组装关系是一个实现级关系,它对应于应用级的聚合关系。它也叫做component(构件)或叫做

ispartof(是…的一部分)。组装与消息两者都是类间的关系,在这种关系中,一个类的实例将是另一个类的实现的一部分。考虑Dictionary类的实现。8软件工程在Dictionary中存储item的一种数据表示是使用散列表(HashTable)。进行Dictionary类的低层设计时,要指明在Dictionary类和HashTable类之间的一个

ispartof关系。在实现时,应当在Dictionary类的定义中声明这个HashTable的实例。HashTableispartofDictionary9软件工程3.继承(Inheritance)继承允许在既存类的基础上定义新类。一个新类B继承了既存类A,则B包括了A定义的某些行为,以及它自定义的某些附加行为。有多少种面向对象程序设计语言,就有多少种不同的继承实现方式。10软件工程继承图ABCDEABCDEABCDE11软件工程(1)针对实现的继承两个类之间“针对实现”的继承关系的建立指的是使用既存类的内部表示来做为新类的内部表示的一部分。我们不推荐这种继承方式。考虑使用继承来实现一个Circle类,为了定义一个圆,需要定义一个点和一个值,做为圆的圆心和半径。因此,Point类可支持Circle类的一部分实现。把Point类当做派生类。12软件工程如果Circle类直接使用Point类的数据成员x和y,将失去抽象。而且失去做为一个点的圆心的标识。针对实现的继承一般在原型开发中使用。Pointxy……点坐标Pointxyredius……圆坐标半径13软件工程(2)针对特殊化的继承这种继承的使用适合于大多数面向对象程序设计语言所提供的关系,是针对一般化-特殊化关系的。isa继承关系类B的一个实例是类A的一个实例。在使用中,既存类的界面可成为新类的界面。这表明新类具有它的基类的所有行为。14软件工程containerisastackclassinterfaceLink-basedstackArray-basedstackisanimplementationofisanimplementationofispartofReversePolishNotationEvaluator15软件工程iskindof继承关系这种继承允许有选择地包含既存类的属性,从而建立新的定义。一个鸟类可能有一个关于飞行的属性。一个鸵鸟派生类在模型化时可能就不选择这个属性,因为鸵鸟不会飞。鸵鸟是一种鸟,但具有的属性与鸟不完全相同。iskindof

继承是不严格继承。16软件工程8.2类的实现一种方案是先开发一个比较小的比较简单的类,做为开发比较大的比较复杂的类的基础。即从简单到复杂的开发方案。在这种方案中,类的开发是分层的。一个类建立在一些既存的类的基础上,而这些既存的类又是建立在其它既存的类的基础上。通过诸如“isa”或“ispartof”之类的关系,利用既存代码就能着手建立新的类。17软件工程1.软件库(SoftwareBase)建立软件库的目的是为了引用现成的构件。存储在软件库中的类以多种途径发生关联,同时,库可以追踪这些关联。软件库工具利用这些关联可以有效地进行开发。18软件工程2.复用(Reuse)伴随着类的设计,应当从复用开始着手类的实现。类的设计可以使用各种抽象的类。在类设计期间,还需要建立这些类中的“具体的”对象。一旦一个数据对象被确认是应用所需要的,则必须把它组织成类,以便有效地提交所需要的模型。19软件工程产生所需功能的次序寻找可“原封不动(As_is)”使用的现成的类,提供所需要的特性;寻找可以用做开发新类的基础的现成的类,通过继承演化出新的类;不用任何复用,开发一个新类。20软件工程3.断言(Asserttions)实现类的一个主动方法是把来自类的设计信息直接纳入代码。特别要求把参数约束、循环执行等编入到代码中。这可以通过某些表示断言的语言机制来实现。一个断言就是一个语句,它表达了对一个过程、一个值,甚至一段代码的约束。21软件工程在栈的描述中,可以使用断言来控制进栈和退栈功能的操作:procedurepush(varS:Stack_Type;

New_Item:Item_Type);assert:ThestackSisnotfull

//precondition

…………assert:ThetopofstackScontainsNew_Item

//postconditionend;22软件工程procedurepop(varS:Stack_Type)returnItem_Type;assert:ThestackSisnotempty

//precondition…………assert:ThestackShasonefeweritemsthatitdidonentry

//postconditionend;

前置条件precondition后置条件postcondition23软件工程在C与C++中有一种头文件:

“assert.h”,它支持断言的格式。例如,实现者可以针对pop操作,作出断言如下:

assert(TOP>0)这样,宏就会检查在试图从栈中退出一项之前栈是否空。如果条件测试失败,则会打印出一条消息,报告源文件名及在文件中发生失效的行号。24软件工程4.调试(Debugging)数据封装限定了许多用以修改数据值的手段,也限定了对错误的数据值进行调查以找出真正原因的功能。某些面向对象的程序设计环境支持使用交互工具进行调试。工具包括断点的设置、访问源代码、检查对象(包括修改数据值和表达式求值)及编辑源代码。25软件工程5.错误处理(ErrorHandling)我们期望一个类能够自负错误处理的责任。类的实例负责定位和报告错误。C在错误处理中使用状态码方法。各种不同的状态码的值能够指明任务的执行是成功还是失败,若是失败又是哪种程度的失败。例如,C中函数“fopen”返回的状态码。如果打开失败,则返回零值;如果打开成功,则返回文件的标志。26软件工程使用状态码方法的难点在于:各个程序必须知道它所调用函数的状态码,并能检验这些状态码及采用行动。如果问题的解决在比它发生的那一层更高的一层进行处理,这将产生比预想更高程度的耦合。因此,问题尽可能在它发生的那一层进行处理。例如,在fopen打开文件失败时,如果当前的文件名不存在,软件可以要求用户键入另一个文件名。27软件工程6.内建错误处理

(Built_InErrorHandling)Ada程序员可以利用语言所提供的例外处理机制帮助做错误处理。一个“例外”是做了意料之外的事情的处理。“例外处理器”是一段代码,在一个特定的例外出现时调用。它可以是终止软件的执行;发信号给一个更高层的例外处理器;对问题进行定位处理。28软件工程7.用户定义的错误处理

(User_DefinedErrorHandling)有两种相对简单的错误处理技术,它们提供了打印出错信息和终止软件执行的能力。它们都不允许嵌套的错误处理。第一种技术使用了一个全局错误处理器对象。每一个类都能对这个全局对象进行存取。29软件工程当在一个用户对象中检测出一个错误的时候,就发送一个消息给这个全局对象。这个消息运载了一个字符串,它就是要被打印的出错信息,消息中还有一个整数,它指出错误的严重程度。消息格式为:

ERROR_HANDLER.handle("Messagetobeprinted",1);ERROR_HANDLER将打印消息并终止应用的执行。30软件工程第二种用户定义错误处理的技术要求每个类都定义或再定义一个命名为error的操作。这个操作不应是类的共有界面部分,它应是一个隐蔽的实现部分,可以被一些公共操作调用以检测错误。这种error操作可以打印消息,在适当时候请求一些额外输入,在必要时终止软件的执行。31软件工程8.多重实现

(MultipleImplementation)同一个类可以多种方式实现。为此,软件库必须对库中的每一部分都能保留充足的信息,使得定义能同时关联到不止一个实现。为了定义连接到几个实现所使用的关系。程序员应能指出要求的实例所在的类,并确定所期待的特定实现。32软件工程stackclassinterfaceLink-basedstackArray-basedstackisanimplementationofisanimplementationofstack类的界面关系是…的实现基于数组的栈基于链表的栈33软件工程8.3应用的实现应用的实现是在所有的类都被实现之后的事情。实际上,当把类开发出来时就已经实现了应用。每个类提供了完成应用所需要的某种功能。在C++和C中有一个

main()函数。可以使用这个过程来说明构成应用的主要对象的那些类的实例。34软件工程C++系统中主过程的两个主要职责是建立实例;

通过指针建立对象之间的通信;以图形系统为例,首先建立一个用户界面的单一实例。一旦它建立起来,就发送一个消息,启动绘图程序的命令循环。然后,这个对象担负起在系统寿命的其余时期协调通信关系和对象建立的责任。35软件工程对于纯面向对象的语言,在系统中的每个“事物”都是对象。在这些语言中没有“主过程”。用户建立起一个类的实例,然后,通过实例接受控制和执行服务,产生实例输出的结果或接收由用户发送来的消息。由那些原始消息而产生的消息序列就成为目标软件的功能。36软件工程8.4面向对象测试面向对象系统的测试与传统的基于功能的系统的测试之间存在很大差别:对象作为一个单独的构件一般比一个功能模块大。由对象到子系统的集成通常是松散耦合的,没有一个明显的“顶层”。如果对象被复用,测试者无权进入构件内部来分析其代码。37软件工程面向对象系统的测试可分为4个层次:测试与对象相关联的单个操作它们是一些函数或程序,传统的白盒测试和黑盒测试方法都可以使用。测试单个对象类黑盒测试的原理不变,但等价划分的概念要扩展以适合操作序列的情况。测试对象簇(聚集)严格的自顶向下或自底向上的集成不适合一组关联对象的情形。应使用基于场景的测试等其他方法。38软件工程对象类测试测试面向对象系统根据系统需求规格说明进行检验和有效性验证的过程可以像对其他范型的系统一样进行。在测试对象时,完全的覆盖测试应当包括:隔离对象中所有操作,进行独立测试。测试对象中所有属性的设置和访问。测试对象的所有可能的状态转换。所有可能引起状态改变的事件都要模拟到。39软件工程对象类,作为在语法上独立的构件,应当允许在不同应用中使用。每个类都应是可靠的且不需了解任何实现细节就能复用。因此对象类应尽可能孤立地进行测试。设计操作的测试用例时的要点:首先定义测试对象各操作的测试用例。对于一个单独的操作,可通过该操作的前置条件选择测试用例,产生输出,让测试者能够判断后置条件是否能够得到满足。40软件工程各个操作的测试与传统对函数过程定义的测试基本相同。然后再把测试用例组扩充,针对被测操作调用对象类中其他操作的情况,设计操作序列的测试用例组。测试可以覆盖每个操作的整个输入域。但这不够,还必须测试这些操作的相互作用,才能认为测试是充分的。各个操作间的相互作用包括类内通信和类间通信。41软件工程putReferencePoint(Point)moveTo(Point)ReferencePointarea()draw()erase()getReferencePoint(Point)DisplayableShape(Point)DisplayableShape类内消息类间消息DisplayableShape()42软件工程设计对象类的规格说明测试时的要点:把对象类当做一个黑盒,确认类的实现是否遵照它的定义。对于“栈”的测试应当确保LIFO原则得以实施。对于多数的对象类,主要检验在类声明的public域中的那些操作。对于子类,要检查继承父类的public域和protected域的那些操作。检查所有public域,protected域及private

域中的操作以完全检查对象中定义的操作。43软件工程等价划分的思想也可用到对象类上。将使用对象相同属性的测试归入同一个等价划分集合中。这样可以建立对对象类属性进行初始化、访问、更新等的等价划分。在设计对象类的行为测试时需要注意:基于对象的状态模型进行测试时,首先要识别需要测试的状态的变迁序列,并定义事件序列来强制执行这些变迁。原则上应当测试每一个状态变迁序列,当然这样做测试成本很高。44软件工程对象集成测试当开发面向对象系统时,集成的层次并不明显。当一组对象类通过组合行为提供一组服务时,则需将它们一起测试,这就是簇测试。此时不存在自底向上和自顶向下的集成。完全的单元应当保证类的执行必须覆盖它的一个有代表性的状态集合。构造函数和消息序列(线程)的参数值的选择应当满足这个规则。45软件工程对象集成测试又称交互测试,目的是确保对象的消息传递能够正确进行。面向对象系统的集成测试有3种可用的方法:用例或基于场景的测试用例或场景描述了对系统的使用模式。测试可以根据场景描述和对象簇来制定。这种测试着眼于系统结构,首先测试几乎不使用服务器类的独立类,再测试那些使用了独立类的下一层次的(依赖)类。这样一层一层地持续下去,直到整个系统构造完成。46软件工程基于线程的测试

它把为响应某一系统输入或事件所需的一组对象类组装在一起。每一条线程将分别测试和组装。因为面向对象系统通常是事件驱动的,因此这是一个特别合适的测试形式。对象交互测试这个方法提出了集成测试的中间层概念。中间层给出叫做“方法-消息”路径的对象交互序列。所谓“原子系统功能”就是指一些输入事件加上一条“方法-消息”路径,终止于一个输出事件。47软件工程子类测试在做继承层次的测试时,自顶向下测试比较容易,但如何测试有几种看法:Fielder认为在父类充分测试的基础上,被子类继承的方法只需最小测试。Horrold主张在测试子类时,只需对被继承的属性和新的属性之间的交互进行测试。D.E.Perry和G.E.Kaiser以Weyuker的测试充分性公理为依据,认为子类中继承的方法和重新定义的方法都必须在子类环境中重新测试。48软件工程面向对象的确认测试在确认测试或系统测试的层次上,不再考虑对象类间相互连接的细节。主要着眼于用户可见的动作和用户可识别的系统输出。为了帮助确认测试的执行,测试者需要回到分析时的动态模型和描述系统行为的事件序列(脚本)进行测试。可以利用黑盒测试的方法来驱动确认测试。测试检测软件中的故障并确定软件是否执行了预定要开发的功能。49软件工程面向对象测试用例的设计测试过程包括了一组测试用例的开发,每一个测试用例要求能检验应用的一个特定的元素。还需要分析用各个测试用例执行测试的结果来收集有关软件的信息。软件测试人员可以参考以下方法:应当唯一标识每一个测试用例,并与被测试的类显式地建立关联。陈述测试对象的一组特定状态。50软件工程对每一个测试建立一组测试步骤,要思考和确定的问题包括:被测试对象的一组特定状态;一组消息和操作;考虑在对象测试时可能产生的一组异常;一组外部条件;辅助理解和实现测试时的补充信息。传统的白盒测试方法可用在类定义的操作测试和类级别测试中,黑盒测试方法可用于多类测试。51软件工程分布式系统的测试分布式处理中涉及的最基本单位是线程,线程是操作系统进程内部能够独立运行的内容,它拥有自己的程序计数器和本地数据。线程是能够被调度执行的最小单位。分布式系统测试主要面临的问题是并发性、网络化和分布式。并发性是指多个线程同时发生。针对并发性错误的测试主要着重于两个线程的交互。在实际实施交互机制前应对相关方法进行测试。52软件工程在网络环境中各个独立的盒子连接到通信设施上,如何实现它们物理上的同步是网络计算的问题。相关的测试就是在组成一个网络系统的各个自治机器之间同步问题的测试。分布式系统使用多进程来支持系统的灵活性一个对象既可以在同一台机器上分布在多个进程中,还可以分布在多个物理上的计算机上。所有这些分布式构件都要能够识别“命名服务”或“注册”对象,能够与其他构件交互。所有在配置文件中登记的机器与构件构成基础结构。53软件工程需要考虑与这些分布式构件相关的测试。分布式系统中的路径测试一条路径是一系列逻辑上连续的语句,它只有在特定的输入下才执行。路径的另一个定义是覆盖变量的定义和使用就形成一条完整的路径。路径测试就是设计测试用例覆盖一个同步顺序。所谓同步顺序是指同步事件按照特定次序发生的顺序,而同步事件是指一个线程产生另一个线程。54软件工程测试应跟踪一个事件到另一个事件的路径。如果从一个同步事件到另一个同步事件有多条可能的控制流路径,只需覆盖其中一条路径。生存周期测试在分布式系统中,生存周期测试是指选择一系列测试用例,测试任何处于生存期中的对象。特别是在整个生存周期过程中存在多条路径,测试必须选择有代表性的路径以保证最大的覆盖范围。55软件工程对于一个类来说,生存周期意味着选择一系列测试,每个测试构造类的一个实例,并通过一系列消息来使用实例,最后再撤销这个实例。一个有效的生存周期测试应能证实对象本身是否正确,还应能证实被测试项是否能够与它所在的环境正确地交互。对于一个类的实例,在它被撤销后必须检查它占用的资源是否已被释放掉。56软件工程分布式模型下面讨论用在分布式系统中的使用某些标准基础结构的测试过程。基本的客户机-服务器模型客户机-服务器模型是最简单的分布式模型。在这种模型下,多个客户机都可访问服务器。服务器是单一进程。由于所有客户机都与同一个服务器交互,因此存在单点失败(即服务器出现问题将影响所有客户机)。测试要点:57软件工程在延时期间,面对同时收到的服务请求,服务器能否把正确结果发送给各个相应的客户机?服务器能否处理快速增长的负载?当负载增加时,服务器的性能可能降低,因此可能选择放弃一部分负载。标准分布式模型-CORBACORBA是对象管理组织OMG开发的公共对象请求代理体系结构,并将它作为分布对象系统的标准体系结构。58软件工程这种结构的核心是对象请求代理(ORB),一个对象通过ORB与系统中的另一个对象通信。CORBA标准的特点:与基础结构相联系的机器可能有不同的操作系统和不同的存储设计;构成分布式系统的构件可以用不同的语言编写;根据对象的分布性和网络中机器的类型,基础结构可以改变它自身的配置。测试要点:59软件工程不考虑基础结构的配置,系统能够正确的工作?测试用例应能产生被测试基础结构的各种预期的配置。在标准基础结构的服务基础上,构造新的测试用例能否被重复使用?测试用例的设计应尽可能地使用基础结构。新发布的特定基础结构能否与已有的应有有效地结合起来?应有一系列的回归测试,使得新发布的基础结构能够在被集成到产品中之前得到测试。60软件工程标准分布式模型-DCOMDCOM是Microsoft开发并鼓励的一种标准的分布式构件对象模型。DCOM“标准”被描述为包含特定方法的标准接口,每个标准接口都提供了一套特定的服务。单个构件可以完成几个接口的服务,或若干构件中的每一个都能完成统一接口的服务,只是方式不同。DCOM是低层次的技术,支持构件间最原始的联系,它不作为应用开发的部分。61软件工程测试要点:对各种构件做任意配置时测试者能否正确编排唯一的标识?测试用例应能利用各种构件确保所有必要的连接能够成功。每个构件能否实现必要的接口?测试用例应能利用各种构件确保所有服务是可利用的并能实现期望的功能。标准接口的实现能否提供正确的行为?应针对每一种标准接口有一套测试。标准分布式模型-RMI62软件工程RMI是Java中的远程方法调用包,它提供一种简化的分布式环境,该环境假定不论连接的是什么样的或什么类型的机器,它们都能运行Java虚拟机。RMI提供一个注册对象,参与分布式系统的所有对象必须知道该注册对象监听到哪个端口的消息。RMI的最新版本使用ORB的Internet协议(IIOP),使RMI对象与CORBA对象共同工作。63软件工程测试要点:那些种CORBA测试模式能够在以RMI为基础的系统上使用?测试用例的构造很多与CORBA的测试用例相同。一般分布式构件模型分布式系统的基本体系如图,主要活动是服务请求方给服务提供方法送消息。请求首先发送给请求方本地的代理对象,代理方联系通信基础结构并传送请求,通信基础结构实例化服务提供方,从对象定64软件工程服务请求方提供方代理提供方代理服务提供方通信和定位服务

温馨提示

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

评论

0/150

提交评论