当开始回放脚本时,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; } |