RFT 描述性编程Word文档格式.docx
- 文档编号:18345221
- 上传时间:2022-12-15
- 格式:DOCX
- 页数:17
- 大小:254.43KB
RFT 描述性编程Word文档格式.docx
《RFT 描述性编程Word文档格式.docx》由会员分享,可在线阅读,更多相关《RFT 描述性编程Word文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
browser.getWebEdit("
.name:
=username"
"
.class:
=Html.INPUT.text"
).setText("
或者
实现的步骤为:
2.1定位浏览器对象
RFT有一个特性,新打开的最后一个浏览器,通过getDomains()查找时,一定是最先找到的。
通过getDomains()获得Html进程后,通过getTopObjects()方法,就可以获得浏览器对象。
publicstaticTopLevelTestObjectgetLastBrowser(StringtoType){
RationalTestScript.sleep(0.5);
DomainTestObjectdomains[]=RationalTestScript.getDomains();
StringdomainName;
TestObject[]topObjects;
Hashtableht;
StringsClass;
booleanvisible=false;
for(inti=0;
i<
domains.length;
i++){
try{
domainName=domains[i].getName().toString();
if(domainName.equalsIgnoreCase("
Html"
)){
topObjects=domains[i].getTopObjects();
if(topObjects!
=null){
for(intj=0;
j<
topObjects.length;
j++){
ht=topObjects[j].getProperties();
sClass=ht.get("
.class"
).toString();
if(toType.equalsIgnoreCase(sClass)&
&
sClass.equalsIgnoreCase("
Html.Dialog"
if(ht!
=null){
visible=(boolean)ht.get("
.visible"
if(visible){
return(TopLevelTestObject)topObjects[j];
}
}
}elseif(toType.equalsIgnoreCase(sClass)&
Html.HtmlBrowser"
return(BrowserTestObject)topObjects[j];
}
}
}
}
}catch(Exceptione){
//logger.error("
Exception:
"
e);
//noop-continueiftargethassincedisappeared
}
}
logger.error("
foundnovalid:
+toType);
returnnull;
}
如果查找不到浏览器对象,可以检查:
1浏览器是否打开。
2浏览器的add-on中,RFT的插件是否正确加载。
3如果安装的是jre1.7,win764位操作系统下,可能会出现不能识别浏览器的情况,可以尝试卸载jre1.7。
4win7下,通过runasadministrator来运行RFT,否则可能会出现脚本不能正确执行的情况。
2.2封装Web对象
下图是RFT的web对象继承关系图。
通过动态查找的方式来识别web对象时,都是从browser对象开始定位的,即BrowerTestObject.
为了便于操作,将页面上的对象封装成基类WebElement,所有的页面对象都继承自WebElement,实际就是对应于GuiTestObject.
类名
名称
主要识别属性
典型操作
典型对象
WebElement
所有的页面对象
.class
.id,.name
click
Html.DIV,Html.TR,Html.LI
WebButton
按钮
.id,.value
Html.INPUT.button
Html.BUTTON
WebEdit
输入框
setText
getText
Html.INPUT.text
Html.INPUT.password
Html.TEXTAREA
WebImage
图片
.id,.name,.title,.src
Html.INPUT.image
Html.IMG
WebLink
链接
.id,.text
Html.A
WebCheckBox
复选框
check
uncheck
isChecked
Html.INPUT.check
WebRadioButton
单选按钮
select
isSelected
Html.INPUT.radio
WebList
下拉框
多选框
Html.SELECT
WebTable
表格
getRowCount
getColumnCount
getCell
...
Html.TABLE
WinButton
弹出框按钮
.text
Html.DialogButton
WinStatic
弹出框文本信息
(index)
Html.DialogStatic
publicclassWebElement{
GuiTestObjectwebElement=null;
publicWebElement(TestObjectto){
if(to==null){
webElement=null;
}else{
if(toinstanceofGuiTestObject){
webElement=(GuiTestObject)to;
}else{
logger.error("
TestObjectclassisnotGuiTestObject:
"
+to.getObjectClassName());
webElement=null;
}
}
publicclassWebEditextendsWebElement{
publicWebEdit(TestObjectto){
super(to);
publicvoidsetText(Strings){
this.click();
//activatetextfield
this.clearText();
this.inputChars(s);
webElement.unregister();
2.3根据描述属性查找对象
识别一个Web对象,可能需要使用1个或者多个属性。
查找对象时,通过getChildren()方法来逐层查找,匹配这些属性,当属性值完全符合时,则认为已经找到。
1动态个数的输入参数,可以使用String...args来解决。
描述属性的key和value值通过:
=来分割。
如:
browser.getWebEdit("
)
2将默认的.class属性写入,减少手工输入代码的工作量
publicWebEditgetWebEdit(String...properties){
HashMap<
String,String>
descMap=WebUtil.getDescMap(properties);
if(descMap!
if(!
descMap.containsKey("
)){
descMap.put("
}
WebElementtestObj=getWebElement(descMap);
if(testObj==null){
returnnewWebEdit(null);
logger.debug("
foundtheobj"
return(WebEdit)testObj;
2先将字符串数组properties解析出属性的键值对,存放到HashMap中
`/**
*将"
=Html.A"
.text:
=链接"
的字符串描述转换成HashMap
*@paramproperties
*@return
*/
publicstaticHashMap<
getDescMap(String[]properties){
descMap=newHashMap<
();
String[]tempAttrbute;
for(Stringproperty:
properties){
tempAttrbute=property.split("
:
="
if(tempAttrbute.length==2){
descMap.put(tempAttrbute[0],tempAttrbute[1]);
}else{
Error:
descriptionstringisinvalid:
+property);
returnnull;
returndescMap;
3按照属性在页面上查找对象
查找对象的方法,使用递归查找child的方法,其好处是,可靠性较好,只要页面上存在指定的对象,则必定可以查找到。
缺点就是查找速度慢,无论是按照深度优先,还是按照广度优先查找,因为必须将前序节点的属性都逐一进行检查。
不过这个问题可以通过后续的缓存路径的方式来解决。
publicstaticTestObjectgetChildObjects(HashMap<
String,String>
descMap,TestObjectparent){
TestobjecttestObj=null;
if(isMatchObject(parent,descMap)){
returnparent;
TestObject[]childObjs=parent.getChildren();
//循环查找直接子对象
childObjs.length;
testObj=getChildObjects(descMap,childObjs[i);
returntestObj;
4属性匹配。
优先匹配.class属性
publicstaticbooleanisMatchObject(TestObjecttestObj,HashMap<
descMap){
StringactualClass=null;
StringexpectVal;
StringactualVal;
HashtableproTable=testObj.getProperties();
if(descMap.containsKey("
)){//优先匹配.class属性
actualClass=proTable.get("
actualClass.equalsIgnoreCase(descMap.get("
))){
returnfalse;
}
booleanisMatch=true;
for(Stringproperty:
descMap.keySet()){
property.equalsIgnoreCase("
)){//逐个遍历剩下的属性
expectVal=descMap.get(property).trim();
if(proTable.containsKey(property)){
actualVal=proTable.get(property).toString().trim();
isMatch=expectVal.equalsIgnoreCase(actualVal);
}else{
isMatch=false;
}
if(!
isMatch){
break;
returnisMatch;
5增加index的识别属性。
通过描述的属性,可能会查找到多个符合属性的元素,可以增加index的属性,默认查找第一个,如果指定了index的值,则按照index的值返回对应的元素。
3缓存节点路径
通过深度优先或广度优先的顺序来查找页面节点,速度必然会慢。
为了加快速度,可以将第一次查找到节点的路径保存起来,第二次查找时,则根据之前保存的路径直接比对,以此提高二次查找的效率。
对每一层的节点按照顺序进行编号,每一层的起始编号均为0。
如上图,username的输入框的路径为0-1-0-0-0,密码的输入框的路径为0-1-0-0-1。
节点路径会保存在缓存文件(key-value的txt文件)中,key和value之间用两个#号分割,key为Web对象的描述属性按照指定顺序连接起来的字符串,value为节点的数字路径。
=Html.INPUT.text,.name:
=userId##0_3_0_1_0_4_3_0_0_0_0_0_3_0
=Html.INPUT.password,.id:
=oldPassword##0_3_0_1_0_4_3_0_0_0_1_0_3_0
由于同一个缓存文件中,并不能区分web对象所在的页面,所以,如果两个不同的页面上,都存在同样属性的web对象,如"
确定"
按钮,就会出现互相覆盖,导致缓存错误的情况。
另外在有些业务系统中,每个用户的权限不同,或者业务流程不同,同一个对象在同一个页面上的路径也会不同,如菜单,每个用户登录后的菜单顺序都会不同。
因此就需要采取以下措施来避免:
1将这两个对象保存到两个不同的缓存文件中。
2增加额外的描述属性来区别这两个对象。
如增加descName,extName这两个属性,它们不参与对象的属性匹配,但是会保存成不同的key值,形成两条不同的记录。
查找对象时的逻辑为:
1根据对象描述属性,生成唯一的缓存key值
2检查缓存文件,缓存文件中是否存在该key值。
2.1如果存在该key值,取出value--节点的路径
2.1.1在页面上,直接根据路径,找到对应的节点
2.1.2检查找到的节点是否符合描述的属性,
2.1.2.1如果符合描述的属性,则返回该对象。
2.1.2.2如果不符合描述的属性,根据缓存路径查找对象失败,跳转到根据属性查找对象流程
2.2如果不存在该key值,则根据缓存路径查找对象失败,跳转到根据属性查找流程
3根据描述属性,逐级在页面上查找该对象
4如果查找到符合属性的对象,将该节点的路径保存到缓存文件中,然后返回该对象进行后续操作
5如果未查找到符合属性的对象,提示错误。
通过缓存来查找web对象,大约0.5秒就能查找到正确的对象,足够满足自动化测试的需要。
publicstaticWebElementgetChildByCachePath(TestObjecttestObj,HashMap<
descMap,StringcachePath){
if(cachePath!
=null&
cachePath.length()>
0){
String[]cacheStep=cachePath.split("
_"
intseq=0;
for(inti=1;
i<
cacheStep.length;
i++){
seq=Integer.parseInt(cacheStep[i]);
TestObject[]tos=testObj.getChildren();
if(tos.length>
seq){
testObj=tos[seq];
logger.warn("
notfoundobjectbycachepath:
level="
+i+"
childcnt="
+tos.length+"
butexpectsequence="
+seq);
foundone"
try{
if(isMatchObject(testObj,descMap,cachePath)){
returnsubTypeWebElement(testObj);
foundobjectbycachepath,butnotmatch:
+descMap.toString()+"
\t"
+cachePath);
}catch(Exceptione){
logger.error("
foundobjectbycachepath,butexcption"
returnnull;
}
logger.debug("
nocachepathfor:
+descMap.toString());
returnnull;
4根据页面信息来描述对象
一个普通的文本输入框:
username:
|___________|
这个文本框的html结构可能有这样几种形式:
<
tr>
td>
uesername:
/td>
<
inputtype=textid=username>
div>
username:
/div>
现有的识别方式,都要通过查看这个输入框的id,name属性来识别。
对于这样一个输入框,人肉眼是如何来识别这个输入框的呢?
必定是根据输入框前的文本信息"
,而不是该输入框的id,name属性。
4.1通过左边文字来描述对象
那么在程序中如何来通过左边的文字来识别一个文本框呢?
browser.getWebEdit(
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- RFT 描述性编程 描述 编程