本文介绍了一种改进的方法,在 IBM Rational Functional tester (RFT) 录制的脚本中采用代码和配置文件来启动应用程序,每次跑脚本前,测试人员只需要打开配置文件设好
build 运行程序的路径,就完成了配置过程。通过该方式也可以使用命令行来运行测试脚本,使自动化测试成为可能。
IBM® Rational® Functional Tester (RFT) 是 IBM 推出的自动化测试工具,借助这一工具,用户可以录制测试过程产生测试脚本,或者自己编写测试脚本以获取更多的灵活性,然后回放这些脚本来自动化测试应用程序。在进行录制或者回放脚本前,为了能够启动要测试的应用程序,用户首先要打开
RFT 的界面,在配置窗口里设好应用程序的名称、种类、路径、工作目录等信息。在实际应用中,一个产品在 beta 或者 release
发布前,会根据项目进展推出一个个 build 。当脚本开发好后,每次为了测试新 build 都要打开 RFT 重新配置,显得比较烦琐,尤其当计划只用命令行远程调用测试脚本,以实现自动化测试的时候。本文介绍了一种改进的方法,即采用代码和配置文件来启动应用程序,每次运行脚本前,用户只需要打开配置文件设好
build 运行程序的路径,就完成了配置过程。通过该方式也可以使用命令行来运行测试脚本,使自动化测试成为可能。
本文将首先介绍如何在 RFT 中设置要启动的应用程序,然后将其应用在一个实际的测试场景中,以此来说明采用默认设置方法在实际应用中会产生的问题。接着将提出一个改进的方法来取代默认方法,进而解决问题。该改进方法已经成功应用在
IBM Lotus Connection 2.0 的安装程序的自动化测试中,在本文的测试场景中,将采用此产品作为测试对象进行说明。
本章将简述在 RFT 中如何设置要启动的应用程序,首先选择 RFT 主界面工具栏上的“配置”,然后选择“配置应用程序进行测试”,弹出如下对话框。如图
1 。
图 1. 配置应用程序对话框
该对话框显示的是被测应用程序的相关信息,包括名称、种类、路径、工作目录等。
当要添加新的应用程序时,点击右侧“添加”按钮,然后在弹出对话框里选择应用程序的种类,有三个类型,一般的应用程序的启动文件都是可执行的
exe 或者 bat,这里我们选择“可执行文件或批处理文件”。如图 2 。
图 2. 添加应用程序的种类
点击“下一步”。然后选择应用程序的 bat 或者 exe 的路径,本文以 Lotus Connections 2.0 的安装程序为例,选择
< LC_installer_dir>\install.bat,即 Lotus Connections 2.0 安装程序在本机上的文件路径。如图
3 。
图 3. 添加应用程序对话框
点击“完成”。然后可以得到以下的信息。如图 4 。
图 4. 配置应用程序对话框
默认名称为 install,类型为 executable,表示可执行的,路径和工作目录为应用程序在本地磁盘的路径,可执行的文件为选择的
bat 文件名。
用户可以点击右侧的“运行”按钮进行测试,如果看到 Lotus Connections 2.0 安装程序成功启动,如图 5 。则说明配置应用程序成功,接着便可以进行下一步操作,录制或者回放脚本。
图 5. Lotus Connections 安装界面
分析启动应用程序脚本
当 Lotus Connections 2.0 安装程序在 RFT 中配置成功后,就可以录制操作,然后生成测试脚本。要录制操作,首先新建一个工程,点击“文件”,然后点击“新建
Functional Tester 项目”,填写项目名称和路径。
新建完工程后,需要新建一个空的脚本文件,在工程上右击,然后选择“使用记录器添加脚本”,输入脚本名称后点击“完成”按钮,会弹出一个“正在记录对话框”,接着点击上面的“启动应用程序”。如图
6 。
图 6. 正在记录对话框
点击后弹出“启动应用程序对话框”,从下拉列表里可以看到前面已经配置好的应用程序,选择 install – excutable
。如图 7 。
图 7. 启动应用程序对话框
点“确定”后将会启动前面所见的 Lotus Connections 2.0 安装程序界面,用户接下来在应用程序上进行的操作都会被
RFT 记记录并自动产生相应脚本。点击“正在记录对话框”(图 6 )上面的“停止记录”按钮,可以完成录制的行为。
查看生成的脚本,testMain(Object[] args) 是主函数,作为脚本执行的起始点,可以看到里面第一行的代码是 startApp("install"),传递的参数正是前面配置的
Lotus Connections 2.0 安装程序的名称,后面是记录用户操作所生成的测试代码。如清单 1 。
清单 1. RFT 生成的测试脚本
public void testMain(Object[] args) {
startApp("install");
next_btn().click();
createDB_option().click();
next_btn().click();
DB2_option().click();
......
} |
当开始回放脚本时,RFT 将首先启动应用程序,然后再进行自动化测试。由此可以得知 startApp 是 RFT 用于启动应用程序的函数,它会根据获得的参数去配置文件
configurations.rftcfg 中映射详细的配置信息,如可执行文件、路径、类型等,这些信息将真正决定应用程序如何启动。
对于前文描述的 Lotus Connections 2.0 安装文件的配置,startApp 会根据名称 install 去匹配并获取详细的信息,从而启动该程序,在
configurations.rftcfg 可以找到对应的代码。如清单 2 。
清单 2. RFT 生成的配置文件代码
<Application L=".Application">
<Name>install</Name>
<Kind>executable</Kind>
<Path>C:\Build\LC2.0_20080427</Path>
<Command>dbWizard_RFT.bat</Command>
<Jvm/>
<Classpath></Classpath>
<Args></Args>
<WorkingDir>C:\Build\LC2.0_20080427</WorkingDir>
</Application> |
configurations.rftcfg 文件通常存放在本地硬盘上的 C :\Documents and Settings\All
Users\Application Data\IBM\RFT\configuration 目目录下。
在实际应用中,一个软件产品在 beta 版或者 release 版发布前,会根据项目进展推出一个个 build,这些 build
经常是每日构建,构建好后放在按一定规则命名的(如日期)的文件内,然后统一存放在 build 服务器上,留待测试团队下载测试。本文的测试对象
Lotus Connections 2.0 安装程序正是如此。
针对实际情况,在搞清楚了 RFT 如何配置和启动应用程序之后,我们会发现一些不便之处。
- 在分工精细的项目团队里,开发脚本的人员和使用脚本的人往往不是一个人,让使用脚本的人经常打开 RFT 去配置容易出错。
- 脚本开发好后,每次为了测试新的 build 都要打开 RFT 重新配置信息,显得比较烦琐。
同时,RFT 支支持命令行方式运行脚本。其中 -datastore 后面指定工程路径,-playback 后面指定脚本的全名称。如清单
3 。
清单 3. RFT 命令行脚本
"C:\Program Files\IBM\SDP70\jdk\bin\java" -classpath
"C:\Program Files\IBM\SDP70\FunctionalTester\bin\rational_ft.jar"
com.rational.test.ft.rational_ft |
-datastore "C:\ workspace\Project1"
-playback testcases.install.Script1
使用命令行方式不仅摆脱了要打开 RFT 界面运行脚本的限制,而且也可以让用户轻易的实现自动化测试,如在 Unix 环境下使用
cron,在 Windows 下使用“任务计划”来自动调用测试脚本。
如此,又出现了一个新的问题:
- 当用户希望用命令行方式启动脚本测试每个 build,然后进一步实现自动化测试时,由于 build 的信息改变,就不得不打开
RFT 界面重新配置 build 信信息。造成了自动化测试的实现上的困难。
针对实际应用中的问题,我们提出了一种改进的启动应用程序的方式,即扩展 RFT 的 startApp 函数,用代码读取配置文件获得
build 信信息,然后进行启动。以图摆脱 RFT 本身的配置步骤。
由此,我们可以写出自定义的启动函数。如清单 4 。
清单 4. 自定义启动函数
// 启动应用程序
public static boolean execApp(String appName) {
try {
appName = appName.replace("\\", "/");
String directory = appName.substring(0, appName.lastIndexOf("/"));
String[] command = {appName};
String workDir = directory;
String outputPath = directory;
int status = -1 ;
if (!"Linux".equals(System.getProperty("os.name"))) {
// Windows 平台启动应用程序
status = runCommand(command, workDir, null, outputPath);
} else {
// Linux 平台启动应用程序
String auth = "chmod +x " + appName;
status = runCommand(new String[] { auth }, null, null,outputPath);
status = runCommand(command, workDir, null, outputPath);
}
if(status == 0){
return true;
}else{
return false;
}
} catch (Exception e){
e.printStackTrace();
return false;
}
}
// 执执行命令
public static int runCommand(String[] command, String workDir,
Map environment, String outputPath) {
ProcessBuilder builder = new ProcessBuilder(command);
builder.redirectErrorStream(true);
Process process = null;
int status = -1;
if (workDir != null)
builder.directory(new File(workDir));
if (environment != null)
builder.environment().putAll(environment);
try {
process = builder.start();
} catch (Exception e) {
e.printStackTrace();
}
if (process != null) {
try {
status = process.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
return status;
} |
runCommand 函数用于执行传递的命令,execApp 函数通过参数获得应用程序路径,然后调用 runCommand 函数来启动应用程序。
接着就可以更新 testMain 函数,使用 execApp 函数代替 startApp 。如清单 5 。
清单 5. testMain 函数
public void testMain(Object[] args) {
// 启动应用程序
execApp(sAPPPath);
......
} |
传递给 execApp 的变量可以通过读取配置文件获得应用程序路径。下面添加读取配置文件代码和相关变量。如清单 6 。
清单 6. 读取配置文件代码
// 配配置文件
public static String sFileLocation="C:\\workspace\\Project1\\conf.properties";
// 应应用程序路径变量
public static String sDBAPPPath;
// 读读取配置文件
public static String getPropertyFromFile(String sKey, String fileName){
Properties prop = new Properties();
File file = new File(fileName);
FileInputStream fis=null;
String sPropVal = "";
try{
fis= new FileInputStream(file);
prop.load(fis);
sPropVal = prop.getProperty(sKey);
fis.close();
}catch(Exception e) {
e.printStackTrace();
}
return sPropVal;
} |
getPropertyFromFile 函数根据配置文件里的键值对返回相应的值。配置文件 conf.properties 里添加键值对为
AppLocation = < 应应用程序路径 > 。对于本文的测试场景,< 应应用程序路径 > 就就是
Lotus Connections 2.0 安装程序在本机上的文件路径,如 C :\Build\LC2.0_20080427\install.bat
。
然后给 sAPPPath 变变量赋予 getPropertyFromFile 的返回值,将其传递给 execApp 。如清单
7 。
清单 7. 更新后的 testMain 函数
public void testMain(Object[] args) {
// 读读取配置文件里的路径
sAPPPath=getPropertyFromFile("AppLocation",sFileLocation);
// 启动应用程序
execApp(sDBAPPPath); |
同时,为了使命令行调用脚本更方便,我们可以将应用程序路径做为命令行的一个参数传递。
进一步修改 testMain,使之既可以读取配置文件获得应用程序路径,也可以通过命令行来获取。如清单 8 。
清单 8. 添加 testMain 获取命令行参数代码
public void testMain(Object[] args) {
if(args.length > 0 && args.length == 1){
// 通过命令行方式读取应用程序路径
sDBAPPPath = args[0].toString();
System.out.println("Read App Info with command");
}else{
// 通过配置文件方式读取应用程序路径
sDBAPPPath=getPropertyFromFile("AppLocation",sFileLocation);
System.out.println("Read App Info with properties");
}
// 启动应用程序
execApp(sDBAPPPath);
......
} |
如此,就可以在命令行中加上应用程序路径参数。当需要测试新 build 时候,通过改变此参数,可以使调用更灵活。如清单 9 。
清单 9. 传递参数的 RFT 命令行代码
"C:\Program Files\IBM\SDP70\jdk\bin\java" -classpath
"C:\Program Files\IBM\SDP70\FunctionalTester\bin\rational_ft.jar"
com.rational.test.ft.rational_ft
-datastore "C:\workspace\Project1"
-playback testcases.install.Script1<App location>
|
通过以上的做法,解决了现实应用中出现的问题:
当有新 build 需要测试的时候,用户只需要在配置文件里改变一下路径,就完成了配置过程。不需要重新打开 RFT 的配置应用程序窗口进行配置。
当需要自动化测试的时候,用户可以使用命令行方式来调用测试脚本,并且在命令行里传递新 build 的路径信息。除了可以采用计划任务来触发
RFT 命令行外,也可以使用 STAF (Software Testing Automation Framework) 来实现
RFT 的自动化框架。关于自动化测试框架实现的话题超出了本文的讨论范围。但是这一切得以实现来源于本文所讨论的改进 RFT 启动应用程序的过程。
本文仅代表本人观点,并非代表 IBM 的立场、策略和观点。
学习
获得产品和技术
讨论
|