RFT概述 一、RFT对象 IBM Rational Functional Tester (RFT)是用于测试 Java、Web、.NET 等各种应用软件的一个自动化测试工具。它支持Java并具备强大的对象识别机制。(基于RFT的自动化测试脚本,都被划分为3个层次:对象层、任务层、用例层。对象识别就是在 RFT 的对象模型框架下,得到被测程序的 GUI 对象。它是对象层开发中最核心的任务。常用的 RFT 的对象识别技术可以分为两大类:静态识别与动态识别)。 通过 RFT,我们可以访问到应用软件中的各个对象以及对象的方法和属性,并以此为依据产生测试脚本,让应用程序自动运行,从而校验程序运行的结果,完成自动化测试。 RFT的对象识别体系,提供了把所有被测试控件映射成为一个树形结构(根是TestObject)的能力,在运行时,它动态地在被测应用程序(application under test,AUT)中定位 TestObject,这使得通过程序来动态遍历所有被测试控件成为可能,并且每个测试对象都被映射成为TestObject的子类来实现,这些TestObject通过树形结构组织在一起,用以映射被测试对象中物件相互包含的关系。如下图:
TestObject 继承:
TestObject类继承于java.lang.Object
TestObject类包含一个参考对象,可以是直接定义参照对象还可以通过使用mapptestobject来间接的定义参考对象。在 RFT ObjectMap 中,由 ObjectManager 来维护mapptestobject对象,ObjectManager 是通过某个识别算法将 Map 中的对象与被测试软件中的对象进行一一对应的。在RFT 中一个非常重要的根接口是 IGraphical 接口,它定义了针对 GUI 元素的所有标准操作(这里的标准操作指的是常用的方法,如click,doubleclick,drag 等),类GuiTestObject,继承自 TestObject 并实现了 IGraphical 接口。
| | | | | 所有测试对象的基础类,适用于几乎所有的图形化控制,并实现了 IGraphical 接口 | | button、dialog、link、document、form、html、image、label | | 调用 startApp 命令时可以使用 ProcessTestObject来确定应用软件的位置的 | | | | | | | | 用RootTestObject 的对象来代表正在被测试软件的整体视图 | | | | 实现了接口IGraphical、IScrollable | | | StatelessGuiSubitemTestObject | 实现了接口IGraphical、IGaphicalSubitem | | | | | | | | 用于高层框架和对话窗口,并实现了窗口IFrame、IGraphical、ITopWindow | | | | | | | | | | | | 用于所有的树、表、名单以及其他管制,并实现了接口IGraphical、IGaphicalSubitem、ISubitem | StatelessGuiSubitemTestObject | | TopLevelsubitemTestObject | 实现了接口IFrame、IGraphical、 IGraphicalSubitem、ISubitem、ITopWindow、 | | | SelectGuiSubitemTestObject | 实现了接口IGraphical、IGaphicalSubitem、ISubitem、ISelect | | | | 实现了接口IGraphical、IToggle、IToggleGUI | | | | 用于高层的HTML浏览器窗口,并实现了接口IBrowserObject、IFrame、IGaphical、ITopWindow | | | | | | |
其中GuiTestObject、BrowserTestObject、ToggleGuiTestObject、TopLevelsubitemTestObject、TextGuiTestObject、TopLevelTestObject、StatelessGuiSubitemTestObject、SelectGuiSubitemTestObject等是比较常用的。 注:表中类的对象在录用过程中是通过 对象_描述性名称 来实现的;如果录用两次,则是 对象_描述性名称2,若是数字,则是 对象_描述性名称_2。例如:button_描述性名称,如果录了两次,则是button_描述性名称2,若是数字,则是button_描述性名称_2 TestObject的方法:
GuiTestObject的方法: ScrollTestObject的方法: | | | | scrollLine***(left、right、up、down) | | scrollPage***(left、right、up、down) | | | |
StatelessGuiSubitemTestObject的方法: 类StatelessGuiSubitemTestObject实现了接口IGraphical、IGaphicalSubitem从而实现了接口IGraphical、IGaphicalSubitem中的方法。 其中接口IGraphical的方法如下表: 接口IGaphicalSubitem的方法如下表: GuisubitemTestObject的方法: Setstate()实现了更改状态的功能 TopLevelSubitemTestObject的方法: selectGuisubitemTestObject的方法: | | | | | | | | select(java.lang.String item) | |
ToggleTestObject的方法: ToggleGuiTestObject的方法: ToplevelTestObject的方法: BrowserTestObject的方法: | | | | | | | | | | | | | | resize(int width, int height) | | move(java.awt.Point screenPt) | | | | | | inputChars(java.lang.String keys) | | | |
TextGuiTestObject的方法: SubitemTestObject的方法: Setstate()实现了更改状态的功能 ProcessTestObject的方法: DomainTestObject的方法: 注: 子类除了自己特有的方法外,还继承了父类中的所有方法。如:ToggleGUITestObject继承ToggleTestObject,所以ToggleGUITestObject有ToggleTestObject的所有方法。并且继承有传递性,ToggleTestObject又继承了GuiTestObject,所以ToggleGUITestObject有ToggleTestObject和GuiTestObject中的所有方法。 二、验证点简介 验证点的类型: RFT具有数据驱动(Data-Driven)测试、ScriptAssure等特性,因而受到广大功能测试人员的青睐。在RFT中,验证点是脚本(Script)中非常重要的组成部分,它完成对被测试程序生成的实际数据和期望数据的比较,并将比较结果写入日志。一般情况下,测试的结果是通过对验证点的执行而得到的。 RFT提供了多种形式的验证点,包括: 静态验证点(Static Verification Point):静态验证点是在录制(Record)RFT脚本的过程中通过向导插入的验证点,它在脚本回放(Playback)的过程中自动被验证。在脚本中是以方法的形式表示的,验证点名字是在验证点被录制时由测试人员指定的验证点决定的。验证点的名字总是表示为 : *** VP().performTest(); 例如:税票打印页面验证点VP().performTest(); 手动验证点(Manual Verification Point):如果验证点所要验证的内容是由脚本开发人员在脚本中所提供的,则需要建立手动验证点对其进行验证。例如待验证数据来自外部数据源的情况,脚本开发人员需将数据读取后以参数的形式显式传给验证点。 手动验证点有两种声明形式: 1. IFtVerificationPoint vpManual (java.lang.String vpName, java.lang.Object actual) 该声明接受两个参数,第一个参数为验证点的名称,第二个参数为被测试对象。 VpManual(“Vp1”,“The object under test”).performTest(); 例如: vpManual(“全选复选框属性验证点”,“allCheckFlag”).perforTest(); 这条语句的作用就是判断被测试对象和基准线(Baseline)是否一致。这里所说的基准线就是期望数据,它以XML格式被存储在磁盘上,后缀名rftvp。 当回放脚本时,如果基准线所对应的文件已经在磁盘上存在,则RFT会比较被测试对象和基准线中的数据是否一致,如果一致,则测试结果为成功(Pass),否则为失败(Failed);如果基准线尚不存在,则会以当前被测试对象作为基准线存入磁盘。 2. IFtVerificationPoint vpManual (java.lang.String vpName, java.lang.Object expected, java.lang.Object actual) 该声明接受三个参数,第一个参数为验证点的名称,第二个参数则为期望数据,第三个参数为实际数据,也就是被测试对象。可以通过如下方式在脚本中调用该方法: VpManual("VP1", "Expected object", "The object under test").performTest()) 例如: vpManual("添加税目明细信息验证点","2",str).performTest(); 当脚本回放时,RFT直接比较期望数据和实际数据,并将比较的结果被写入日志。总的来说,验证点的执行过程如下图所示: 图 验证点执行流程图
动态验证点(Dynamic Verification Point):动态验证点是在脚本首次回放时建立的。验证点一旦建立,其行为就和静态验证点相同了。它也有两种形式: 1.IFtVerificationPoint vpDynamic (java.lang.String vpName) 例如:vpDynamic ("dynamic1").performTest(); 2. IFtVerificationPoint vpDynamic (java.lang.String vpName, TestObject objectUnderTest) 例如:vpDynamic ("dynamic1", AnAWTButtonButton()).performTest(); 如果以录制-回放(Record-Playback)模式使用RFT进行图形界面(GUI)的自动化回归测试(Regression Test),较常用的是静态验证点。而由于RFT的数据驱动测试特性以及与其他RUP工具的良好集成,使之也是非图形化界面的功能测试的首选工具之一。在这些测试用例中,存在着大量的用户自定义类型对象,这些被测试对象并不能在录制过程中被插入对象映射表(ObjectMap)中,也就是不能使用静态验证点来进行验证,这就需要我们使用手动验证点来比较他们。 三、RFT与数据驱动测试 数据驱动测试是一项单个脚本使用不同的输入和响应数据重复执行的技术。在数据驱动测试中,自动化测试脚本使用从外部数据源中读取的变量,而不是直接使用文字值(Literal value)。数据驱动测试的优势在于其将数据与测试脚本分离,从而可以在不修改测试脚本的情况下通过更新测试数据池中的数据完成对测试用例的增加、更改和删除。 在RFT 中通常使用数据池(Datapool)作为数据驱动测试的数据源。数据池是一系列数据记录的集合。这些记录作为测试脚本回放时的变量输入。RFT 数据池为表格结构(Tabular)。要创建数据池,用户可以通过 RFT 所提供的数据池编辑器直接创建测试数据池或者在脚本录制过程中生成私有数据池,也可以从 Excel 或者 Rational Test Manager 中导入数据。数据池建立后,将其与 RFT 的测试脚本相关联,被关联的测试脚本就可以通过迭代器读取数据池的记录,从而实现数据驱动测试了。RFT的数据池包含公有数据池和私有数据池: 私有数据池: 在脚本的录制过程中,点击插入数据驱动的命令按钮, 按住并拖动手行光标来选择测试对象 点击确定即可。在脚本代码中就生成了相应的代码, 私有数据池中的数据只能被本脚本在回放过程中调用,其它脚本不能调用。 公有数据池: 通过新建一个测试数据池可以创建一个公有数据池,也可以从 Excel 或者 Rational Test Manager 中导入数据,使得不同的脚本在回放过程中都可以从该数据池中读取数据。 导入后缀名为csv的数据池 点击“文件”>“导入” 点击“下一步” 选择要导入的csv文件的位置,并点击“下一步” 输入数据池的名称,并选择要创建的位置,点击“完成”,则数据池就导入成功。 在调用公有数据池的时候,要先连接数据池,设置数据池的路径,然后再调用数据池中的数据。例如: 四、TestObject类与接口 ***TestObject类实现了接口,从而也实现了接口中的方法,下面介绍接口中的方法,以及实现接口的类是如何实现接口中的方法的,灵活运用这些类、接口及其方法,能够极大地扩展 RFT 对象识别的功能。 4.1接口之间的继承关系及方法: 4.1.1接口之间的继承关系:(如下图) 4.1.2接口中的方法 IGraphical接口 IGraphicalSubitem接口 IWindow接口 ITopWindow接口 IFrame接口 | | | | | | | | | | | | resize(int width, int height) | | | |
ISelect接口 | | | | | | | | select(java.lang.String item) | |
IClickTo接口 | | clickTo(MouseModifiers modifiers, Subitem subitem) | | clickTo(MouseModifiers modifiers, Subitem subitem, java.awt.Point pt) | | | |
IText接口 | | | | setText(java.lang.String text) | |
IBrowserObject接口 IFileDialog接口 | | | | | | setFile(java.lang.String file) | |
IInternalFrame接口 方法toFront() IScreen接口 | | | | | | inputChars(java.lang.String characters) | | inputKeys(java.lang.String keys) | | windowFromHandle(long handle) | | windowFromPoint(java.awt.Point point) | |
IScrollable接口 | | | | scrollLine***(left、right、up、down) | | scrollPage***(left、right、up、down) | | | |
ISubitem接口 | | | | setState(Action action, Subitem item) | setState(Action action, Subitem start, subitem end) |
ITestObjectReference接口 IToggle接口 IToggleGUI借口 | | clickToState(MouseModifiers modifiers, State state) | | dragToState(MouseModifiers modifiers, State state) |
4.2实现接口的类是如何实现接口中的方法 接口是抽象类的变体。接口中的所有方法都是抽象的,没有一个有程序体。接口中定义的变量默认是public static final 型。接口是用关键字interface来定义的 例如: 定义了接口ApplyForTableInterface,该接口中有两个方法setParasDerault和inputTable。 类ApplicantRegisterTable实现了接口ApplyForTableInterface 则类ApplicantRegisterTable要实现接口中的所有方法,否则就会报错 接口中的方法没有程序体,只有在实现该接口的类中才有该方法的程序体,实现该方法: 类ApplicantRegisterTable定义了接口中的方法。 |