由于协作图在表示用例实现时,协作图上的场景路径是从第一条入口消息开始到所有能触发端口输出事件或没有后继消息的出口消息之间的所有可能的消息流。要获取场景路径上的消息流,可以通过消息之间的偏序关系以及决定消息流分支和循环的条件来实现。回顾协作图上消息及其顺序号的定义,整数表示过程调用中相邻高层中的消息顺序,同一整数项下的不同消息是表示一个前驱-后继式的平面控制流,嵌套的消息顺序号表示过程的调用控制流。消息顺序号隐含地表示了消息之间的偏序关系,因此可以在协作图上提根据消息的发送条件及其顺序号来跟踪场景路径。协作图中通过消息顺序号跟踪消息执行的顺序比顺序图中通过自上而下的生命线跟踪消息执行的顺序困难得多,但由于协作图更容易表示对象之间的动态连接关系,协作图不关注全局的消息执行顺序,只关注一个场景的执行路径上的消息顺序,这为我们识别场景路径提供了方便。协作图上的分支和循环导致了许多可能的路径,极端的情况下路径的数目可能到达一个庞大的数字,我们要达到协作图上的路径覆盖,采用简单的方法达到判定/循环覆盖。我们先将循环消息看作条件消息,在遍历场景路径的过程中,访问一条消息后,先找出该消息可能的直接后继,然后采用深度优先的方法选择一个直接后继继续遍历,当到达一个没有后继的消息时,就完成一个场景路径的遍历,回溯到下一个直接后继,继续遍历,只到所有的直接后继都已被访问,则完成了所有的场景路径的遍历。这样我们实现每条消息至少遍历一次,每个条件分支都至少遍历了一次,也避免了路径的穷尽覆盖。然后处理协作图上的循环,一般是给出绕过循环、循环一次、循环最多次以达到循环路径的覆盖。对于存在分支和循环的场景路径,例如图1所示的协作图上有7个条件判断和一个最大次数为2的循环,可能的路径有2*2*2*2*3*2*2*2=192条,但由于有5个条件判定各有一个分支直接导致场景路径结束,所以实际的场景路径应为1+1+1+1+1+3*2+2=13条,这13条场景路径对应相应软件功能的13个执行场景。
我们在协作图上遍历生成场景路径的同时,很容易基于路径覆盖准则获取相应场景执行过程中的控制流和数据流、覆盖路径的条件,然后可以确定每一路径所需要的输入和状态条件,当满足所有路径条件时线程就会沿着该路径执行,这正是我们定义集成测试用例所需要的信息,因此我们考虑将场景路径作为基于协作图的集成测试的基础。下面我们分析协作图表示的协作在实现中通过参与者之间的集成完成时可能发生的故障,这样便于我们研究针对检错为目的的测试。
2.3基于协作图的协作集成测试模式
协作图上描述的软件系统的消息的错误实现可能导致协作中表现的行为发生偏差,从而使最终实现与设计不一致,偏离软件规约规定的功能。例如由于消息名的编码错误、错误的参数、不正确的参数值、不正确的或缺少输出以及非预期的运行时绑定导致的错误方法调用;消息前驱约束实现错误导致发送者对象发送违反接受者对象前提条件的消息或者发送者对象发送违反接受者对象的顺序约束的消息;消息的发送者或接受者对象错误导致错误的对象和消息的绑定;参与者缺少功能或特征导致错误的对象引起正确的异常、正确的对象产生错误的异常。所以链上的消息箭头和约束、消息标签、对象等协作图上的元素未按设计正确实现会导致最终的软件与设计不一致,如果协作图的实现中存在错误,肯定在协作图至少一条路径上,要达到该错误,在未知该错误在那条路径上时,只能通过协作图上选择所有可能的执行路径,并导出能够跟踪这些路径的测试用例,并用它们来执行软件,来确定错误在哪条路径上,即哪条路径被错误实现了,从而可以调试软件,改正错误,以保证实现与设计一致。
这些可能发生的错误都是在参与协作的对象之间交互时发生,也就是系统在通过不同类的对象的方法之间集成实现系统的行为时发生,这种错误通常由集成测试来发现。软件集成测试有几种常用的集成测试模式(integration testing pattern):一次性组装、自底向上集成、自顶向下集成、协作集成、基干集成、层次集成等,但是考虑到面向对象软件时有的模式不一定有用,在面向对象的系统中,很难找到一个控制的层次结构,使得方便定义自底向上集成、自顶向下集成、层次集成等策略。在面向对象的环境中我们可以通过基于线程或基于使用的测试技术测试类的交互。这里交互的类可以是单个类及其实例、类簇、组件、子系统或系统。用协作图描述的系统协作在集成测试时,协作集成是最佳的测试模式[9],通过在协作中参与的组件来决定集成测试所有参与的对象。基于协作的集成测试需要检测协作的参与者之间的接口和交互,通过协作组织集成。每次处理一个协作,直到协作图上的所有协作都被测试。当所有构件的接口和构件之间的交互都测试完时集成测试完成。协作中包括的构件按照在一个处理线程、一个事件-响应路径来选择,要求系统中每个构件之间的消息已经被至少测试一次。我们前面定义场景路径正是一个线程完成协作执行的一个事件-响应路径,所以可能发生的错误会出现一条或多条场景路径上。
测试模式是一个测试策略,是建立在测试模型基础上的,而测试模型应该是被测软件系统的一个表示,能够从测试模型上获取测试需求,导出测试规约,从而生成测试用例。协作图是对象、组件、子系统、系统范围需求的良好来源,对系统的一个有限片断来说,提供了实现的抽象视图,它通常是过多或过少细节之间的一个良好的折中,可以用于在不同抽象级别和粒度级别建立软件系统的模型。由于协作图是描述的对象之间的交互,而系统的功能正是通过这些交互实现的,所以要考虑将设计描述的协作图作为生成集成测试的测试用例的测试模型。协作图上包括了对象间传递的消息及其顺序,这正是设计级的控制流和数据流信息,以往数据流和控制流只能从程序源码中分析得到。数据流和控制流对生成测试有很大的作用,所以我们利用协作图生成测试用例,就是要从协作图上提取出相应的数据流和控制流信息,利用传统的数据流、控制流生成测试用例的方法,生成可用于集成测试的测试用例。所以本文使用作为系统设计描述的协作图作为测试行为的测试模型,避免重新构造测试模型或者进行模型转换。
2.1中分析了协作图中描述的信息,这也是作为测试模型的协作图中包含的对生成测试用例有用的信息,这些信息是规约在转变成实现时必须保持的,这些信息也是测试时要确认在软件实现中是否正确保持的设计信息,因此这就是测试工作第一步要获取的测试需求。测试需求的正确实现要求也就是测试规约,它规定了能让软件执行并正确反应测试需求的测试用例。如果我们能够用足够的测试用例执行了程序,并证明协作图上所有测试需求都在软件中正确保持了,就可以说测试充分了,本文主要关注协作图表示的系统的动态交互行为,而协作图上用于表示交互行为的主要是消息及其偏序序列,所以本文研究的测试方法的充分性准则是协作图上所有的消息及其偏序关系都被测试用例覆盖。表1中的协作图的集成测试需求说明至少有一个测试用例测试对应的关系来检查测试需求是否满足。
符号 关系 集成测试需求