GUI测试覆盖准则 GUI的存在为用户的操作带来了极大的方便,同时,也使得GUI软件更复杂、更难以测试。GUI软件的测试由于其凸现出来的/重要性,已日渐引起学术界和工业界的兴趣和重视。然而,关于GUI软件测试的研究还处于初级阶段:很多问题还没有解决,GUI软件测试依然需要较高人工成本,还不能满足保证软件质量的实际需求。
GUI的存在为用户的操作带来了极大的方便,同时,也使得GUI软件更复杂、更难以测试。GUI软件的测试由于其凸现出来的/重要性,已日渐引起学术界和工业界的兴趣和重视。然而,关于GUI软件测试的研究还处于初级阶段:很多问题还没有解决,GUI软件测试依然需要较高人工成本,还不能满足保证
软件质量的实际需求。
GUI软件
GUI具有以下优点:
(1) 用户操作简便、直观;
(2) 能够避免许多无意义的或者错误的用户输入;
(3) 能够在有限面积内显示更丰富的信息;
(4) 使得软件更加美观,易于被用户所接受。
因此,越来越多的软件利用GUI来与用户进行交互,GUI软件已成为计算机软件的主流。深入人们日常工作和生活的各种
办公软件、
财务软件、Internet浏览器、Web应用程序,都是GUI软件。
与不带GUI的软件相比,GUI软件具有很多特性。
(1) GUI软件接收到的输入是作用于GUI上的各种事件(Event);
(2) GUI软件所能接受的输入受到GUI本身结构和状态的限制。GUI本身具有特定的层次结构,同时也具有自身的状态。GUI软件运行中,用户需要根据这些信息来进行软件操作;
(3) GUI软件的输出形式多样,可能是图形界面上的变化、图像、文字或者若干个事件;
(4) 软件的运行结果不仅仅决定于当前时刻的输入,与软件的初始状态和操作历史(之前的用户操作)都有关系;
(5) GUI软件运行对操作系统依赖性很强。GUI软件运行过程中经常会调用操作系统的功能,这使得
外部设备的状态,操作系统的状态都会对GUI软件的运行产生影响。GUI软件与操作系统之间的界限变得模糊,许多功能是通过操作系统的
接口函数与
软件代码的交互实现的。
(1)
测试用例需要复杂的定义。测试用例严格来说包括软件输入及其期望输出,但通常也将软件输入称为测试用例。而GUI软件的状态与测试历史相关,软件运行的结果与软件初始状态、测试历史和当前测试输入都有关系,难以用简单的数据结构表示;测试的期望输出也变得很复杂。这使得测试用例的定义变成一个首要问题,有了明确的测试用例的定义才能够进行进一步的研究。同时,测试用例的定义对测试的效率也会产生直接影响;
(2) 测试用例的生成变得复杂。GUI软件的测试输入是事件序列,而这些事件的发生没有固定的顺序,因此GUI软件的输入域非常庞大或者无穷。另一方面,GUI软件的输入受到GUI的结构和状态的限制,在其输入域上的很多事件序列是无效的,无法正确执行或者不会得到软件的响应。如何获得有效的
测试用例成为生成GUI测试用例的关键;
(3) 测试用例的自动执行变得困难。GUI软件的输入和输出是交替进行的,而且测试输入受到GUI结构和状态的限制,这些特点使得自动测试时需要时刻监视GUI的结构和状态;
(4) 测试Oracle问题更加复杂。测试Oracle是判断软件是否发生缺陷的判据。一般来说对不同的软件需要用不同的方法来实现测试Oracle,这本身就是个很复杂的问题。而由于GUI软件的输出形式多样,使得判断软件是否发生缺陷首先要通过各种手段辨识出软件的输出和状态,使得测试Oracle问题更加困难;
(5) 需要新的
测试覆盖准则。GUI软件是
事件驱动的,软件接收到事件后即调用相应的代码来响应该事件。由于事件的发生没有固定的顺序,而软件的运行又与测试历史相关,使得GUI软件的
控制流和数据流都变得极其复杂,直接应用现有的覆盖准则成本比较高,所以需要研究针对GUI测试的覆盖准则来指导
测试用例的生成和判断测试的充分性;
(6) GUI软件的操作剖面受到GUI的影响。很多GUI软件为用户提供了若干快捷键、快捷方式等,这些界面的元素对用户操作习惯会产生重大影响,在
软件可靠性研究中需要考虑到GUI对操作剖面的影响。
GUI
软件测试由于其重要性及其独有的难点,已日渐引起学术界和软件产业界的兴趣和重视。近年来有不少学者和研究机构对GUI的测试进行了研究,从测试的各个角度提出了很多方法,从软件测试的各个环节来研究软件测试。下面从GUI
测试覆盖准则和GUI
测试用例生成两个方面来介绍现有学术界的一些GUI软件测试方法。
GUI测试覆盖准则
软件测试覆盖准则是一个被关注很久的课题,是指测试中对测试需求覆盖程度的要求。而测试覆盖率是用来定量描述对测试需求覆盖程度的度量。可以说覆盖准则是各种
软件测试技术的核心。常用的覆盖准则包括:
语句覆盖准则、
分支覆盖准则、
条件覆盖准则、
路径覆盖准则、状态覆盖准则、
数据流覆盖准则等等。这些覆盖准则多是在上世纪90年代之前被定义的,都不是针对GUI软件测试的。在GUI软件测试中,由于其输入是事件序列,而这个序列是由用户决定的,具有很大的随意性和随机性,这使得GUI软件的
控制流图和
数据流图比起传统非GUI软件要复杂很多,导致这些传统的覆盖准则难以使用。因此有必要专门为GUI
软件测试定义新的覆盖准则。
针对GUI
测试覆盖准则的相关研究主要包括以下几项。
(1) Memon等在提出了基于事件的测试覆盖准则。他们将被测GUI按照窗口划分为若干模块,将作用在每个模块内GUI部件上的事件归为一类,按照这些事件能够被执行的先后关系创建事件流图(Event-Flow Graph)。不同GUI部分之间的相互调用则使整体树(Integrated Tree)来表示。在这两种模型基础上,他们定义了若干种模块内覆盖准则(Intra-Component Coverage Criteria)和模块间覆盖准则(Inter-Component Coverage Criteria)。模块内覆盖准则指标包括事件覆盖准则、事件交互覆盖准则、长度为
n的事件序列覆盖准则等,这些覆盖准则实际上是要求
测试用例集覆盖事件流图上的顶点、边以及长度为
n的路径,反映了对这一GUI
模块测试的充分性。而模块间
测试覆盖准则包括调用覆盖准则、调用-关闭覆盖准则以及长度为
n的跨模块事件序列覆盖准则,这些覆盖准则要求对GUI模块间的调用进行测试。实际上,在Memon等的后续工作中,原本定义于模块内的事件覆盖率和事件交互覆盖率也被应用到模块间,是比较常用的GUI测试覆盖率。
(2) 特定事件序列的测试覆盖准则。Xie和Memon提出了几种事件序列的模式,他们通过实验表明符合这几种模式的事件序列具有比较高的缺陷检测能力,因此,在
测试用例集应当包含符合这些模式的测试用例。
(3) McMaster等提出了一种用于GUI软件
回归测试的调用堆栈覆盖准则(Call Stack Coverage)。在软件的运行过程中,内存中有一个称为调用堆栈的数据结构,这个堆栈中的数据反映了软件中函数被调用的顺序,如果两个测试用例被执行时其调用堆栈中内容相同,则说明这两个测试用例调用函数的顺序一致。调用堆栈覆盖准则将
函数调用顺序相似的测试用例看作等价。在进行回归测试时,受测试成本限制,可能无法运行现有的所有测试用例,因此需要对测试用例集进行缩减,使用调用堆栈覆盖率时,需要逐一分析测试用例的调用堆栈,分析器函数调用顺序,如果一个测试用例的函数调用顺序与前面的测试用例一致,则将这个测试用例看作
冗余。由于这种覆盖率需要
测试用例的运行中的数据,难以用于指导测试用例的生成;而且这种覆盖准则无法以覆盖率的形式度量测试的充分性。
(4) Zhao等提出了基于Event Handler的
测试覆盖准则。Event Handler是用于响应用户输入事件的代码,是GUI软件
源代码的组成部分。Event Handler之间相对独立,但存在共享变量。如果一个Event Handler调用了一个或多个在另一个Event Handler中定义的变量,则称这两个Event Handler为一个Handler Interaction。而基于Event Handler的测试覆盖准则要求用户覆盖 a.所有Event Handler, b.所有Handler Interaction。这种覆盖准则克服了基于事件的覆盖准则中存在大量
冗余测试需求的问题。
GUI测试用例生成
当前国内外学者针对GUI测试用例生成的问题已经提出了若干种方法,可以分为五类:录制/回放技术、基于有限状态自动机生成测试用例、基于UML生成GUI测试用例、利用人工智能方法生成测试用例和基于事件流图生成测试用例。
a) 录制/回放技术
HP WinRunner/QuickTest、IBM Rational这类GUI测试工具中提供了测试用例录制/回放机制,可以将用户在被测GUI软件上的操作录制为
测试脚本,而在进行测试时回放这些脚本。这是工业界应用比较广的一种测试用例生成方法。然而这类方法需要人工设计并录制测试用例,可以说是仅仅是人工测试的辅助工具。
b) 基于有限状态自动机生成测试用例
有限状态自动机(Finite State Machine,简称FSM)是一种能够描述交互式系统的数学模型。GUI软件作为一种交互式系统,也可以使用FSM进行建模。基于FSM的
测试用例生成主要有以下几种方法。
Belli 在文献中使用FSM对GUI软件与用户的操作以及
软件缺陷进行了建模,并给出算法将FSM转换为等价
正则表达式,然后利用这些等价正则表达式生成GUI测试用例。Chen等以被测软件GUI上的GUI部件属性为状态,事件作为输出,GUI部件属性的变化作为输出,构建FSM,通过FSM上的路径搜索得到输入序列作为
测试用例。
上述方法使用直接使用FSM对GUI进行建模,由于存在状态爆炸的问题,难以处理较大的GUI软件,FSM模型的创建难度也比较大。Shehady等使用带变量的有限状态自动机(Variable Finite State Machine,简称VFSM,有的文献也称为扩展有限状态自动机,即Extended Finite State Machine,EFSM)来对GUI软件进行建模。VFSM可以通过定义变量大大减少状态空间中状态的数量。文中创建VFSM时是以当前窗口作为状态,将测试中操作的或关注的变量加入
自动机中;然后给出算法,将VFSM转化为FSM,再由FSM生成事件序列作为GUI
测试用例。但这种方法依然难以应用于大的GUI软件,创建VFSM难度也比较大,需要很高的人力成本。
White等提出了一种使用多个FSM对被测GUI软件进行建模的方法,以缩小FSM的规模,减少生成测试用例的个数。这种方法首先将在用户操作后产生的GUI上可观察的变化作为一个响应(responsibility);再对每个响应人工地辨识出一系列GUI部件,通过对这些部件的操作可以产生这个响应,这样的一系列GUI部件成为一个完全交互序列(Complete Interaction Sequence,简称CIS);然后对每一个CIS建立一个FSM;下一步是利用文中给出的方法将FSM中相对独立的状态子集组合成一个超状态;最后利用变换后的FSM生成
测试用例。
Li扩展了White等的工作,将GUI被测软件在局部和整体两个层次建模:局部层次上以流图对GUI软件行为进行建模;在整体层次上则采用基于CIS的方法建立FSM模型。通过在流图和FSM上的遍历,可以得到所需的测试用例。这种方法进一步减少了FSM模型状态的数量。
上述基于FSM生成测试用例的方法主要问题在于需要对被测GUI软件手工建立FSM模型,这是一个难度和工作量都很大工作。
c) 基于UML生成GUI测试用例
UML(Unified Modeling Language,
统一建模语言)是用来对软件系统进行
可视化建模的一种语言。在软件开发过程中,人们常用UML来编写设计文档。
Vieira等中提出利用UML
用例图和
活动图来生成GUI
测试用例的方法。这种方法首先要人工对UML进行标注,然后根据标注后的UML文档生成测试操作。这类方法使用的前提是具有完善的UML
软件设计文档或UML软件规约(Specification),具有较大的局限性;所生成的测试用例还需要人工转化为
测试脚本,或者人工施加到被测软件上。
d) 利用人工智能方法生成测试用例
利用人工智能方法生成测试用例的研究主要是将智能规划方法(Planning)和遗传算法(Genetic Algorithm)引入GUI测试用例生成。
利用规划方法生成GUI
测试用例是Memon等提出的。这种方法将事件看作引起被测软件状态发生变化的操作,将其表示为初始状态和操作后的状态,然后用智能规划的方法寻找从给定初始状态到目标状态的路径作为GUI测试用例。这种方法的优点是随着测试用例的生成,还能得到被测软件期望到达的状态或期望输出,这些信息可用于判断是否发生
软件失效。但使用这种方法时需要人工确定每个事件的初始状态和其引起的状态变化,工作量非常大,难以用于大规模GUI
软件测试。
Kasik等提出了利用遗传算法创建GUI
测试用例的方法。作者认为在GUI测试中熟练测试人员设计的测试用例效率更高,使用遗传算法对熟练测试人员生成的样本测试用例集进行学习,然后根据学习的结果来生成新的测试用例。这种方法依然需要较高的人工成本,同时其效果受样本集的影响很大。
e) 基于事件流图生成测试用例
事件流图是Memon等提出的一种描述事件间跟随关系的模型。所谓跟随是指在测试中一个事件能够在另一个事件施加后被施加到被测软件上。事件流图中的路径就是在测试中可以运行的“可行”测试用例序列。在文献中,Memon等使用遍历算法在事件流图上查找特定的路径来作为GUI测试用例。这种方法没有明确的目标,会生成大量
冗余测试用例。
事件流图无法描述事件间跟随关系发生变化的情况。受到这个限制,这些基于事件流图的方法生成的
测试用例在很多情况下无法顺利运行,需要较多的人工操作来修正所生成的测试用例。
f) 基于活动流图生成测试用例
活动流图是Zhao提出的一种用于GUI测试用例生成的流图模型。这种模型改进了事件流图模型,克服了事件流图无法处理跟随关系发生变化的缺点。这种模型是在事件流图上添加跟随关系成立条件,然后将所有成立条件的影响封装到若干个子图中(这些子图成为活动),从而生成活动流图。每个活动都是一个单入单出的有向图,其中的部分有向边具有成立条件,可以看作是一个
控制流图。也就是说,每个活动都能够很容易地转化为一段
测试脚本代码。根据活动流图进行路径搜索,就可以将不同活动对应的测试脚本组合成满足某种测试需求的
测试用例。