技术开发 频道

扼杀QTP检查点完结篇--节点的故事

  【IT168 技术文档】

  前言

  有一天,一家学校的校长在典礼上叫了Tom 的名字,这时候有8 位学生都

  站了出来。校长事先已经记住了排队顺序中第3 个班的Tom 就是他要叫的。但

  由于今天班级顺序都打乱了,校长看了,只能再次叫道,父亲是Jack,出列。幸

  运的是,这个时候学生只有2 位。校长再加了个条件,爷爷叫William,父亲是Jack

  的出列.最后,就只剩下一个学生出列。

  在做Web 的QTP 自动化测试时候,不免会出现这样几种情况:

  ?? QTP 中相同属性的对象,通过添加Index 去区别;

  ?? 页面元素动态变化,难以通过Index 去识别;

  ?? 想根据文本提示不同,对相同类型元素做操作,却无从下手;

  而我们透过上面的故事可以知道,原来我们可以透过节点去解决这些问题,

  但要怎么做呢?

  一、简单了解Html节点

  大部分做过Web 测试的测试员们都会偶尔好奇的看看程序的Html 代码,也

  可能了解了Html 节点,节点的特点就和树一样,能够让你更轻松的遍历出你需

  要的元素。例如:

<屋子屋主=小卢>
<书架名字=A >
<书本名字= Java Cook Book >
<书本名字= QTP >
</书架>
<书架名字=B >
<书本名字= Java Cook Book >
<笔记名字=QTP 学习笔记>
</书架>
</屋子>

  在这里面,屋子、书架、书本是节点,而我们就是通过这些节点去遍历得

  到我们想要的东西。通过上面的例子,我们也同样看到,使用不同的名字的书架,

  尽管有2 本叫Java Cook Book 的书,但都可以准确的得到我们想要的。

  二、辅助工具

  QTP 中的Object Spy 功能,是在使用QTP 过程中比较长用到的功能,但是,

  QTP 对某些表格标记节点、部分排版标记等不能很准确的抓取出来,也就无法

  透过SPY 功能看到Html 的节点上下层关系,也不能让我们更好的了解节点与节

  点之间的联系从而做好编写脚本的工作。

  在这里推荐使用的一个工具是微软的IEDevToolBar

  1、下载安装:

  http://www.microsoft.com/downloads/details.aspx?FamilyID=e59c3964-672d-

  4511-bb3e-2d5e1db91038&DisplayLang=en

  安装之后,在IE 顶部菜单的“查看”——“工具栏” 里面钩选“Developer

  Toolbar”项即可。重启IE 后,可以在界面上看到一个这样的小图标, 点它。

  打开它,如图:

 
     2、功能简介:

  一般我们主要使用的几个功能:

  1)Find??Select Element By Click

  简单的获取页面元素,方便在树中查看。提示:在点击页面元素前,先随便

  选中节点树上面的一个节点,使得在做点击获取元素操作时候,能够展其开所在

  位置。

  2)Outline??Table Cells 、Outline??Tables 、Outline??DIV Elements

  用不同颜色标出所有的Table Cells、Tables、DIV

  Outline??Any Elements

  3)通过用户自己输入节点名,并选择颜色后,确定。在界面上会标示出所

  有同类型节点的元素。
 

【注】 51Testing授权IT168独家转载,未经明确的书面许可,任何人或单位不得对本文内容复制、转载或进行镜像,否则将追究法律责任。 本文出自51Testing电子杂志《51测试天地》第十四期,http://www.51testing.com/html/82/n-141082.html

  三、Dom 的节点属性

  在对节点操作的时候,我们除了借助辅助工具去获取上下层节点的同时,但

  有时候可能因为节点的属性不确定,让我们不能直接获取节点。因此我们会借助

  一些比较常用的节点属性来获取。

  (一)DOM 节点属性

  1、nodeName 属性返回一个字符串,其内容是给定节点的名字:

  例子:Browser(“browser”).page(“page”).Link(“link”).object. parentNode.Noden

  ame

  2、nodeType 属性返回一个整数,这个数值代表着给定节点的类型:

  例子:Browser(“browser”).page(“page”).Link(“link”).object. parentNode. nodeT

  ype

  3、nodeValue 属性将返回给定节点的当前值:

  例子:Browser(“browser”).page(“page”).Link(“link”).object. parentNode. nodeV

  alue

  (二)遍历节点树

  1、childNodes 属性将返回一个数组,这个数组由给定元素节点的子节点构

  成:

  例子:Browser(“browser”).page(“page”).Link(“link”).object. childNodes

  2、firstChild 属性将返回一个给定元素节点的第一个子节点:

  例子:Browser(“browser”).page(“page”).Link(“link”).object.firstChild

  3、lastChild 属性将返回一个给定元素节点的最后一个子节点:

  例子:Browser(“browser”).page(“page”).Link(“link”).object.lastChild

  4、nextSibling 属性将返回一个给定节点的下一个子节点

  例子:Browser(“browser”).page(“page”).Link(“link”).object.nextSibling

  5、parentNode 属性将返回一个给定节点的父节点:

  例子:Browser(“browser”).page(“page”).Link(“link”).parentNode

  四、实战节点

  1、QTP 相同属性的对象,如何不通过添加Index 去区别?

  首先看看下面的Html 代码片,如果读者有兴趣,可以自己建一个Html 文

  件,命名为

  Test.html,接着把代码片复制下去并保存。

<DIV id=div1>
<a href=http://www.51testing.com>测试</a>
</DIV>
<DIV id=div2>
<a href=http://www.baidu.com>测试</a>
</DIV>

  使用QTP 我们把2 个“测试”的Link 都添加进对象库后,我们会发现对象

  库会分别给他们都添加一个index 属性。但是我们透过了IEDevToolBar 可以看

  到如下图片的树:

  可以看到原来每个连接分别包含在DIV 节点下面,所以要点击第二个连接

  时候,可以这么写:

  browser("Browser").Page("Page").webelement("html id:=div2").link("index:=0").

  click

  在这里,先通过ID 获取了DIV 的这个对象,然后点击它下面的第一个Link。

  这个方法的优点在于我们不是直接的在Page 上寻找Link,而是更为仔细的透过

  它的父节点来找到它。有些时候对象添加进对象库,由于识别机制问题,若干个

  对象都被添加为同一个对象,导致了无法操作,这时候,我们如法炮制的使用这

  个方法,哪么问题也就迎刃而解。

  那么,我们使用这种方法就只能做这点事情吗?你可以带着这个问题继续往

  下看。

  2、页面元素动态变化,难以通过Index 去识别?

  在做自动化项目中,由于用户的权限的不同,菜单、页面显示的效果也不一

  样,那么我

  们录制的脚本完全就排不上场,好比下面的2 个图片:

  首先,我在这里需要解决2 个问题:

  第一个是因为用户权限、其他因素导致了页面元素动态变化,同一个“打开”

  对象在不同情况下功能不一致。

  第二个是页面需要被操作的元素属性基本一致。

  这个效果很像我们有时候在项目中遇见的菜单的展开和收缩。我们需要以不

  变应万变。(连接也可以换成图片“+”、“-”等。)

  大家同样有兴趣可以建一个Html 文件,并保存下面代码:

<table id=table2>
<tr><td>
<a href=http://www.google.com>打开</a></td>
<td><table >
<td><div>谷歌</div></td>
</table></td></tr>
</table>
<table id=table1>
<tr><td>
<a href=http://www.51testing.com>打开</a></td>
<td><table >
<td><div>51Testing</div></td>
</table></td></tr>
</table>

  保存完毕后,我们打开了IEDevToolBar,可以瞧到下面的树形结构:

  我们这里就做个点击“谷歌”字样前面的“打开”实例:

Public function open(opentext)
Dim guge
If browser("Browser").Page("Page").WebElement("html tag:=DIV","innertext:="
&opent
ext,"index:=0").Exist then ‘首先判断有这个字样的对象是否存在
set guge=browser("Browser").Page("Page").WebElement("html tag:=DIV","innertext:=
谷歌","index:=0") ‘把对象赋值给guge
newid=guge.object.parentNode.parentNode.parentNode.parentNode.parentNode.parentN
ode.parentNode.parentNode.id ‘透过上面图片可以看到第8 个节点是有id 这个值的,
这也是非常有价值的一个节点,所以我们只能通过它来做下步操作。所以这步的操作,
可以记成一个简单的口诀,寻有价值节点。
browser("Browser").Page("Page").WebElement("html
id:="
&newid).link("index:=0").click ‘和第一个例子的点击连接一样
end if
End Function
open("谷歌")

  实现了上面的点击打开操作后,在实战1 中的问题也就没有了(什么?你忘

  记第一个问题是什么,也难怪,读得入神了)。

  而在这个例子中,可能你会提出一个小小问题,是否它就真的能适用整个项

  目呢?其实像这种动态的Web,由于它会根据用户或者其他因素发生页面变动,

  所以它代码生成都是有自己的规则,也就是节点顺序一般都套用到其他地方,不

  会发生变化。

  3、除了类似菜单选择实例,我们还能做什么?

  在项目里面,某些页面可输入框可谓是多不胜数,所以我们都只填写了必填

  的,而非必填的在测试用例中也很少体现出来,那么这部分是否也会成为漏网之

  鱼而今后成为一个祸根呢?如果你已经懂得如何应用节点去解决类似菜单的问

  题,同样的它也适用在这里。

  看看下面图片:

  代码片:

<table id=table1>
<tr><td>
<div>姓名:</div></td>
<td><table >
<td><input type="Text"></td>
</table></td></tr>
</table>
<table id=table2>
<tr><td>
<div>地址:</div></td>
<td><table >
<td><input type="Text"></td>
</table></td></tr>
</table>
<table id=table3>
<tr><td>
<div>邮件:</div></td>
<td><table >
<td><input type="Text"></td>
</table></td></tr>
</table>
<table id=table4>
<tr><td>
<div>电话号码:</div></td>
<td><table >
<td><input type="Text"></td>
</table></td></tr>
</table>


那么需要做的事情分几步:
?? 先获页面上所有的输入框。不一定是input 节点,大家根据实际情况而定。

Dim des
Dim AllInput
Set des=description.Create()
des("html tag").value="Input"
set AllInput= browser("Browser").Page("Page").ChildObjects(des)


?? 遍历每个Input 并且获取Div 节点的值。

For i=0 to AllInput.count-1
newid=AllInput(i).object.parentNode.parentNode.parentNode.parentNode.parentNod
e.parentNode.parentNode.parentNode.id
text=browser("Browser").Page("Page").webelement("html
id:="
&newid).webelement("html tag:=Div","index:=0").getroproperty("innertext")
next

使用正值表达式归类出Text 的属于什么类型。(代码略)
我们在datatable 里面新建2 个列,一个命名为reg,一个是Value

Reg Value
姓名|name|名|公司小卢
maile|邮件51testing@51testing.com
地址|address 上海
电话|phone|传真000-1234567


除了上面提到的正规输入我们的value,我们还可以对它做许多其他的测
试操作,例如是否只支持数字输入、文字输入、特殊符号等等。
而我们会遍历所有的正值表达式,也就是Reg 列,等到确认了是那列时候,
再取出相应的Value,填入对应的Input。
使用这样的操作方法能够很快速的填入我们的事先确定好的“信息”,并且
给人感觉很智能。

结束语
让测试脚本更加灵活,更加智能,发挥自己的想象力去做好自动化测试,相
信你的明天会更好!

0
相关文章