[QTP中RO与TO3]如何访问DOM对象和方法(描述性编程)

来源:互联网 发布:python相对路径import 编辑:程序博客网 时间:2024/06/05 20:47

看到很多人被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对象,这个对象中有一个名叫GooglePage对象,Page对象中有名叫qWebEdit对象,WebEdit对象执行了Submit方法。实际上Browser()这是Browser对象的默认方法,这个方法接收一个对象名参数,返回Browser对象,PageWebEdit也类似。除了用对象名参数化对象方法之外,还可以用其他的属性或者对象参数化。

这段代码涉及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自带了对ActiveXVisual BasicWeb对象的识别规则,其他例如JavaFlash等的需要加载相应插件。

 

 

在回放时,QTP根据测试对象的属性定位实际页面上的对象(Run-time Object, RO),并在RO上执行事件。如果回放时找不到对象,QTP会默认启动智能识别(Smart Identification),智能识别的规则在Object Identification中单独定义。

 

 

 

 

More About录制/回放

 

录制的主要目的在于获取对象,以便回放时能够识别。获取对象的方法有几种方式,录制只是其中一种,也就是录制这一步不是必须的,可以跳过。那还有哪些方式可以获取对象呢?

1.   Object RepositoryAdd Object直接抓取对象,其实也是另一种形式的录制

2.   常说的描述性编程,描述性编程又可以分成两种基本类型:基于QTP Test Object的描述性编程和基于DOM Object的描述性编程。后者需要对对象识别的理解更加深入,这里稍后介绍。而前者就是大家十分熟悉也经常使用的,具体有三种不同的使用方式:

      a)   DescrīptionChildObjects组合

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对象上执行一些特殊的操作,这时我们希望能够有某种手段能够定制对象事件,QTPRegisterUserFunc为我们提供了这种功能。

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 ObjectDom Object之说,这两个到底有什么区别呢?所谓QTP Object包括TORO都是被QTP封装后的对象,而DOM ObjectQTP没有什么关系。我们知道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接口去操作就会灵活的多,DOMHTML结构视为一棵树,每个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的访问。