看到很多人被QTP弄得晕头转向,我深有感触,有一句话突然浮上心头“不识庐山真面目,只缘身在此山中”。当你接触并研究过多个工具之后,会发现道理原来就是这么简单。这里也送迷路者一句话:工具永远只是工具,工具永远是被利用的,你更需要把握问题的本质。
废话不多说了,当年我用的版本是QTP9.0,这里把我对QTP的一些认识重新整理,和各位分享,仁者见仁,智者见着,大家相互学习,共同切磋。有什么不正确的地方,欢迎大家指出。整理的思路我按照从浅入深逐步展开,以便大家理解。例子就以Web应用为例,这个我比较熟悉,但道理是共通的。当然要了解本文,你还是需要具备基本的QTP知识,至少要知道录制、回放、对象库、描述性编程等基本概念。
QTP对象库
例如我们以Google的搜索为例录制脚本,代码如下:
Browser("Google").Page("Google").WebEdit("q").Set "qtp"
Browser("Google").Page("Google").WebEdit("q").Submit
当录制下这段代码之后,QTP做了哪些事情呢?
1.首先最明显的在QTP主窗口的专家视图下多了两行代码(废话-_-!)
2.其次我们打开Object Repository,发现QTP创建了一些对象
QTP自动生成的代码怎么理解?结合Object Repository,可以这样理解,有一个名叫Google的根节点Browser对象,这个对象中有一个名叫Google的Page对象,Page对象中有名叫q的WebEdit对象,WebEdit对象执行了Submit方法。实际上Browser()这是Browser对象的默认方法,这个方法接收一个对象名参数,返回Browser对象,Page和WebEdit也类似。除了用对象名参数化对象方法之外,还可以用其他的属性或者对象参数化。
这段代码涉及3种类型的对象:Browser对象、Page对象、WebEdit对象。怎么知道这些对象的类型,可以在Object Repository窗口的右侧的Class属性就知道了。右侧的有部分属性是不能修改的,有部分属性是可以修改。可修改的属性都有一个默认显示的列表,点击添加按钮可以改变默认值的设置。这个有什么作用呢?默认的属性是QTP用来描述抓取下来的对象的,你可以通过修改它让QTP在执行时根据你的设置灵活的匹配实际的对象。
本文出自asoqa的51Testing软件测试博客:http://www.51testing.com/?233320
QTP怎么去标识一个对象?
在录制时,QTP根据Object Identification中定义的对象属性在录制时识别页面的元素,并映射成QTP的测试对象(Test Object, TO);同时根据Web Event Configuration中定义的规则识别对象事件。默认QTP自带了对ActiveX、Visual Basic、Web对象的识别规则,其他例如Java、Flash等的需要加载相应插件。
在回放时,QTP根据测试对象的属性定位实际页面上的对象(Run-time Object, RO),并在RO上执行事件。如果回放时找不到对象,QTP会默认启动智能识别(Smart Identification),智能识别的规则在Object Identification中单独定义。
More About录制/回放
录制的主要目的在于获取对象,以便回放时能够识别。获取对象的方法有几种方式,录制只是其中一种,也就是录制这一步不是必须的,可以跳过。那还有哪些方式可以获取对象呢?
1. 用Object Repository的Add Object直接抓取对象,其实也是另一种形式的录制
2. 常说的描述性编程,描述性编程又可以分成两种基本类型:基于QTP Test Object的描述性编程和基于DOM Object的描述性编程。后者需要对对象识别的理解更加深入,这里稍后介绍。而前者就是大家十分熟悉也经常使用的,具体有三种不同的使用方式:
a) Descrīption和ChildObjects组合
Set ōDesc = Descrīption.Create()
oDesc("micclass").Value = "WebRadioGroup"
Set ōbjs = Browser("Google").Page("Google").ChildObjects(oDesc)
objs(0).Select "#1"
b) 用Descrīption对象参数化Test Object
Set ōDesc = Descrīption.Create()
oDesc("name").Value = " 手气不错"
Browser("Google").Page("Google").WebTable("高级搜索").WebButton(oDesc).Click
c) 用属性参数化Test Object
Browser("Google").Page("Google").WebTable("高级搜索").WebButton("name:=手气不错").Click
默认的,录制回放时的事件都是QTP封装后的事件。
定制对象事件
大部分情况下,我们使用QTP封装后的事件就可以了。但是在某些情况下,我们需要在QTP对象上执行一些特殊的操作,这时我们希望能够有某种手段能够定制对象事件,QTP的RegisterUserFunc为我们提供了这种功能。
1.注册新方法
Function SetDefaultValue(test_object, ByVal val)
If StrComp(val, "") = 0 Then
test_object.Set "default"
Else
test_object.Set val
End If
End Function
RegisterUserFunc "WebEdit", "SetDefaultValue", "SetDefaultValue", TRUE
Browser("Google").Page("Google").WebEdit("q").SetDefaultValue ""
Browser("Google").Page("Google").WebEdit("q").Submit
上面这段代码在WebEdit对象注册了一个新的方法SetDefaultValue
2. 修改老方法
Function SetDefaultValue(test_object, ByVal val)
If StrComp(val, "") = 0 Then
test_object.Set "default"
Else
test_object.Set val
End If
End Function
RegisterUserFunc "WebEdit", "Set", "SetDefaultValue", TRUE
Browser("Google").Page("Google").WebEdit("q").Set ""
Browser("Google").Page("Google").WebEdit("q").Submit
这段代码定义了SetDefaultValue方法并替换了以前的Set方法。
如何访问DOM对象和方法(描述性编程)
前文提到描述性编程时有QTP Object和Dom Object之说,这两个到底有什么区别呢?所谓QTP Object包括TO和RO都是被QTP封装后的对象,而DOM Object和QTP没有什么关系。我们知道Html是一种结构化的语言,而Html Dom定义了访问和操作HTML文档的标准方法,DOM Object指的通过DOM接口访问的HTML文档对象。那QTP如何获取DOM Object?很简单,只要通过Object属性就可以使用DOM接口访问这些对象。例如下面这段话就是通过DOM接口访问Input对象,并直接将输入框的value值赋值为abc,相当于QTP WebEdit对象的Set方法:
Browser("Google").Page("Google").WebEdit("q").Object.value = "abc"
那什么时候会用到DOM Object?怎么用呢?
用QTP时,大家会发现有不少的对象QTP经常抓取不下来。例如某个Html代码中DIV中套用了DIV:
<div id=”parentDIV” class=”class 1”>
<div id=”childDIV” class=”class2”>
<input id="inputid" class="textfield" type="text" value=””/>
</div>
</div>
大家可以试试,如果用QTP本身的对象抓取功能,如果想把两个DIV层都抓取下来非常困难,如果对象都抓取不了,就更不要提后续的操作了。但如果用DOM接口去操作就会灵活的多,DOM将HTML结构视为一棵树,每个HTML文档元素及其属性是树上一个节点,可以用getElementById直接访问它们,也可以通过childNodes属性一层一层的访问。下面是一段范例代码:
'获取childDIV对象
Set ōbj = Browser("Browser").Object.document.getElementByIdx_x_x("childDIV")
'获取childDIV的子节点
Set co = obj.childNodes
'childDIV的子节点为input对象
Set inputObj = co(0)
'设置input文本框的内容为aa
co(0).value = "aa"
当然这些通过QTP Object的描述性编程也是可以做到的。关于Html Dom的详细介绍可以到这个网址看看:http://www.w3school.com.cn/htmldom/index.asp
More About 描述性编程
Object属性通过DOM提供了一种直接访问Web元素属性的途径。除此之外QTP还支持一种直接访问Web元素属性的方式,就是attribute/[属性]的方式。
例如有一段源代码如下:
<A href="http://www.google.cn" lid="l1" id="link1">link1</A>
<A href="http://www.baidu.com" lid="l2" id="link2">link2</A>
QTP脚本可以这样写
'点击link1的链接
Browser("Browser").Page("Page").Link("attribute/lid:=l1").Click的方式点击link1的链接。
'打印link1的lid的属性值
Msgbox Browser("Browser").Page("Page").GetRoProperty("attribute/lid:=l1")
好,现在我们知道了一种更加灵活的方式操作Web对象。但毕竟很多HTML元素页面上是看不出效果的,那我们怎么知道Web对象的结构,以便获取他们并进行操作呢?最土的办法就是查看源代码,但是源代码往往夹杂着大量的动态代码和注释,看起来挺累。这时可以借助一些工具。这里我推荐ie developer toolbar,这个是微软出的ie插件,可以查看每个html文档元素的结构及属性,包括css样式,操作简洁,功能完全可以弥补QTP对象识别的不足。如下图:
不过有点遗憾的是,QTP对于Object属性有这样一个说明“TheObjectproperty for Web objects is supported only when running steps on Internet Explorer. It is not supported when working with Netscape Browser or Mozilla Firefox”,看来QTP只支持IE对于DOM Object的访问。