RFT与Spring结合进行自动化脚本开发
目前,大部分自动化脚本开发者利用RFT的测试对象地图管理测试脚本的测试对象,RFT的测试对象地图有两种类型:公有测试对象地图和私有测试对象地图。
(1)目前,大部分脚本采用的都是私有测试对象地图,如果被测试的程序顶层对象发生变化,这样每个脚本关联的测试对象地图都要进行修改,之所以这样,有一个原因:在RFT中测试对象地图不能够继承(仅仅可以合并),如果两个测试对象地图之间可以进行继承,这样把公用的测试对象放在父测试对象地图中,其他的测试对象地图继承这个公用的测试对象地图(同时继承公有的测试对象),如果被测试程序顶层框架发生变化,仅仅只修改父测试对象地图就可以了,但是目前RFT中不能实现(据我了解)。
(2)RFT中还有一种类型的测试对象地图是公有的测试对象地图,公有的测试对象地图可以实现公用的测试对象重复使用,如果测试对象是一模一样的,RFT在公有的测试对象地图中只保留此测试对象的一个实例,但是把多个测试对象都插入到一个测试对象地图中,同样又面临着难以管理的困难。
(3)另外,RFT中的测试对象地图与脚本紧紧的耦合,如果程序即使发生很小的变动,也要更新测试对象地图,修改脚本等等。
(4)spring具有强大的功能:Ioc,可以实现在xml中把一个测试对象注入到另一个测试对象中,再加上可以利用RFT的find方法可以把spring的配置文件配置成一张RFT测试对象地图。另外,一个spring配置文件可以被另一个spring文件import进来。这样可以把公有的测试对象放在一个spring配置文件中,然后有其他的spring配置文件进行导入,可以实现测试对象地图(spring的配置文件)的继承。另外,在spring的配置文件中,可以注入一个对象的属性,这样可以人工的更改这个测试对象的父框架,另外可以可以注入测试对象的识别属性,这样可以进行人为的进行测试对象识别属性的更改(这样可以更好的应对被测试程序的变化)。
例如:
- <import resource="classpath:pkg/base-test-object-map.xml"/>
- <property name="objectProperties">
- <list>
- <value>.class=Html.FORMvalue> 然后是怎么使用spring配置文件中的测试对象
- <value>.name:.*Formvalue>
- list>
- property>
- <property name="parentTestObject">
- <ref bean="browserTestObject"/>
- property>
在脚本中引用测试对象通过如下语句:
- 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管理的测试对象地图快。
- xml version="1.0" encoding="gb2312"?>
- "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <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>
- <bean id="baseTestObjectScript" class="pkg.BaseTestObjectScript"/>
- <bean id="browserTestObject"
- factory-bean="baseTestObjectScript"
- factory-method="getBrowserTestObject"
- singleton="false"/>
- <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的代码如下:
- 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代码如下,其中如果用精确匹配就用=作为分隔符,如果是通过正则表达式匹配就通过:作为分隔符,然后在程序内部就会做正则表达式的转换。
- 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配置文件中的测试对象,从而可以实现测试对象的继承。
- xml version="1.0" encoding="gb2312"?>
- "http://www.springframework.org/dtd/spring-beans.dtd">
- <beans>
- <import resource="classpath:pkg/base-test-object-map.xml"/>
- <bean id="loginFormHelper"
- class="pkg.TestObjectHelper"
- singleton="false">
- <property name="objectProperties">
- <list>
- <value>.class=Html.FORMvalue>
- <value>.name:.*Formvalue>
- list>
- property>
- <property name="parentTestObject">
- <ref bean="browserTestObject"/>
- property>
- bean>
- <bean id="loginForm"
- factory-bean="loginFormHelper"
- factory-method="getSonTestObject"
- singleton="false">
- bean>
- <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>
- <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>
- <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()方法是为了返回多个测试对象而准备的。代码如下: