RFT 对象概述
RFT 对象
从开发的角度看,GUI 通常都是基于某一 GUI 开发库(SWT/SWING/AWT),这些库通常是按照面向对象的方式进行建模的,它将每一个 GUI 元素映射成该库中某一个类的对象。
从测试的角度看,所有的 GUI 元素,无论基于何种 GUI 库,都被 RFT 映射成对象,RFT 提供一个对象模型框架管理各种 GUI 元素。
图 1 是一个典型的基于 SWT 开发的 GUI,对于其中的一个按钮,在开发者看来,它就是 SWT 库中 Button 类的一个对象;但是 RFT 并不区分这是 SWT 库中的按钮,或者是其他 GUI 库的按钮,它都被映射成 RFT 对象模型中 GuiTestObject 对象。
在用 RFT 提供的 Inspector 工具获取 GUI 元素时,需要用到开发模型。而进行 RFT 脚本开发时,又需要用到 RFT 对象模型。熟练掌握两种对象模型,对提高 RFT 自动化测试效率非常有帮助。
图 1. RFT 对象模型示例
RFT 对象识别
基于 RFT 的自动化测试,都会采用 IBM 推荐的 ITCL 框架。在这个框架下,所有的脚本被划分为三个层次:对象层,任务层,用例层。对象识别就是在 RFT 的对象模型框架下,得到被测程序的 GUI 对象。它是对象层开发中最核心的任务。
常用的 RFT 的对象识别技术可以分为两大类:静态识别与动态识别。动态和静态方法各有优缺点,静态方法识别效率高、开发成本比较低,但是脚本的可维护性比较差;而动态方法刚好相反。
扩展 RFT 对象识别技术
采用常用的对象识别技术,可以识别出大部分的 GUI 元素,但有时也会遇到 RFT 无法识别的 GUI 元素,事实上识别这类用常用对象识别技术无法识别的 GUI 元素占用了 RFT 脚本开发的大部分时间。
RFT 中一个非常重要的根接口是 IGraphical 接口,它定义了针对 GUI 元素的所有标准操作(click,doubleclick,drag 等)。另外一个非常重要的根类是 GuiTestObject,它继承自 TestObject 并实现了 IGraphical 接口。常用对象识别技术中 GUI 元素都是被映射为 GuiTestObject 对象。它们在 RFT 对象模型中的位置如图 2 所示。灵活运用这些类、接口及其方法,能够极大地扩展 RFT 对象识别的功能。
图 2. RFT 对象模型类图
- 问题描述
使用 RFT 经常听到的一个谬论就是 RFT 只能测试基于 java 的 GUI 程序,对于 C/C++ 或者 windows 标准控件,RFT 无法识别。事实上,RFT 提供了 IWindow 接口用于识别平台相关的控件。
- IWindow 接口介绍
从图 2 中可以看出,IWindow 接口也继承自 IGraphical 接口,从这点看,IWindow 接口具有与 GuiTestObject 类似的功能。
使用 IWindow 接口能够识别平台相关的 GUI 控件,但是其接口函数的具体实现与平台相关,windows 与 linux 上的实现就不一样,可以通过下述方法判断具体的平台,本文将主要分析 windows 上的应用。
清单 1
- 典型应用
图 3 是记事本的“页面设置”对话框,是一个 windows 原始窗体。如何识别这个窗体,并点击“确定”按钮呢?基于 RFT 的实现方法如下:
图 3. 被测试程序 GUI
确定对象识别的起始点。通常选取最上层窗体作为对象识别的起始点,具体方法如下所示:
清单 2
这些方法都返回一个 IWindow 接口的数组,每一个数组元素代表一个顶层窗口,并且这些窗口之间是互相独立的。
识别符合要求的顶层窗口,即“页面设置”对话框。IWindow 接口提供了两个方法:getText() 与 getWindowClassName() 来实现。对于窗体,getText() 返回窗体的标题;对于控件,getText() 返回控件的文本。getWindowClassName() 返回 win32 标准控件名。如何知道被测程序的标准控件名呢?在 windows 上有许多工具,例如下文中将提到的 AutoIt 以及 Visual Studio 提供的 Spy++。图 4 是用 AutoIt 得到的 GUI 元素的属性。
图 4. 利用 AutoIt 得到 GUI 元素的属性
对顶层窗体数组根据文本值和标准控件名进行匹配,则可以识别出符合要求的顶层窗体。这两个方法均返回字符串,为了提高识别的效率,通常对这些字符串进行正则表达式匹配。具体用法如下,参数 sCaption 表示窗体的标题,sWindowClassName 表示窗体的 Win32 标准类名。
清单 3
识别窗体内的控件,即“确定”按钮。以顶层窗口为起点,通过 IWindow 提供的 getChildren() 函数可以得到内嵌在顶层窗体的 GUI 控件(如 button,label 等),该方法返回 IWindow 接口的数组,对数组元素根据文本值和标准控件名进行匹配,即可识别出内嵌的控件。识别内嵌控件的方法如下,参数 iTopwin 表示顶层窗体,sCtrlText 表示控件的文本值,sCtrlClassName 表示控件的 Win32 标准类名。
清单 4
IWindow 还提供了 getOwned() 方法,可以得到出顶层窗体拥有的子窗体(如模式对话框等)。
完成点击“页面设置”窗体中“确定”按钮的 RFT 脚本如下。
清单 5
- 问题描述
在进行 GUI 自动化测试时,一个经常遇到的问题就是如何测试开发者定制的控件?通常一组定制的控件,是作为一个整体被 RFT 识别出来,你可以对这个整体作一些操作,但是如何识别出每一个具体的定制控件呢?可以使用 TestObject 类提供的方法:Invoke 函数。
- Invoke 方法介绍
Invoke 方法类似于 java 中的反射机制,它可以在运行时而不是编译时调用函数。通俗地说,在 RFT 中,它可以根据字符串来调用相应的函数。这使得不仅可以调用某些确定的方法(如 GuiTestObject 的方法),还可以主动查询定制控件本身提供的方法,大大加强了对象识别能力。
- 典型应用
使用 Invoke 函数的一个典型例子就是测试 Notes 8 的 tab 项。Notes 8 的 tab 项是一个定制的 java 控件。RFT 会将多个 tab 项识别为一个 GuiTestObject 对象,如何识别出每一个 tab 项呢?并执行关闭 tab 项的操作呢?
首先采用 Object map 方法识别出 RFT 能够识别出的最小的定制控件的集合。如下图 2 红色方框所示的 GUI 元素是 RFT 所能识别出的最小的对象。在本例中它被识别为 GuiTestObject 的对象:sTabFolderObject。
图 5. Notes 8 中定制控件
图 5 Notes 8 中定制控件
确定需要调用的方法。调用 Invoke 方法需要事先知道方法的名称,TestObject 提供了另外一个方法:getMethods 它能够返回控件所有的方法,你可以按照如下的方式调用它。
清单 6
按照这种方式,能够在控制台打印该控件所有可用的方法,从中分析出需要的方法。在本例中发现 getItems 能够返回所有的 tab 项。
调用 Invoke 方法识别出具体的定制控件。完整的用法如下所示,参数 name 表示希望识别的 tab 项的文本值,sTabFolderObject 为上述红色方框表示的对象。
清单 7
完成关闭 tab 项操作。利用 Invoke 可以很便捷的操作 GUI 对象,但是一定要避免使用用户所不能操作的方式来操作控件,因为这违背了测试的原则。从 getMethods 返回的方法中发现 dispose 方法也可以关闭 tab 项,但很显然用户不能这样操作,而用户关闭 tab 项的操作就是点击 tab 项的“X”。因此在 RFT 脚本中,可以首先得到“X”的坐标,然后在该点执行单击操作。具体的方法如下所示。
清单 8
集成第三方自动化工具
- 问题描述
使用 RFT 进行自动化测试时,经常遇到这样的尴尬,一方面 RFT 在识别某些对象时遇到一些问题,比如无法识别,识别效率低,开发识别脚本代价很高。另一方面又有大量的第三方 GUI 自动化工具对某些特定的领域有很好的性能。如果能够结合 RFT 与其他自动化工具,就能够极大地提高自动化测试的效率,更加适应敏捷开发与测试。
- AutoIt 介绍
AutoIt 是一种在 windows 平台上,针对 C/C++ 以及 windows 标准控件的,免费、开源的自动化管理工具。AutoIt 本身有一种非常简单的脚本语言,这种脚本语言类于 Basic,并且其脚本可以直接转化为可执行程序且不依赖于任何库。事实上,AutoIt 的这些功能,RFT 提供的 IWindow 接口也能够完成,但 AutoIt 具有更高的效率。
- 典型应用一
仍然以 IWindow 接口中点击“页面设置”对话框中的“确定”按钮为例。介绍如何结合 RFT 与 AutoIt 完成上述操作。
- 开发 AutoIt 脚本。AutoIt 对 GUI 对象的识别区分 windows 和 controls。对于 windows 是通过 title/text 方式进行对象识别;对于 controls 是通过 title/text/controlID 方式进行识别。ControlID 是 AutoIt 中特有的概念,它不是一个特定的值,可以是:内部 ID,text,class,instance,classmn 以及它们的组合。在本例中,最终需要识别的对象是“确定”按钮,同时它又位于“页面设置”窗体中。具体的 AutoIt 脚本如下。
- 在 RFT 中调用 AutoIt 脚本。RFT 提供了多种启动其它进程的方法,其中类 RationalTestScript 提供的 startApp 和 Run 方法比较常用。使用 startApp 需要事先在 IDE 中进行配置,而 Run 方法具有更多的普遍性,具体的调用方法如下。
清单 10
- 典型应用二
在 RFT 中一类经常遇到的问题就是如何处理那些非预期的活动窗体。例如,点击安全网页上的 link,而这个 link 所指向的却是一个非安全的网页,如果浏览器对安全性要求较高的话,就会弹出一个对话框询问你是否仍然打开这个页面,如果选择“是”则下次重复这样的操作将不再会弹出对话框进行询问,否则下次仍然会询问。因此是否会出现这个窗体取决于是否建立了信任关系,而在脚本开发时是无法预见的。
采用常用的对象识别技术,其典型的处理方法如下所示。
清单 11
上述处理方法采用了常用的对象识别技术识别那些非预期的窗体,如果这些窗体无法用常用方法识别,如何来处理这类问题呢?
图 6. 非预期的对话框
图 6 是打开网页前,系统弹出的一个对话框,它是一个 windows 原始窗体,无法采用常用方法识别(当然可以用 IWindow 来识别),以下结合 RFT 和 AutoIt 来处理。
- 开发 AutoIt 脚本。AutoIt 脚本的任务是点击“Security Alert”对话框中的“Yes”按钮。这可以分为两步,第一步判断对话框是否已经存在;第二步点击“Yes”按钮。具体的 AutoIt 脚本如下所示。
清单 12
- 开发 RFT 脚本。RFT 脚本有三个任务,第一是点击安全网页上的 link 使得“Security Alert”对话框出现。第二是调用 AutoIt 脚本关闭弹出的对话框。第三是判断非安全网页是否已经打开。具体的 RFT 脚本如下所示。
清单 13
从以上可以看出,相比单纯使用 RFT,基于 RFT 与 AutoIt 的混合解决方案需要的脚本显著减少,大大提高了脚本开发效率。当然这种混合解决方案需要你对 AutoIt 有一定的了解,增加了学习的负担,但是一旦掌握,对于提高自动化测试效率是很明显的。
总结
本文阐述了各种不同的对象识别技术,其中 IWindow 接口用于识别 windows 标准控件;Invoke 方法用于识别应用程序定制的 GUI 控件;此外还介绍了 windows 平台上一款优秀的自动化工具 AutoIt 以及如何与 RFT 结合进行自动化测试。将 RFT 常用的对象识别技术与这些特定条件下的对象识别技术相结合,能够使得 GUI 自动化测试更加敏捷。
转载:http://www.ibm.com/developerworks/cn/rational/r-cn-extendsrftobj/index.html