转自:http://www.ibm.com/developerworks/cn/rational/r-cn-rftscriptiterativetimes/index.html
本文采用循序渐进的方式介绍了一种减少 Rational Functional Tester(RFT)测试脚本开发迭代次数的方法。该方法综合调试、异常处理、流程控制等技术,以调试的方式进行脚本开发,能够实现快速开发脚本的目的,特别适合于中大型测试脚本的开发。
这篇文章介绍了一种减少 RFT 测试脚本开发迭代次数的方法。
通过学习这篇文章,您可以了解:
手工开发 Rational Functional Tester(RFT)测试脚本的过程和开发普通的程序类似,需要经过“编写、执行、发生错误、退出执行、查找并修改错误、再次执行脚本……开发成功”的过程。其中“执行、发生错误、退出执行、查找并修改错误”几个环节可能需要多次的循环迭代。对于步骤繁多的大型脚本,上述迭代次数的大幅增加将会产生巨大的时间成本。本文提出一种实现快速开发脚本的方法,该方法综合调试、异常处理、流程控制等技术,以调试的方式实现脚本的开发。该方法把编写和调试脚本的过程合一,可以一边开发脚本,一边执行脚本;当脚本执行出现错误时,能够迅速定位错误,并且在修改错误之后无需从头执行脚本。这种方法能够有效地缓解传统开发方法存在的迭代问题,特别适合于中大型测试脚本的开发。
本文主要面向使用 RFT 且以手工方式开发 Java 型测试脚本的工程技术人员。我们假设你已具备如下的知识背景:
为提高代码的重用性,测试人员一般不直接录制功能性自动化测试脚本,而是采用手工方式开发测试脚本,传统的开发流程如图1所示:
一般来说,为开发一个测试脚本,在编写脚本之后,需要反复迭代上图所示流程中的几个环节:执行脚本、抛出错误、退出执行、查找错误、修改错误、再次从头执行脚本。为了快速开发脚本和复用代码,测试人员虽然可以使用特定的自动化测试框架来开发脚本,但脚本的开发过程仍然遵循上述的步骤。
图 2 展示的是一个自动化测试脚本的片段,它开发于特定的测试框架。在编写该脚本之后,需要执行脚本以验证脚本的正确性。
如果脚本片断中步骤 2 的代码存在错误(例如,找不到相应的操作对象),RFT 通常将会异常退出,结束脚本的执行(另外的可能是弹出窗口,让测试人员更新对象的识别方法),我们需要查找并修改代码中的错误,然后重新执行脚本。如果脚本再次发生错误,我们将继续重复“退出执行、定位错误、修改错误、再次执行脚本”的过程。
为了避免从头执行脚本引起的时间消耗,通常测试人员采用注释的方式对脚本进行调试,例如,注释掉步骤 2 之前的代码(见图 2),然后重新执行脚本,RFT 将从步骤 2 开始执行相关的测试操作。虽然这种方法可以节省一定的时间,但是反复地对代码进行注释容易使脚本逻辑结构变得混乱,有时反而不利于调试。
注:这里只能选择性地注释掉其中的一些操作语句,像变量定义这样的语句不能被注释掉。
如果测试脚本隐含着多处错误,上述的开发方式就必须多次迭代“退出执行、查找错误、修改错误、再次执行脚本”的过程。
对于小型的测试脚本,由于代码规模小、错误数量有限,迭代引起的时间成本是比较低的。然而对于大型的测试脚本,随着代码规模的扩大,出错的可能性和频率也会随之增加,大量的迭代将会导致时间成本的大幅增长。因此,如何尽量减少迭代的次数,对于开发大型脚本具有重要的意义。
下面我们开始介绍一种可以减少迭代次数的开发模式。
这里先简单介绍一下我们的设想。
为了缓解传统开发方式存在的迭代问题,实现快速地开发脚本,我们设想:
我们能否用现有的技术来实现上述的设想呢?答案是肯定的。为了实现这些设想,我们可以借助的理论依据和技术有:
在介绍具体的开发流程之前,我们首先介绍一种新的脚本结构。该结构不同于传统的脚本结构:它使用选择结构和循环结构作为实现分割脚本和控制测试步骤执行顺序的主要手段。图 4 中的代码描述了这种新的脚本结构。
下面我们对结构代码的各组成部分逐一进行介绍:
RFT 测试脚本体现为一个类,测试步骤一般被放置于某一类方法中。对于脚本中需要共享的数据,例如文件名、组件名、需要进行对比验证的数据等,我们使用类变量或者方法内部变量的形式进行表示。
switch-case 结构用于划分测试脚本,每个 case 分支存放一个测试步骤的代码。case 语句的条件值对应测试用例中的测试步骤号。
for 循环语句用于控制脚本的执行过程,循环变量(见图 4 中的变量 step)指明每次循环需要执行的 case 分支(测试步骤),在调试状态下,我们可以通过修改该变量的值指定将要执行的测试步骤。
我们使用 try-catch 结构包含整个循环结构,也就是全部的测试步骤。然后在 catch 语句处设置断点,并在其中添加如下语句:
System.out.println("Step " + step + " throw: "+ e.getMessage())。
|
通过在 catch 语句设置断点,可以在脚本抛出异常(Exception)或错误(Error)时,捕获脚本发生的问题并立刻暂停执行脚本。在暂停执行脚本以后,我们可以通过单步执行异常处理语句来定位出错的 case 分支(测试步骤),同时也可以使用 RFT 相关工具(例如 Test Object Inspector)以及相关的调试工具来辅助定位错误;我们还可以借助热交换功能修改出错的代码,或者修改变量 step 的值以指定 RFT 将要执行的 case 分支。鉴于测试脚本不同于普通的应用程序,对于脚本抛出的错误(Error)不一定必须退出脚本的执行。因此我们在 catch 部分声明捕获 Exception 类和 Error 类共同实现的接口:Thowable.。
在介绍完脚本结构之后,下面我们以流程图的形式给出脚本的具体开发流程(见图 5),并对其中的几个环节予以说明。
下面我们对流程图中的几个主要操作环节的细节进行说明:
建立图 4 所示的脚本结构代码。确保每一个 case 语句对于一个 break 语句 , 然后把测试步骤的描述以注释的形式写入对应的 case 分支。由于脚本结构比较固定,因此也可以事先定义一个脚本结构代码模板,以便每次开发新脚本时能够复用已有的结构代码,从而减轻开发的工作量。
在编写测试步骤代码之前,首先把以下两个语句设为断点:
为了控制每次脚本执行的进度,我们可以把每个 break 语句都设置为断点,以便写一段代码,就执行该段代码,从而达到一边编写脚本,一边执行脚本的目的。
通过点击图 6 所示的按钮,用调试模式执行脚本。然后根据暂停执行时的断点类型进行不同的操作:
在调试状态下,修改代码并执行保存操作会导致执行点转移到当前方法的开始语句。点击图 7 所示的按钮可以恢复执行暂停的脚本,那么 RFT 将会执行 step 指定的 case 分支。
下面我们以图 2 的脚本为例,介绍具体的开发过程:
完成脚本开发以后,我们再次执行脚本来确认脚本的正确性:首先去除所有的断点(仅保留 catch 语句处的断点),修改循环变量 step 的值为 0,指明 RFT 从头到尾地顺序执行所有测试步骤。然后以调试的形式执行脚本。
由于每个测试步骤的代码都是以调试方式开发的,出错可能性已非常小,即使出现错误,我们也能够通过 catch 语句迅速地捕获、定位并予以更正。
在实际工作中,我们曾经开发过一个执行时间长达 40 分钟的测试脚本,如果使用传统方法进行开发,一般至少需要 2 天的时间。借助于本文提出的开发方法,我们在不到 1 天的时间内就完成了开发工作,从而节约了大量的时间。
RFT 测试脚本文件的入口类方法是:
public void testMain(Object[] args) |
RFT 执行脚本时会自动调用该方法。由于 RFT 不支持对该方法内的代码进行热交换错误修正,因此不能在该方法内开发脚本代码。我们可以选择在其他类方法中开发测试脚本,然后通过 testMain() 方法调用该方法。
调试状态下,对该类成员声明的编辑都会导致 RFT 出现异常,所以不要在调试状态下编辑类成员声明,总之,类成员变量只适合于存放固定不变的共享数据,而对于容易发生改变的数据应该使用方法内部变量进行存放。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/14780873/viewspace-628471/ ,如需转载,请注明出处,否则将追究法律责任。