IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope: Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  Rational  >

利用 STAF Java API 扩展 Rational Functional Tester 跨系统测试多个应用程序

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 中级

陈 海泉, 软件工程师, IBM
颜 林, 软件工程师, IBM

2009 年 4 月 24 日

Rational Functional Tester(RFT)是 IBM Rational 的一款用于功能测试的软件。它可以执行 Java、HTML、.NET 和 Windows 本地程序的 GUI 功能测试。RFT 可以测试运行于本地的多种程序,但在实际的测试项目中,还有一种需求是测试多台机器上的应用程序。例如协作软件的测试用例要求测试多台机器上程序之间相互通信。这种用例仅靠使用 RFT 无法实现自动测试。本文介绍了一种扩展 RFT 功能的方法 ── 使用 STAF 的 Java API 扩展 RFT 的功能,使之可以实现分布式的测试,达到跨系统测试多个应用程序的目的。

大 GUI 软件的功能和回归测试软件,它可以测试多种应用程序。但其测试范围仅限于本地程序而无法测试远程机器上的软件。这就无法满足某些特定的测试需求。如有的协作软件是需要多台机器之间相互通信才能完成一项功能。仅仅使用 RFT 无法满足这种需要。本文介绍了如何通过结合 STAF Java API,来扩展 RFT 的功能使之能够跨系统测试多个应用程序。

本文首先将 RFT 的功能范围,了解 RFT 在测试协作应用程序上的不足。然后介绍 STAF 及其 Java API,再介绍如何结合 RFT 和 STAF Java API 来扩展 RFT 的功能,最后用一个实例来说明一个具体的应用。

RFT 的功能范围

上面已经提到,RFT 仅能够测试本地的应用程序,而无法同时执行其他系统上的测试脚本。这是由 RFT 的系统架构决定的,RFT 的进程模型如图 1 所示:


图 1.  RFT 进程模型
RFT 进程模型

RFT 的测试进程是通过共享内存的方式和被测程序进行通信的。这就决定了其测试范围只能限制在本地程序。而且只能执行本地程序的脚本。下面列出了 RFT 的功能范围列表:

  • 测试平台:Windows, Red Hat Linux, Suse Linux, Ubuntu Linux
  • 测试域:Java 程序,HTML 程序,.Net 和 Windows 程序,AJAX 程序,SAP 程序,Siebel 程序,Flex 程序,嵌套域(如 Java 程序嵌套 HTML 程序)
  • 与 Rational 其他软件结合:ClearQuest Test Manager (CQTM),ClearCase, ClearCase MultiSite, and ClearCase LT。

Rational ClearQuest Test Manager 是一款测试管理工具,可以通过这款软件来远程执行不同机器上的 RFT 脚本。该软件可以和不同系统上运行的 Agnet Controller 进行通信。但这里存在一个缺点,即无法完成这样的用例:在机器 A 上的脚本测试本地的协同软件与机器 B 进行通信,同时需要在机器 B 上执行另外一段脚本来验证该通信的成功。RFT 和 CQTM 的结合将很难完成这种类似的测试用例。因为这需要在同一个脚本中既能在本地进行一些 UI 操作,也能在远程系统上进行一些 UI 操作。这就需要扩展 RFT 脚本的功能,使之能跨系统测试。

由于 RFT 的脚本语言可以是 Java,这就给扩展提供了便利。下面就讲述如何结合 STAF Java API,在 RFT 的 Java 脚本中,直接和其他系统中的 STAF 程序通信,实现同时在不同系统中进行 UI 测试的功能。





回页首


STAF 及其 Java API 介绍

STAF 是个开源的自动测试框架,通过使用 STAF 的各种叫做“服务”(Service) 的组件,可以对网络上的计算机进行各种操作,例如 : PROCESS 服务可以在指定的计算机上运行程序或系统命令。对 STAF 的典型应用是通过使用其 STAX 服务编写基于 XML 的测试脚本,然后使用命令行的形式运行该脚本来控制指定的机器启动各种测试用例。除了通过使用命令行使用 STAF,它还提供了多种 API,让多种类型的测试代码能够直接使用 STAF 的服务,操作网络上的计算机。API 包括 C/C++, Rexx, Java, Perl, Python 和 Tcl。通过在 RFT 的 Java 测试代码中调用 STAF Java API,可以执行用例在多台计算机上测试。下面对 STAF API 的主要模块做简要介绍:

基本接口

基本借口就是 STAF 使用的核心功能,用来提交命令并取回运行结果。提交命令涉及到 3 个概念:目标,服务和请求。目标就是运行命令的对象,可以是计算机名或 IP 地址,如果在本地运行可以用“local”表示。服务在前面提到过,可以是 STAF 内部或配置好的外部服务。请求是符合该服务定义的字符串,具体格式跟提交的服务有关。下面举例说明:

如图 2 在运行着 STAF 的机器上,可以在命令行中运行“STAF local PING PING”。它一般用来判断目标的状态,如果返回“PONG”表示本机上的 STAF 运行正常。


图 2。在命令行中运行“STAF local PING PING”
在命令行中运行“STAF local PING PING”

代码 1。用 API 运行“STAF local PING PING ”
try { 
    STAFHandle handle = new STAFHandle("demo"); 
    try { 
        String result = handle.submit("local", "PING", "PING"); 
        System.out.println(result); 
     } finally{ 
       handle.unRegister(); 
    } 
}catch (STAFException e){ 
    System.err.println("STAFException, RC=" + 
    e.rc + "\nmsg=" + e.getMessage()); 
} 

如果本机上的 STAFProc 正常运行,执行例 1 代码,输出:

PONG

输出结果跟在命令行手动执行是完全一致的。现在说明一下用到的对象 :

STAFHandle: 与 STAF 通讯的基本对象,用来注册 STAF,向 STAF 提交服务请求 , 和解除 STAF 注册。

STAFHandle 可以在构造函数中使用字符串或整形数注册一个新的或已有的 STAF 句柄 (handle), 通过调用 submit 或 submit2 方法来提交服务请求。这两个方法都需要 3 个字符串作为参数传入,即目标,服务与请求,跟使用命令行时完全相同。

submit 或 submit2 的区别在于前者返回字符串来表示结果,发生错误时抛出 STAFException;submit2 使用 STAFResult 对象表示运行结果和错误代码。STAFResult 有两个成员变量: rc 和 result。rc 相当于例 1 中的 e.rc,result 与例 1 中的 result 以及 e.getMessage() 相同。用户可以根据使用习惯来选择 submit 与 submit2。使用 STAFHandle 结束之后,需要对其反注册,即 handle.unRegister()。

封送(marshall)接口

对于返回结果比较复杂的服务请求,表示执行结果的数据通过字符串按照一定格式传递给 Java。封送接口提供了一套机制将字符串按照一定规则把数据从字符串中解封(unmarshall)出来。


代码 2。数据的解封
STAFResult result = handle.submit2("local", "FS", "LIST DIRECTORY /var"); 
System.out.println("RC=" + result.rc + "\nResult=" + result.result); 
  
if (STAFMarshallingContext.isMarshalledData(result.result)){ 
    STAFMarshallingContext mc = 
    STAFMarshallingContext.unmarshall(result.result); 
    List<?> ls = (List)mc.getRootObject(); 
    System.out.println("Unmarshalled value: " + ls); 
}else{ 
    System.err.println("Return value: " + result.result); 
} 

执行例 2,输出结果如下(Windows 用户执行代码,可以修改“/var”为任何本地路径):

RC=0 
Result=@SDT/[15:212:@SDT/$S:5:games@SDT/$S:5:crash@SDT/$S:5:local@SDT/$S:3:tmp@SDT/
$S:5:cache@SDT/$S:5:spool@SDT/$S:4:mail@SDT/$S:7:backups@SDT/$S:3:log@SDT/$S:3:opt@SDT/
$S:3:ibm@SDT/$S:3:lib@SDT/$S:4:agns@SDT/$S:3:run@SDT/$S:4:lock 
Unmarshalled value: [games, crash, local, tmp, cache, spool, mail, backups, log, opt, 
ibm, lib, agns, run, lock] 

  1. RC 是 STAF 执行状态代码,每个数字表示一定的执行状态。0 表示命令成功执行,其它值各有对应的错误类别,具体含义可以参照 STAF 用户手册“Appendix A。API Return Codes”章节。
  2. Result 是 @SDT 开头的一个字符串。它是经过 STAF 封送生成的数据,需要进行解封操作得到实际的数据。对数据解封,需要用到 STAFMarshallingContext.unmarshall(String),该方法返回 STAFMarshallingContext 的一个实例 mc,调用它的 getRootObject() 方法能够得到 Object,再跟据实际情况转换成相应类型。跟据具体情况,它可能是 java.util.List 或 java.util.Map。函数 STAFMarshallingContext.isMarshalledData(String) 可以用来判断字符串是否经过封送处理。
  3. 解封之后,可以得到 List 对象,将它打印出来,得到输出数据的第三行。

读者可以在命令行执行“STAF local FS LIST DIRECTORY /var”,把输出结果跟 API 返回结果对比,来理解为什么返回结果是 List。

实用工具接口

这组接口里面提供了一些编写 STAF 用例时有用的函数。本文由于篇幅限制,只介绍较常用的 STAFUtil.wrapData(data)。


代码 3。使用 STAFUtil.wrapData 处理包括空格的参数
String request = "START SHELL COMMAND " + 
     STAFUtil.wrapData("ls /var") + 
     "SAMECONSOLE RETURNSTDOUT STDERRTOSTDOUT WAIT"; 
STAFResult result = handle.submit2("local", "PROCESS", request); 
System.out.println("RC=" + result.rc + "\nResult=" + result.result); 
  
STAFMarshallingContext mc = 
     STAFMarshallingContext.unmarshall(result.result); 
Map ls = (Map)mc.getRootObject(); 
System.out.println("Unmarshalled value: " + ls); 

STAF service 用空格分离请求中的各个参数,当数据中含有空格时,往往容易带来错误。wrapData 函数用来解决这一问题,经过使用它把字符串封装后,无论字符串中有无空格或其它特殊符号,都可以被服务请求正确接受。

例 3 还演示了如何提交 PROCESS 服务请求,它用来运行操作系统上的命令或可执行程序,例如 "ls",“dir”或“java”,并将执行结果包装成 Map 对象。

除了上面提到的 3 个接口,STAF Java API 还有私有数据借口,用于 Log 和 Monitor 服务的接口和 Log 预览器接口。这些接口的使用不在本文讨论范围内,有需要的读者可以自行查阅 STAF Java 用户手册。

整合 STAF API 到 RFT 测试代码中

STAF API 可以配合 RFT 执行需要多台机器的测试。要做到这一点,一般需要两件事:1,在远程计算机上启动测试;2,取回测试结果。下面分别介绍实现方式:

在 RFT 测试脚本中调用 STAF API 启动远程计算机上的测试

RFT 提供了命令行接口启动测试,7.0 以上版本 RFT 提供的接口格式如下:

java -cp <class path> com.rational.test.ft.rational_ft -datastore 
    <path to test project> -log <path to store RFT logs> -playback 
    <testcase to execute> [-args <parameters for testcase>] 

通过 STAF PROCESS 服务调用 RFT 的命令行接口,能够在指定的机器上执行测试用例。需要注意的是所有在测试工程中用到的 jar 包都需要在 "-cp" 的参数中指定,包括 rational_ft 和 JSTAF 的路径。前者是 RFT 启动入口类所在的包,在 RFT 的安装目录中可以找到;后者是 STAF Java API 的包,在 STAF 的安装路径中。一个具体使用的例子如下:


代码 4。通过命令行在 Windows 操作系统中执行 RFT 测试用例
"C:/Program Files/IBM/SDP70/jdk/jre/bin/java.exe" -cp 
"C:/Program Files/IBM/SDP70/FuntionalTester/bin/rational_ft.jar";"C:/STAF/bin/JSTAF.jar"
com.rational.test.ft.rational_ft -datastore x:/project -log C:/project_logs
  -playback testcases.demo -args test1 

例 4 中 RFT 与 STAF 都安装在默认路径下,为了能让远端测试机与本地测试机都使用同样的测试工程,工程可以放在共享文件夹中,再映射到 x:/ 盘。运行的测试用例是 x:/project/testcases/demo.java,,参数 test1 会被传入到 demo 的 testMain 函数中。
在 Linux 平台上,需要更改 RFT 与 STAF 的路径和 classpath 分隔符。如果测试工程用到了很多 jar,以 cp 参数传递不便的话,RFT 提供了另外一个方法:将所有需要的 jar 文件 (rational_rf.jar 除外 ) 拷贝到下面路径就能省去在 -cp 中指定。

  1. Windows XP: C:\Documents and Settings\All Users\Application Data\IBM\RFT\customization
  2. Windows Vista: C:\ProgramData\IBM\RFT\customization
  3. Linux: /etc/opt/IBM/Rational/RFT/customization

参照例 3 使用 PROCESS 服务可以在指定的测试机上通过命令行启动 RFT 来执行测试用例。PROCESS 中的 WAIT 参数可以让 Java 代码一直等待到命令执行结束才往下继续执行。RETURNSTDOUT 和 STDERRTOSTDOUT 两个参数的作用是把控制台 STD,ERR 管道输出的数据传到执行结果中。

在 Linux 上使用命令行运行 RFT 测试还需要传入正确的系统环境变量:

STAF API 需要设置环境变量 "LD_LIBRARY_PATH=/usr/local/staf/lib"

STAF API 与 RFT 的 "LD_PRELOAD=/opt/IBM/SDP70/FunctionalTester/bin/libftevent.so" 不兼容。有的文档可能要求用户将此环境变量设置到系统中,这样会导致 STAF API 运行时崩溃。其实这个环境变量只需要在启动被测程序时设置。为了防止兼容问题,不妨在启动 RFT 时,传入环境变量 LD_PRELOAD=""

SATF PROCESS 服务可以使用 ENV 参数设置环境变量,例如 :

START SHELL COMMAND rftcmdline SAMECONSOLE RETURNSTDOUT STDERRTOSTDOUT WAIT ENV 
LD_LIBRARY_PATH=/usr/local/staf/lib ENV LD_PRELOAD="" 

取回测试用例执行结果

不同的测试项目有可能使用截然不同的日志方式,但是测试结果的输出方式不外乎以下两种:

  1. RFT 的控制台输出。测试结果直接以 System.out/err.println 的形式打印在控制台中,参照例 3 中的方式执行 RFT,result.result 解封后得到 Map 对象中的 "data" 键对应值即 RFT 控制台输出。通过分析字符串中的关键词,可以知道测试用例执行情况
  2. 日志文件。通常的测试工程使用 RFT 提供的日志接口,测试结果以 html 的格式保存在文件中。通过使用 STAF FS 服务,可以将日志文件从远程测试机拷贝到本地,或者直接读取日志文件内容(具体用法请参照 STAF 用户手册中 FS 服务的介绍)。进一步分析 html 文件,能够得到测试结果

在某些测试过程中,如果能实时获取远程计算机执行情况,而不必等到所有用例执行结束,可以更有效率的控制测试过程。例如,在远程计算机上按顺序执行 10 个验证点,其中每个验证点失败都会导致整个用例失败。遇到这种情况,当某个验证点失败的话,与其等待到所有用例执行结束,不如提前中止测试以节约时间。这就需要能够实时获取并分析远程计算机执行的情况。通过使用线程以异步的方式在远程计算机执行 RFT 测试,并间隔读取并分析日志文件,有助于更灵活地控制测试过程。

一个具体应用

Lotus Notes 中有个叫 Roaming User 的功能。该功能能够保存用户的信息如收藏夹,工作台,各种设定偏好以及个人日记数据库存储到 Domino 或文件服务器中,这样无论用户在何种系统何种平台上登录,将能与服务器上的用户信息进行同步。对该功能进行自动化测试,涉及到至少 2 个不同系统之间的协作。一个简单的用户设定偏好漫游用例如下:

  1. 在机器 A 登录 Notes,打开 Preference 对话框,进行一些设置,关闭 Notes。
  2. 在机器 B 登录 Notes,打开 Preference 对话框,检查设置是否跟机器 A 一致。

该用例涉及到两台机器之间的同步,对于实现这个用例的 RFT 脚本而言,首先在机器 A 通过自动化操作来设置 Preferences,然后在机器 B 验证 Preferences 是否同步到本地。

我们给测试用例类设置了一个参数,用来表示是在本地运行还是在远程运行,为了便于读者理解,测试脚本代码简化为例 5 所示:


代码 5。用户设定偏好漫游测试用例
public void testMain (Object[] args) 
{ 
       //determine if it needs set preferences or not 
        boolean bDoSet = false; 
      if(args.length > 0){ 
         String arg = (java.lang.String) args[0]; 
          if (arg.equalsIgnoreCase("DoSet")) { 
               bDoSet = true; 
            } 
      } 
    // 如果传入参数 DoSet, 则不发送 STAF 命令  
    if (!bDoSet) { 
           STAFHandle handle = new STAFHandle("demo"); 
           // 构造执行该 RFT 脚本的命令行 , 传入参数 DoSet 
           String rftcmdline = "java -cp ..。demo.script1 -args DoSet"
           String result = handle.submit("machineB", "PROCESS", "START SHELL COMMAND " +
                    STAFUtil.wrapData(rftcmdline) +
                    "SAMECONSOLE RETURNSTDOUT STDERRTOSTDOUT WAIT ENV LD_LIBRARY_PATH = 
                    /usr/local/staf/lib ENV LD_PRELOAD=\"\"");  
           // 验证第二台机器的运行结果 
          VerifyResult(result); 
     } 
     // 打开 preference 对话框 
     OpenPrefereces(); 
    if (bDoSet){ 
          // 设置 Notes 的配置 , 在机器 B 运行 
        SetupPreferences(); 
          // 验证是否成功 
          VerifySetupPreferences(); 
     } else  { 
           // 同步设置 
     SyncPreferences(); 
         // 验证 Notes 的 preferences 是否设置成功,在机器 A 运行 
           VerifyPreferences(); 
    } 
} 


其流程如图 3 所述:


图 3。流程图
流程图

从上述例子可见,通过 RFT 来调用 STAF 的 Java 接口,从而在第二台机器上远程运行必要的测试,来达到远程测试的目的。运行远程测试完成后,再在本地继续运行脚本来验证协作是否成功。这样大大扩展了 RFT 的应用范围,实现了真正的同时运行远程和本地测试。





回页首


总结

综上所述,通过 STAF 的 Java 编程接口,我们可以扩展 RFT 的功能,使之能够进行远程的测试。这样适用于协同软件在不同平台,不同机器上的协同工作的功能测试。通过这种结合 STAF 和 RFT 的技术,我们能够弥补 RFT 无法进行跨系统、跨平台的功能测试的缺陷,为更为广泛的测试范围,拓展了思路。



参考资料

学习

获得产品和技术

讨论


作者简介

陈海泉在 Lotus Notes 自动测试组,从事基于 Rational Functional Tester 的自动测试工作,对在 Windows 和 Linux 平台上使用 RFT 有着丰富的经验。同时他还有对移动设备的自动测试经验。


颜林,目前是 IBM 中国软件开发实验室的软件工程师,从事 Mac OS X 平台下的自动化测试工作。技术兴趣包括 Eclipse ,Mac OS X 开发,Linux 开发,Open Source。




对本文的评价










回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款