top
Loading...
RFT與Spring結合進行自動化腳本開發之一
Spring具有強大的功能:Ioc,可以實現在xml中把一個測試對象注入到另一個測試對象中,再加上可以利用RFT的find方法可以把spring的配置文件配置成一張RFT測試對象地圖。目前,大部分自動化腳本開發者利用RFT的測試對象地圖管理測試腳本的測試對象,RFT的測試對象地圖有兩種類型:公有測試對象地圖和私有測試對象地圖。

(1)大部分腳本采用的都是私有測試對象地圖,如果被測試的程序頂層對象發生變化,這樣每個腳本關聯的測試對象地圖都要進行修改,之所以這樣,有一個原因:在RFT中測試對象地圖不能夠繼承(僅僅可以合并),如果兩個測試對象地圖之間可以進行繼承,這樣把公用的測試對象放在父測試對象地圖中,其他的測試對象地圖繼承這個公用的測試對象地圖(同時繼承公有的測試對象),如果被測試程序頂層框架發生變化,僅僅只修改父測試對象地圖就可以了,但是目前RFT中不能實現(據我了解)。

(2)RFT中還有一種類型的測試對象地圖是公有的測試對象地圖,公有的測試對象地圖可以實現公用的測試對象重復使用,如果測試對象是一模一樣的,RFT在公有的測試對象地圖中只保留此測試對象的一個實例,但是把多個測試對象都插入到一個測試對象地圖中,同樣又面臨著難以管理的困難。

(3)另外,RFT中的測試對象地圖與腳本緊緊的耦合,如果程序即使發生很小的變動,也要更新測試對象地圖,修改腳本等等。

(4)一個spring配置文件可以被另一個spring文件import進來。這樣可以把公有的測試對象放在一個spring配置文件中,然后有其他的spring配置文件進行導入,可以實現測試對象地圖(spring的配置文件)的繼承。另外,在spring的配置文件中,可以注入一個對象的屬性,這樣可以人工的更改這個測試對象的父框架,另外可以可以注入測試對象的識別屬性,這樣可以進行人為的進行測試對象識別屬性的更改(這樣可以更好的應對被測試程序的變化)。

例如:

xml 代碼

<!--從classpath(類路徑)中導入base-test-object-map.xml文件 可以使用base-test-object-map.xml文件中定義的bean-->
<!--導入時候要包含完整的包名-->
<import resource="classpath:pkg/base-test-object-map.xml"/>

<!--設置待查找對象的識別屬性 格式:propertyName-propertyValue-->
<property name="objectProperties">
<list>
<!--屬性名稱和屬性精確匹配用=-->
<!--屬性名稱和屬性用正則表達式匹配用:-->
<value>.class=Html.FORMvalue> 然后是怎么使用spring配置文件中的測試對象
<value>.name:.*Formvalue>
list>
property>

<!--設置從什么對象開始查找 注入父測試對象-->
<!--browserTestObject 引用的是base-test-object-map.xml文件中已經定義的bean-->
<property name="parentTestObject">
<ref bean="browserTestObject"/>
property>

在腳本中引用測試對象通過如下語句:

java 代碼

TextGuiTestObject text_userName = new TextGuiTestObject((TestObject)context.getBean("userNameText"));
text_userName.setText("system");

(5)采用spring管理測試對象,也不是說一勞永逸的,如果被測試程序發生變化,避免不了的也要修改spring配置文件。但是,至少比RFT管理測試對象地圖的修改量要小的多。

(6)采用spring管理測試對象也有以下缺點:

(1)需要測試腳本開發者有比較高的編程技能(熟悉springIoc基本配置和對RFT API比較熟悉)

(2)被測試程序結構規范,最好每個HTML元素都有其名字,還有每次修改程序,如果HTML元素名稱能不修改最后就不修改(RFT可以通過組件名稱查找對象)還有就是按鈕上面的文本,采用RFT管理測試對象地圖也有此要求。

(3)要求對被測程序的組件結構有充分了解(可以通過RFT測試地圖了解)

(4)開發采用spring管理測試對象地圖的腳本比開發有RFT管理的測試對象地圖時間要長的多,但是帶來的好處也是明顯的。

(5)測試對象執行動作的速度也沒有RFT管理的測試對象地圖快。

base-test-object-map.xml 代碼

xml 代碼

<!--sp-->xml version="1.0" encoding="gb2312"?>
<!--CTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" </sp-->
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

<!--注冊com.rational.test.ft.script.Property屬性編輯器-->
<bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.rational.test.ft.script.Property">
<bean class="pkg.TestObjectPropertyEditor"/>
entry>
map>
property>
bean>

<!--實例化pkg.BaseTestObjectScript類-->
<bean id="baseTestObjectScript" class="pkg.BaseTestObjectScript"/>

<!--調用baseTestObjectScript中的非靜態方法getBrowserTestObject產生一個BrowserTestObject測試對象-->
<bean id="browserTestObject"
factory-bean="baseTestObjectScript"
factory-method="getBrowserTestObject"
singleton="false"/>
<!--調用baseTestObjectScript中的非靜態方法getDocumentTestObject產生一個DocumentTestObject測試對象-->
<bean id="documentTestObject"
factory-bean="baseTestObjectScript"
factory-method="getDocumentTestObject"
singleton="false"/>

beans>

base-test-object-map.xml 可以作為公有的測試對象地圖,其中customEditorConfigurer向容器注冊了一個屬性編輯,pkg.BaseTestObjectScript是一個RFT腳本,此腳本有getBrowserTestObject()和documentTestObject(),可以在這個類中放入基本的測試對象,通過Spring將這些對象封裝為bean, 然后有其他的spring配置文件來import,這樣就實現了對象的繼承。pkg.BaseTestObjectScript的代碼如下:

java 代碼

package pkg;

import resources.pkg.BaseTestObjectScriptHelper;

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

public class BaseTestObjectScript extends BaseTestObjectScriptHelper
{
public void testMain(Object[] args)
{
}

public BrowserTestObject getBrowserTestObject()
{
return browser_htmlBrowser(document_H(),DEFAULT_FLAGS);
}

public GuiTestObject getDocumentTestObject()
{
return document_H();
}
}

pkg.TestObjectPropertyEditor代碼如下,其中如果用精確匹配就用=作為分隔符,如果是通過正則表達式匹配就通過:作為分隔符,然后在程序內部就會做正則表達式的轉換。

java 代碼

package pkg;

import com.rational.test.ft.script.Property;
import java.beans.PropertyEditorSupport;
import java.util.StringTokenizer;
import com.rational.test.ft.value.RegularExpression;

public class TestObjectPropertyEditor extends PropertyEditorSupport
{
public void setAsText(String text)
{
String delimiter = null;
Object propValue = null;

if(text == null || text.length() < 1 || (text.indexOf(EQUAL_MARK) == -1 && text.indexOf(COLON) == -1))
{
throw new IllegalArgumentException("識別屬性為空或格式不正確 =表示進行精確匹配 :表示使用正則表達式匹配");
}

if(text.indexOf(EQUAL_MARK) != -1)
{
delimiter = EQUAL_MARK;
}
else if(text.indexOf(COLON) != -1)
{
delimiter = COLON;
}

//解析字符串
StringTokenizer st = new StringTokenizer(text, delimiter);
String name = st.nextToken();
String value = st.nextToken();

propValue = value;

if(text.indexOf(COLON) != -1) //如果分隔符為 : 將propValue設置為正則表達式
{
propValue = new RegularExpression(value, false);
}
setValue(new Property(name, propValue));
}

public String getAsText()
{
Property property = (Property)getValue();
return property.getPropertyName() + "-" + property.getPropertyValue();
}

public final String EQUAL_MARK = "="; //"=" 表示進行精確匹配
public final String COLON = ":"; //":" 表示使用正則表達式匹配
}

然后介紹一下其他的Spring配置文件通過導入另一個Spring配置文件實現,測試對象的繼承。如下,通過import另一個配置文件,這個spring配置文件中的對象就可以使用被導入的spring配置文件中的測試對象,從而可以實現測試對象的繼承。

pkg/logon-map.xml

xml 代碼

<!--sp-->xml version="1.0" encoding="gb2312"?>
<!--CTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" </sp-->
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

<!--從classpath(類路徑)中導入base-test-object-map.xml文件 可以使用base-test-object-map.xml文件中定義的bean-->
<!--導入時候要包含完整的包名-->
<import resource="classpath:pkg/base-test-object-map.xml"/>

<!--實例化pkg.TestObjectHelper類-->
<bean id="loginFormHelper"
class="pkg.TestObjectHelper"
singleton="false">

<!--設置待查找對象的識別屬性 格式:propertyName-propertyValue-->
<property name="objectProperties">
<list>
<!--屬性名稱和屬性精確匹配用=-->
<!--屬性名稱和屬性用正則表達式匹配用:-->
<value>.class=Html.FORMvalue>
<value>.name:.*Formvalue>
list>
property>

<!--設置從什么對象開始查找 注入父測試對象-->
<!--browserTestObject 引用的是base-test-object-map.xml文件中已經定義的bean-->
<property name="parentTestObject">
<ref bean="browserTestObject"/>
property>
bean>

<!--調用loginFormHelper中的getSonTestObject 此方法返回TestObject測試對象-->
<bean id="loginForm"
factory-bean="loginFormHelper"
factory-method="getSonTestObject"
singleton="false">
bean>

<!--動態查找text_userName測試對象-->
<bean id="userNameTextHelper"
class="pkg.TestObjectHelper"
singleton="false">
<property name="objectProperties">
<list>
<value>.class=Html.INPUT.textvalue>
<value>.name=userNamevalue>
list>
property>

<property name="parentTestObject">
<ref bean="loginForm"/>
property>
bean>

<!--動態查找text_password測試對象-->
<bean id="userNameText"
factory-bean="userNameTextHelper"
factory-method="getSonTestObject"
singleton="false">
bean>

<bean id="passwordTextHelper"
class="pkg.TestObjectHelper"
singleton="false">
<property name="objectProperties">
<list>
<value>.class=Html.INPUT.passwordvalue>
<value>.name=passWordvalue>
list>
property>

<property name="parentTestObject">
<ref bean="loginForm"/>
property>
bean>

<bean id="passwordText"
factory-bean="passwordTextHelper"
factory-method="getSonTestObject"
singleton="false">
bean>

<!--動態查找ubmit_button測試對象-->
<bean id="submitButtonHelper"
class="pkg.TestObjectHelper"
singleton="false">
<property name="objectProperties">
<list>
<value>.class=Html.INPUT.submitvalue>
<value>.value=進入value>
list>
property>

<property name="parentTestObject">
<ref bean="loginForm"/>
property>
bean>

<bean id="submitButton"
factory-bean="submitButtonHelper"
factory-method="getSonTestObject"
singleton="false">
bean>

<!--點擊菜單-->
<bean id="menuHelper"
class="pkg.MenuHelper"
singleton="false">

<!--待點擊菜單名稱 必須按照先后順序-->
<property name="menus">
<list>
<value>菜單名稱1value>
<value>菜單名稱2value>
<value>菜單名稱3value>
<value>菜單名稱4value>
list>
property>

<!--注入父測試對象 定義從什么對象開始查找菜單并點擊-->
<property name="parentTestObject">
<ref bean="documentTestObject"/>
property>
bean>

beans>

下面是上面的配置文件中用到的pkg.TestObjectHelper類,這個類暴露出parentTestObject 和 objectProperties兩個屬性用spring來注入,從而確定從什么對象開始查找對象和以什么條件查找對象。通過getSonTestObject() 方法返回找到的測試對象(只允許返回一個對象,如果找到多個就會拋出異常),其中還有個getSonTestObjects()方法是為了返回多個測試對象而準備的。代碼如下:

package pkg;

import com.rational.test.ft.AmbiguousRecognitionException;
import com.rational.test.ft.ObjectNotFoundException;
import com.rational.test.ft.object.interfaces.TestObject;
import com.rational.test.ft.script.Property;
import com.rational.test.ft.script.SubitemFactory;

public class TestObjectHelper
{
public Property[] getObjectProperties()
{
return objectProperties;
}

public void setObjectProperties(Property[] objectProperties)
{
this.objectProperties = objectProperties;
}

public TestObject getParentTestObject()
{
return parentTestObject;
}

public void setParentTestObject(TestObject parentTestObject)
{
this.parentTestObject = parentTestObject;
}

public TestObject getSonTestObject()
{
return findSonTestObject();
}

public void setSonTestObject(TestObject sonTestObject)
{
this.sonTestObject = sonTestObject;
}
作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗