更有效使用 IBM Rational Functional Tester 的方法

转自:http://www.ibm.com/developerworks/cn/rational/09/userationalfunctionaltestereffectively/index.html

IBM Rational Functional Tester 提供了一些特性,用户可以使用这些特性来有效测试 GUI 程序。IBM Quality Software Engineering(QSE)团队引入了一个层级结构框架,也就是所谓的 QSE 框架,以让维护变得更加容易。该框架使用 Rational Functional Tester 对象认知特性。本文向您展示了怎样扩展 QSE 框架,以及怎样使用 Rational Functional Tester 的特性来提高测试的生产效率。您还可以得到可以有效支持测试多语言程序的建议。

导言

IBM® Rational® FunctionalTester 提供了自动化测试的特性。为了使用记录特性,您可以记录一次测试活动并将其保存为测试脚本。在此之后,不论何时您想要执行相同的测试时,都可以运行该测试脚本。

在您测试却想要输入数据时,您可以在记录期间使用测试数据汇特性。如果您使用了测试数据汇特性,那么您就可以在运行测试脚本之前更改输入数据了,而不需要重复记录该测试活动。您可以使用验证点,Rational Functional Tester 会使用它来比较实际值和预期值,然后生成一个带有详细信息的报告,信息会向您展示是否得到了预期值。但是,使用记录特性您也许会关注,当测试的程序被更改过时,您也许会需要重新记录测试活动。

为了降低操作的难度,IBM Quality Software Engineering(QSE)团队引入了一个层级结构的框架,也就是所谓的 QSE 框架。该 QSE 框架会将 GUI 对象与测试用例隔离开来。Rational Functional Tester 提供了 Test Object Map 特性,使用该特性可以获得 GUI 对象。通过使用 GUI 对象的方法可以执行对 GUI 的操作。QSE 框架由以下三层组成。

  • appobjects 文件包含了测试对象映射特性获取的 GUI 对象。
  • tasks 文件夹包含的程序,通过使用 appobjects 文件夹中的对象来执行 GUI 操作。GUI 操作可以当做任务来分类和实施。例如,注册进程可以当做任务来实施。
  • testcases 文件夹包含了程序,您可以使用 tasks 文件夹中的程序来执行测试用例,并且可以记录结果。

您可以使用 QSE 框架来提高维护性。如果想要得到关于 QSE 框架的更多信息,可以引用参考资源章节中的 An Object-Oriented framework for IBM Rational Functional Tester 项。

本文向您展示了通过扩展 QSE 框架和使用 Rational Functional Tester 特性(例如测试数据汇和验证点),怎样更加有效地自动化测试。本文还向您介绍了一些技巧,这些技巧是关于怎样测试支持多种语言的程序的。

提供 GUI 控制方法

考虑一下测试图 1 中所示的程序。


图 1. 程序 GUI
数据库关系分析器

点击以放大

在这个 GUI 中,您可以选择 Actions > Create New Set 菜单项,如图 2 所示。通过 Test Object Map 特性可以获得这些对象。


图 2. 程序菜单
菜单命令

对于 QSE 框架提供的 jar 文件,您可以定义如图 3 和列表 1 所示的方法,以得到 Test Object Map 特性获取的 GUI 对象。


图 3. 得到 GUI 对象的测试对象和程序
左边是代码,右边是 .. Explorer

点击以放大


列表 1. 得到 GUI 对象的程序

package appobjects;

import resources.appobjects.MainGUIHelper;
import ibm.widgets.*;
import ibm.widgets.ancestors.*;
import ibm.widgets.swt.*;

import com.rational.test.ft.*;
import com.rational.test.ft.object.interfaces.*;
import com.rational.test.ft.script.*;
import com.rational.test.ft.value.*;
import com.rational.test.ft.vp.*;

public class MainGUI extends MainGUIHelper {

  public ToggleWidget getActions() {
    TestObject to = actions(ANY, NO_STATE);
    return new ToggleWidget(to);
  }

  public ToggleWidget getActionsCreateNewSet() {
    TestObject to = actionsCreateNewSet(ANY, NO_STATE);
    return new ToggleWidget(to);
  }

  public ToggleWidget getConfigureGroupDiscoveryOptions() {
    TestObject to = configureGroupDiscoveryOptions(ANY, NO_STATE);
    return new ToggleWidget(to);
  }

  public ToggleWidget getCreateNewView() {
    TestObject to = createNewView(ANY, NO_STATE);
    return new ToggleWidget(to);
  }

  public SubitemWidget getGrdTree() {
    TestObject to = grdTree(ANY, NO_STATE);
    return new SubitemWidget(to);
  }

  public ToggleWidget getRunGroupDiscovery() {
    TestObject to = runGroupDiscovery(ANY, NO_STATE);
    return new ToggleWidget(to);
  }

  public ToggleWidget getRunTraceAnalyzer() {
    TestObject to = runTraceAnalyzer(ANY, NO_STATE);
    return new ToggleWidget(to);
  }

  // -----------------------------------------

  public void testMain (Object[] args) 
  {
     // Unit testing can go here
     // (will be deleted next time ClasGenerator is run)
  }
}

列表 2 中的程序模拟点击 Actions 菜单,然后点击 Create New Set 子菜单。


列表 2. 检查程序以点击菜单项

MainGUI mainGui = new MainGUI();
mainGui.getActions().click();
mainGui.getActionsCreateNewSet().click();

正如本例所示,您可以通过使用 GUI 对象来轻松控制 GUI。但是,找到用于执行 GUI 操作的方法会很困难。图 4 显示了一个范例:当您右击树形结构的节点时,考虑一下这个例子。


图 4. 展开树形节点的菜单
右击     TRACE_ANALYSIS

在树形结构中,您不能将每一个节点当做一个对象。如图 5 所示,您需要得到树对象,然后使用方法中的一种以右击树的节点。


图 5. 获取树对象
获取一个树对象

如果您不知道 GUI 对象是怎样执行 GUI 操作的(就像本例),那么您可以使用记录特性,然后引用生成的程序。在本例中,当您记录右击节点时,您可以得到如列表 3 所示的程序。


列表 3. 生成程序以模拟右击树的节点

public void testMain(Object[] args) 
{
	
	// Frame. Database Relationship Analyzer
	grdTree().click(RIGHT, atPath("SAMPLE->ORDER->TRACE_ANALYSIS"));
}

在 tasks 文件夹中编写这种程序并不是十分有效。相反,在类中编写通用方法以模拟以上的操作就比较合适了,它继承了 appobjects 文件夹中的 GUI 对象类。这种类型的类并不需要当做一个 Rational Functional Tester 脚本来创建:将其当做一个 Java™类来创建已经足够了。创建一个文件夹,例如一个名为 apputils 的文件夹,以存储这种类型的类。列表 4 中的程序显示了右击树节点的通用方法。 MainGUIUtil 类继承了 MainGUI 类。 MainGUI 类包含了主窗口中的 GUI 对象,它位于 appobjects 文件夹之下。前面使用的 grdTree 方法,可以用于将树对象替换为 MainGUI 类中定义的书对象,在本例中是 getGrdTree 方法。


列表 4. 模拟右击树节点的范例程序

public class MainGUIUtil extends MainGUI {
	public void rightClickView(String dbName, String setName, String viewName) {
		String s = dbName + "->" + setName + "->" + viewName;
		getGrdTree().click(RIGHT, atPath(s));
	}

通过使用这样的方法,tasks 文件夹中的程序可以和 GUI 操作一样得到直觉地实施。

有效的自动化数据输入过程

对于 QSE 框架,输入数据的过程如下所示。

  1. 通过使用 Test Object Map 特性来获取每一个输入区域,以得到它的 GUI 对象。
  2. 定义方法以得到 GUI 对象。
  3. 通过使用 GUI 对象的方法来设置输入值。

您可以使用 Test Datapool 特性,来有效地执行数据输入操作。例如,图 6 显示了一个带有输入区域的 GUI。考虑一下该 GUI 中的输入数据。


图 6. 带有输入区域的程序 GUI
运行 Trace Analyzer 窗口

在打开该 GUI 之后,开始记录,然后通过选择 Insert Data Driven Commands 获取该窗口。在获取之后,暂停您的记录操作,输入假程序数据以激活 OK 按钮,重命名记录操作,点击 OK,然后停止记录。当您这样做时,会生成如图 7 和列表 5 所示的程序。如果您想要对由多个面板组成的向导应用该技术,那么就在每一个面板中插入数据驱使的命令,这样您就可以参数化所有的输入区域了。


图 7. 随着 Test Datapool 特性一起生成的程序
左边是代码,右边是 .. Explorer

点击以放大


列表 5. 生成的程序

package recordingobjects;
import resources.recordingobjects.RunTraceAnalyzerGUIRecordingHelper;
import com.rational.test.ft.*;
import com.rational.test.ft.object.interfaces.*;
import com.rational.test.ft.object.interfaces.SAP.*;
import com.rational.test.ft.object.interfaces.WPF.*;
import com.rational.test.ft.object.interfaces.dojo.*;
import com.rational.test.ft.object.interfaces.siebel.*;
import com.rational.test.ft.object.interfaces.flex.*;
import com.rational.test.ft.script.*;
import com.rational.test.ft.value.*;
import com.rational.test.ft.vp.*;

public class RunTraceAnalyzerGUIRecording extends RunTraceAnalyzerGUIRecordingHelper
{
  public void testMain(Object[] args) 
  {
    // Data Driven Code inserted on 2009/02/28
    
    // 
    schemaName().setText(dpString("SchemaName"));
    tableName().setText(dpString("TableName"));
    startDate().setText(dpString("StartDate"));
    startTime().setText(dpString("StartTime"));
    endDate().setText(dpString("EndDate"));
    endTime().setText(dpString("EndTime"));
    ok().click();
  }
}

如果您定义了一个包含该程序的方法,那么其他的程序就可以调用该方法了。当您调用该方法时,测试数据汇中定义的值会在合适的区域中得到设置。正如您在图 7 和列表 5 中看到的那样, dpString 方法用于得到来自测试数据汇的值。

如果您更改了方法,以通过方法参数传递输入值,那么该方法就可以得到通用的应用了。在本例中,如果您为开始时和结束时使用了测试数据汇值,并通过方法参数动态地设置其他的输入值,那么方法如列表 6 所定义的那样。


列表 6. 动态输入数据的范例程序

public void runTraceAnalyzer(String schema,
			String table,
			String startDate,
			String endDate)
{
	schemaName().setText(schema);
	tableName().setText(table);
	startDate().setText(startDate);
	startTime().setText(dpString("StartTime"));
	endDate().setText(endDate);
	endTime().setText(dpString("EndTime"));
	ok().click();
}

自动结果验证

如果有一些结果会显示在 GUI 中,那么通过使用验证点特性,就可以很容易地比较实际值和预期值了。

静态地验证结果

例如,如果您想要得到如图 8 所示的表格,那么就在记录开始之后,将表格当做验证点,然后停止记录。它会产生如图 9 和列表 7 所示的程序。


图 8. 包含一些结果的表格
带有 6 行和 2 列的表格

图 9. 生成验证点特性的程序
左边是代码,右边是 .. Explorer

点击以放大


列表 7. 生成的程序

package verificationpoints;
import resources.verificationpoints.TestResult1Helper;
import com.rational.test.ft.*;
import com.rational.test.ft.object.interfaces.*;
import com.rational.test.ft.object.interfaces.SAP.*;
import com.rational.test.ft.object.interfaces.WPF.*;
import com.rational.test.ft.object.interfaces.dojo.*;
import com.rational.test.ft.object.interfaces.siebel.*;
import com.rational.test.ft.object.interfaces.flex.*;
import com.rational.test.ft.script.*;
import com.rational.test.ft.value.*;
import com.rational.test.ft.vp.*;

public class TestResult1 extends TestResult1Helper
{
  public void testMain(Object[] args) 
  {
    table().performTest(ResultTableVP());
  }
}

复制以上的程序以创建如列表 8 所示的方法。如果您调用了该方法,那么 Rational Functional Tester 会自动比较实际值和预期值。


列表 8. 验证结果的范例方法

public void verifyResult() {  table().performTest(ResultTableVP()); }

动态地验证结果

如果您想要动态地更改预期值,那么您可以使用 IFtVerificationPointvpManual(java.lang.String vpName, java.lang.Object expected, java.lang.Object actual).performTest methodvpManual 方法有三个 参数。第一个参数是设置项目中独一无二的验证点名,第二个参数是设置预期的对象,而第三个参数是设置一个实际对象。如果您想要比较如本例中那样表格中的值,那么您可以使用vpManual方法中第二个和第三个参数的 com.rational.test.ft.vp.impl.TestDataTable类对象。您可以创建如列表 9 所示的预期对象。您还可以指定比较的区域,它是在 setComparisonRegions方法中完成的。


列表 9. 创建一个表格作为预期结果的范例程序

TestDataTable tbl = new TestDataTable();
tbl.setColumnHeader(0, "Table Name");
...
tbl.insert(new String[7], 0);
tbl.setCell(0, 1, "CUSTINFO");
...
TestDataTableRegions regions = new TestDataTableRegions();
regions.addRegion(TestDataTableRegion.allCells());
tbl.setComparisonRegions(regions.getRegions());

在接下来的例子中,您可以使用验证点对象作为预期对象,它是通过获取 GUI 表格作为上例中的验证点得以创建的。它将会创建一个预期的对象。接下来,编辑该对象的值。为了得到实际值,您可以使用测试对象映射获取的table对象的getTestData(String testDataType)方法,如列表 10 所示。 testDataType 参数拥有显示在验证点窗口中的 type属性。您可以在图 10 中看到它。在本例中,该值是“可视的内容”。


列表 10. 验证表格结果的范例方法

Public void verifyResult() {
	TestDataTable tbl = (TestDataTable)ResultTableVP().getBaselineData();
	tbl.setCell(0, 1, "CUSTHIST2");
	vpManual("VP1", tbl, table().getTestData("visible contents")).performTest();
}

在本程序中,“CUSTHIST2”在一个单元中得到设置,以前它是“CUSTHIST”。运行这种方法会产生一个错误,您会得到如图 10 所示的信息。


图 10. 导致一个验证点的具体结果(表格)
左边是属性的表,右边是值

点击以放大

前面的范例讨论了 table 对象。可以比较的其他对象如表格 1 所示。


表 1. 可以比较的对象

GUI 类型
com.rational.test.ft.vp.impl.TestDataTree
列表com.rational.test.ft.vp.impl.TestDataList
菜单栏com.rational.test.ft.vp.impl.TestDataTree
Character 字符串字符串

tree 对象中,列表 11 显示了一个添加节点到作为验证点获取的 tree 对象的程序。


列表 11. 验证树结果的范例方法

public void verifyResult() {
	TestDataTree tree = (TestDataTree)GRDTreeVP().getBaselineData();
	TestDataTreeNodes nodes = (TestDataTreeNodes)tree.getTreeNodes();
	TestDataTreeNode node = (TestDataTreeNode)nodes.getRootNodes()[0];
	node = (TestDataTreeNode)node.getChild(0);
	node = (TestDataTreeNode)node.getChild(0);
	node = (TestDataTreeNode)node.getChild(0);
	
	TestDataTreeNode node2 = new TestDataTreeNode();
	node2.setNode("GROUP2");
	
	TestDataTreeNode[] n = new TestDataTreeNode[2];
	n[0] = (TestDataTreeNode)node.getChild(0);
	n[1] = node2;
	node.setChildren(n);
	
	vpManual("TreeVP1", tree, grdTree().getTestData("tree")).performTest();
}

当您运行该程序时,您会得到如下的信息(图 11)。


图 11. 验证点(树)中的具体结果
左边是表格,右边是树视图

list 中,列表 12 显示了向作为验证点获取 list 对象添加项的程序。


列表 12. 验证列表结果的范例方法

public void verifyResult() {
	TestDataTree tree = (TestDataTree)GRDTreeVP().getBaselineData();
	TestDataTreeNodes nodes = (TestDataTreeNodes)tree.getTreeNodes();
	TestDataTreeNode node = (TestDataTreeNode)nodes.getRootNodes()[0];
	node = (TestDataTreeNode)node.getChild(0);
	node = (TestDataTreeNode)node.getChild(0);
	node = (TestDataTreeNode)node.getChild(0);
	
	TestDataTreeNode node2 = new TestDataTreeNode();
	node2.setNode("GROUP2");
	
	TestDataTreeNode[] n = new TestDataTreeNode[2];
	n[0] = (TestDataTreeNode)node.getChild(0);
	n[1] = node2;
	node.setChildren(n);
	
	vpManual("TreeVP1", tree, grdTree().getTestData("tree")).performTest();
}

当您运行该程序时,会得到以下的信息(图 12)。


图 12. 验证点(列表)中的具体结果
左边是表格,右边是值

测试支持多种语言的程序

为了测试多个语言的程序,您可以使用包含密钥和值对( [KEY]=[VALUE]),此处该值会显示在 GUI 中。资源文件的一个范例是在 Java 的 ResourceBundle 类中使用的资源文件。配置该文件的步骤如下所示。

  1. Rational Functional Tester 的 ivory.properties 文件中以下的属性的目录被激活。
    # When enabled this property allows string look up in a localized string table, 
     if available
    rational.test.ft.services.enable_localization=true

  2. 在将文件的基底名字更改为 Rational Functional Tester 项目名之后,包含密钥和值对的程序的资源文件,会复制到 Rational Functional Tester 项目的资源文件夹之下。显然创建文件也是可行的。资源文件名格式为:
    • [Rational Functional Tester project name]_[language].properties
    例如,在本例中 Rational Functional Tester 项目名为“DRAProject”,日本资源文件名为:
    • DRAProject_ja.properties
  3. 重启 Rational Functional Tester。
  4. 打开测试对象图,然后将作为 GUI 显示值的属性值,更改为资源文件的密钥名。有一些属性名,例如下面的,有 GUI 显示值。
    • accessibleContext.accessibleName
    • .captionText
    • name
    • text
    在子菜单中,有一些属性值会与由下划线(“_”)隔开的上级菜单联系起来。在这种情况下,将权重变为 0。

例如,将英文资源文件复制到日本资源文件中,然后在每一个值的前面添加一些日本字符。您可以在如图 13 中的 GUI 中这样做。


图 13. 日语的程序 GUI
左边是树视图,右边是细节信息

点击以放大

打开测试对象图,然后将作为 GUI 显示值的属性值更改为资源文件的密钥名字,如图 14 所示。


图 14. 在测试对象图中输入资源文件的密钥名
顶部的树视图,底部是具体信息

点击以放大

当您按住 Enter 键时,密钥名就会更改为合适资源文件中的实际值,如图 15 所示。密钥名就存储在里面,值会根据语言环境而发生动态的变化。当您双击属性值,以再次切换编辑模式时,您可以看到资源文件的密钥名。当您更改资源文件的一些值时,然后重启 Rational Functional Tester,在测试对象图中您可以看到更改的值。


图 15. 将密钥名自动更改为资源文件中的值
顶部的树视图,底部是具体信息

点击以放大

接下来的 name 属性,具有与上级菜单名相联系的值,由下划线(“_”)隔开。所以它的权重会更改为 0(图 16)。


图 16. 为找到 GUI 对象更改属性的权重
顶部的树视图,底部是具体信息

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17117101/viewspace-618397/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/17117101/viewspace-618397/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值