使测试自动化脚本与域无关以重用测试脚本

使用 IBM Rational Functional Tester 描述性编程实现跨域的脚本重用

在测试自动化中,会将测试脚本和相关的测试框架绑定到接受测试的应用程序底层域。然后,判断是否可以跨域使用框架提供的相同记录对象、脚本和可重用函数就成为了一个难题。要克服这个问题,关键是使得自动化测试脚本与域无关。其结果是,可以跨不同的测试应用程序域使用相同的应用程序对象、测试脚本和可重用函数,无需考虑它们是否是 HTML、Java、Microsoft .NET、Microsoft Windows 等。

Shruti Grover, 高级软件工程师, IBM

作者照片Shruti Grover 是 IBM India Software Labs Software Technology Group 的 Retail Software Solutions Group 中的一名自动化顾问和测试负责人。她有超过 11 年的工作经验,掌握了各种商用和开源测试自动化与测试管理工具的专业知识,是 Rational Functional Tester 测试团队的负责人,实现了多个测试框架。她已在本地及国际会议上发表过有关测试主题的演讲,其中包括 IBM 亚太和拉丁美洲优质软件工程研讨会、IBM Rational 技术交流、质量保证研究院、Rational 软件开发大会以及 TechConnect。她曾撰写过有关 Rational Functional Tester 的 developerWorks 文章。



2012 年 8 月 10 日

免费下载:IBM® Rational® Functional Tester 试用版  |  IBM® Rational® 测试人员资源工具包
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

问题:域依赖性阻碍了脚本的重用

无论测试自动化开发人员通过记录回放还是传统描述性编程来创建脚本,测试脚本和可重用函数都会绑定到接受测试的应用程序的底层域。那么,我们如何确保编写功能的工作(例如,将文本设置到某个 Edit Box)在每次域转变时都不会重复?今天,您可能正在为某个基于 Web 的应用程序编写测试脚本,并且每次都以 HTML 格式针对域进行记录和编写脚本。随后,您可能需要使用您之前已经编写代码的相同功能,但要跨一个基于 Java 的应用程序。

当我们使用记录回放机制时,所有与应用程序交互的测试对象都被记录和存储在 IBM® Rational® Functional Tester 对象映射中。图 1 显示了一个这样的示例,其中应用程序域被硬编码为 Java。

图 1. 以 Java 作为应用程序域的一个对象映射
屏幕显示 Test Domain (#domain) 值为 Java

类似地,如果使用描述性编程机制开发测试脚本,函数会被绑定到某个特定的应用程序域。在这种情况下,实现测试函数可重用性就会变得具有挑战性。

因此,最好使脚本和底层测试对象与应用程序域无关。


解决方案:使用描述性编程实现跨域兼容性

Rational Functional Tester 提供一种动态机制,在脚本回放过程中获得测试对象的引用。find() API 使这一点成为可能,因为它引用接受测试的应用程序中的对象时,无需在测试对象映射中记录或硬编码该对象。该 API 找到父测试对象或顶层测试对象,并查找一个匹配的子对象。

使用 find() API 识别域或顶层对象

鉴于这一点,通过描述性编程实现测试自动化框架以及使用 find() API 可以有助于识别接受测试的应用程序的域或顶层对象,并相应地找到该对象下面的一个匹配的子测试对象。清单 1 中的代码说明了该过程。

清单 1. 为当前应用程序设置测试域值
 String myDomainName = "";

//For HTML Browser - Set the Application Domain Name
myDomainName = "Html.HtmlBrowser";

OR

//For HTML Dialog - Set the Application Domain Name
myDomainName = "Html.Dialog";

OR

//For Swing JDialog - Set the Application Domain Name
myDomainName = "javax.swing.JDialog ";

OR

//For Swing JFrame - Set the Application Domain Name
myDomainName = "javax.swing.JFrame";

OR

//For Custom Parent Objects - Set the Application Domain Name
myDomainName = " com.ibm.retail.rma.res.ui.config.MasterAgentInfoDlg ";

在 Rational Functional Tester 代码中,当应用程序域被设置后,顶层测试对象可以被解析为它所要映射到的父对象类型。清单 2 中的代码片段说明了这一点。在本例中,如果域是 HTML Browser,顶层对象被解析为 BrowserTestObject;如果域是 HTML Dialog,顶层对象被解析为 TopLevelTestObject,等等。

清单 2. 将父对象解析为应用程序域
/* Parse the Top Level Test Object to the corresponding test object type based 
 * on the domain name that was set
 */

TestObject myDomain;

if (myDomainName.equalsIgnoreCase("Html.HtmlBrowser")) {
	myDomain = (BrowserTestObject)
			returnTO(".class", "Html.HtmlBrowser");
}
else if (myDomainName.equalsIgnoreCase("Html.Dialog")) {
	myDomain = (TopLevelTestObject)
			returnTO(".class", "Html.Dialog");
}
else if (myDomainName.equalsIgnoreCase("javax.swing.JDialog")) {
	myDomain = (TopLevelTestObject)
			returnTO(".class","javax.swing.JDialog");
}
else if (myDomainName.equalsIgnoreCase("javax.swing.JFrame")) {
	myDomain = (TopLevelTestObject)
			returnTO(".class", "javax.swing.JFrame");
}
else if (myDomainName.equalsIgnoreCase
		("com.ibm.retail.rma.res.ui.config.MasterAgentInfoDlg")) {
	myDomain = (TopLevelTestObject)
			returnTO(".class",
			"com.ibm.retail.rma.res.ui.config.MasterAgentInfoDlg");
}

/* This function returns the 1st instance of a test object based on the 
 * recognition property and the property value provided.  If the test object 
 * is not found null will be returned.
 */
public TestObject returnTO(String recognitionProperty,
                            String recognitionPropertyValue,) {
		
	RootTestObject rTO = getRootTestObject();
	TestObject[] TOs = rTO.find(atDescendant(recognitionProperty, propValue));
	TestObject returnTO = null;
	int numOfObjects = TOs.length;
	if (numOfObjects >= 1)
		returnTO = TOs[0];
	
	return returnTO;
}

在将顶层测试对象解析为正确的父测试对象类型后,使用 find() API 将有助于获得该对象下面的子对象的引用。然后,您可以编写一个通用的可重用函数,该函数将以跨域的方式工作。清单 3 中的代码显示一个示例,其中定义了通用 setText 函数,无论应用程序域是 HTML、Java、.NET,还是基于当前图形化用户界面技术的任何其他域,该函数均有效。

清单 3. 通用的跨域 setText() 函数
public boolean setTextGuiTestObject(TestObject myDomain,
                    String recognitionProperty,
                    String recognitionPropertyValue,
                    String valueToSet) {
	boolean status = true;
		
	try {
		TestObject[] TOs = null;
		TOs = myDomain.find(atDescendant
				(recognitionProperty, recognitionPropertyValue));
		int numOfObjects = TOs.length;

		if (numOfObjects >= 1) {
				
			TextGuiTestObject myGTO1 = null;
			
			myGTO1 = (TextGuiTestObject) TOs[0];
			myGTO1.waitForExistence(2500, 0.10);
			if (myGTO1.exists()) {
				System.out.println("Setting Text: " + valueToSet);
				myGTO1.click();
				myGTO1.setText(text);
			}
		}
		myGTO1.unregister();
	}
	catch (Exception e) {
		System.out.println("Unable to set Text :: " + e.toString());
		status = false;
	}
	return status;
}

在本例中,该函数没有绑定到任何应用程序域。相反,在将值设置到 Text Box 之前,应用程序域作为一个输入参数被传递给该函数。因此,只要提供了正确的域、标识属性以及要设置的值,自动化脚本就能够在任何域的编辑框中设置文本。

当应用程序域经常改变时使用该方法

然而,该自动化测试脚本开发模型还解决了另一个方面的问题。

在自动化测试中,接受测试的应用程序常常会从一个域转变到另一个域。以下是一个示例场景:

  • 您在一个 HTML、基于 Web 的应用程序上开始自动化。在这种情况下,顶层测试对象是:HTML.Browser。
  • 在脚本中,某个操作启动了一个 HTML 对话框。从 Rational Functional Tester 的透视图可看到,顶层测试对象现在已经转移到 HTML Dialog。
  • 在更多导航之后,这个基于浏览器的应用程序会启动了一个 Java Swing 对话,其中顶层测试对象已转换为 javax.swing.JDialog。

在所有这些情况中,如果有一个通用的操作将文本设置到各自顶层测试对象下面的子对象,这种使函数与域无关的方法将会有很大的帮助。您需要做的只是传递与该操作相关的域。就是说,您首先传递一个 HTML.Browser、HTML.Dialog,然后再传递 javax.swing.JDialog。代码清单 4 说明了这一点。

清单 4. 顶层应用程序域经常改变的情况
 TestObject myDomainName;
String myDomainName = "";

/*
 * Step 1 - Set value to the text box in Html.Browser
 */
myDomainName = "Html.HtmlBrowser";
if (myDomainName.equalsIgnoreCase("Html.HtmlBrowser")) {
	myDomain = (BrowserTestObject)returnTO(".class", "Html.HtmlBrowser");
}
setTextGuiTestObject(myDomain, ".id", "hostname", "StoreServer");


/*
 * Step 2 - Set value to the text box in Html.Dialog
 */
myDomainName = "Html.Dialog";
if (myDomainName.equalsIgnoreCase("Html.Dialog")) {
	myDomain = (TopLevelTestObject)returnTO(".class", "Html.Dialog");
}
setTextGuiTestObject(myDomain, ".id", "searchIP", "9.124.45.43");


/*
 * Step 3 - Set value to the text box in javax.swing.JDialog
 */
myDomainName = "javax.swing.JDialog";
if (myDomainName.equalsIgnoreCase("javax.swing.JDialog ")) {
	myDomain = (TopLevelTestObject)returnTO(".class", "javax.swing.JDialog");
}
setTextGuiTestObject(myDomain, ".id", "searchPort", "9443");

在一个频繁改变的应用程序域场景中,该方法非常有效。自动化脚本和函数变成可重用,因而减少了冗余。


该方法的价值的总结

您可以在商用或开源的任何自动化工具中有效地使用本文中所描述的方法。使您的脚本与域无关并不只是实现脚本的可重用性。当在某个域(如 HTML)中构建的应用程序功能被转移到另一个域(如 Java)时,它还可以使脚本运行稳定。但无论如何,在您编写测试脚本之后,它都可以在相同产品生命周期的多个版本中使用。

此外,由于这些通用函数的可重用性是使用跨域方法的结果,这些脚本和函数不会被绑定到特定产品或应用程序域。

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Rational
ArticleID=832856
ArticleTitle=使测试自动化脚本与域无关以重用测试脚本
publish-date=08102012