本节书摘来自异步社区《精通QTP——自动化测试技术领航》一书中的第1章1.6节对象库(下)之进阶编程篇,作者余杰 , 赵旭斌,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.6 对象库(下)之进阶编程篇
精通QTP——自动化测试技术领航
阶段要点

掌握手写代码的3种方式。

明确测试对象(TO)与运行时对象(RO)的区别。

4种操作对象封装属性的方法。

你也可以是一名魔术师、黑客。

几种常见的QTP无法识别或识别错误的原因。

1.6.1 引言
在对象库上篇这个章节中,相信读者已经对对象库的使用以及其他各个方面有了一个全面的了解。那么从现在开始,作者将引领读者开始基于对象库编程的学习,从而掌握对象库编程的知识与技巧。读者如果觉得在对象库上篇中还有不能够完全掌握的地方,建议重新学习直到完全掌握为止,因为只有打好了上篇所介绍的基础,才能学习好下篇的知识,真正做到融会贯通。

在前面的章节“1.4 认真并请远离QTP的脚本录制模式”中,作者也已经提到过在QTP自动化测试中绝对不只是单纯的录制与回放,因为只要稍微复杂点的业务,录制模式就不能满足我们的需求了。那么,要想完成自动化测试业务流,就必须依仗QTP的编程模式,举个例子,就比如多个脚本间的数据中转,如果没掌握QTP的编程知识,那一定就没有办法实现。在1.4章节中,作者已经展示过了QTP的代码片段,但并没有深入去介绍到底如何去手写代码,因为这些内容都是本章节的重点。接下来就要开始逐步地详细介绍QTP的第一种编程模式“对象库编程”了,这种编程模式同样也是作者最推崇的一种模式,因为它是QTP的一个特色和亮点。本章节也可以说是到目前为止最难学习的一个章节,包含的内容也很多,包括对象库的编程技巧、编程知识、编程原理等。不过,作者相信在学习完本章节以后,读者的QTP水平一定会有一个明显的飞跃。当然,条件是读者必须深入掌握本章节的所有内容,并能够举一反三。如果对象库编程没有学好,那将会成为读者今后应用QTP自动化测试技术的绊脚石。

1.6.2 基于Expert View的对象库编程必备知识
1.6.2.1 手写代码的3种方式
在QTP的对象库编程中,存在着3种编写代码的方式,依次分别是:步骤生成器、Complete Word、对象拖动生成。接下来,作者就依次介绍这些手工生成代码的方式。

第一种:步骤生成器方式。

先要介绍的是步骤生成器方式,这种方式可以说是QTP的一个“元老”,在QTP一出现就具备了。严格来说,它应该算是QTP的一种功能,接下来就让我们一起动手完成一系列的实例,从而掌握这种编程方式。

既然是一种功能,那么就首先来看一下它所处的地理位置,以及如何去访问到这个功能。

依次选择QTP上方菜单栏→Insert→Step Generator。
操作快捷键F7。
现在随意使用一种手段去使用它,并来认识它,如图1-131所示。

如图1-131所示,可以看到这就是步骤生成器的一个界面。在Category中有3个下拉选项(在图中已经展示出来了),这3个选项就分别代表了步骤生成器可以生成的3种不同类别的代码。

在QTP的Expert View编程中,一行代码就是一个步骤,所以,生成了一行代码也就等于生成了一个步骤。

接下来就逐一生成不同类别的步骤,QTP的“F7”一共可以生成3个类别的代码,所以在这里就划分成3个实例进行操作演示并同步讲解。

实例1:Test Objects。

预备工作:添加一些对象进对象库,事先已经添加好了,如图1-132所示。

如图1-132所示,我们看到对象库里存在一些对象了,那么,接下来需要完成这样一个任务,就是生成一句点击“百度一下”按钮的代码。

Step 1,选中Test Objects下拉选项,选择完毕后,如图1-133所示。


如图1-133所示,我们可以看到,在选中Test Objects这个分类以后,它下面的那个Object下拉框默认显示了一个对象,这个对象就是对象库中的那个父对象。然后再来看Object下拉框的下面,它是一个Operation下拉框,顾名思义就是,这个下拉框可以选择各种不同的操作,不过需要注意的是,Operation下拉框中的可选操作都是基于当前所选择的对象,当前所选对象不支持的操作是选择不到的。我们可以看到,当前默认选择的是Sync操作,这个不用去管它,是系统默认的,不用去深究。接着在下面有一个Arguments的区域,在这里会显示所选操作的一些参数,当前在图1-133中这块区域没有任何东西,是因为Sync这个操作方法没有参数可设置。再接着下面是一个Return value的勾选框,如果当前的对象操作可以有返回值的话,就可以勾选了,并且还能在后面的文本框中输入返回值的名称。最下面就是一个步骤生成预览的区域,这个就不多解释了。如果生成一个步骤以后,还要继续生成其他后续步骤,则勾选上Insert another step,这样在点击了OK按钮以后,“F7”窗口就不会关闭了,可以继续生成下一个步骤代码。好了,也借此机会把这个界面上的一些功能大致介绍了一下,让读者有个了解,在接下来的操作中就不再重复介绍了。

那么继续回到主题,显然现在默认所选的对象不是我们需要的,需要的是生成一句对“百度一下”进行操作的代码,那么此时该怎么办呢?让我们来看下一步。

Step 2,点击Object下拉框右边的“方块+箭头”按钮(在图1-133中),在点击以后会出现一个Select Object for Step的界面,如图1-134所示。

如图1-134所示,可以看到在Select Object for Step这个界面中可以进行对象的选择,除此以外,还包括了一些其他的功能,比如对象查找、从程序指定对象等,这些功能不是重点,就不多做介绍了。那么,我们就选择“百度一下”对象,然后点击OK按钮,点击后如图1-135所示。


如图1-135所示,现在可以看到Object下拉框中已经变成了“百度一下”这个Button对象,并且Operation下拉框也随之变成了Button对象下的一些操作方法,默认是Click(恰好是需要的操作方法)。

Step 3,进行后续设置。这一步就很简单了,我们就拿“百度一下”这个Button控件为例,可以从图1-135中看到Button控件的Click方法有3个参数,其中参数x和参数y是可以设一个值的(如果需要的话),参数BUTTON由于不能设置具体的值,所以QTP显示了。那么接下来就试着设置一下参数x和参数y吧,在设置之前大家请注意步骤生成预览区域的代码,目前是:“Browser("百度一下,你就知道").Page("百度一下,你就知道"). WebButton("百度一下").Click”,等设置了参数以后再来看看步骤生成代码区域。

Step 4,设置x = 97、y = 120。分别点击x与y的Value对应列,点击后的效果如图1-136所示。

从图1-136中可以看到,x的值已经可以设置了,不过要注意的是,准备输入的值需要与Type类型相关,Integer类型的输入值当然不可以是字符串类型,反之亦然。在继续输入Value之前作者还要介绍一个小功能点,它就是<#>按钮(图1-136中0的右边),这个按钮的作用是参数化,可以在这里将Value参数化,然后在QTP的Data Table里设置各种需要的测试数据。来看一下它的界面,首先点击一下<#>按钮,点击后的效果如图1-137所示。

如图1-137所示,选择Parameter后就可以将参数进行参数化设置了,并且可以选择参数化数据的位置(Global sheet或Current action sheet)。另外,Parameter这个下拉框的其他一些选项在这里就不多做介绍了。读者目前只需要知道步骤生成器里也可以将数据参数化即可,关于QTP的Data Table会在后面的一个章节独立介绍。

回到正题,待x和y都设置好以后,再来看一下步骤生成预览区域的代码,看看是否起了变化,如图1-138所示。


如图1-138所示,在Click方法后面多出了两个参数,就是我们设置的x和y,当然,对于一个Button控件来说,这些参数其实可有可无,除非是一些很特殊的情况,一般情况下都是不用去设置的,作者在这里只是做个演示。

第一种手写代码的方式就写到这里,这个方式在QTP 8.x的时候还是经常被使用到的,接下来继续看一下其他代码生成方式。

第二种:Complete Word方式。

相信做过开发或者写过Java代码的读者都应该对Complete Word这个名词不陌生?它就是开发脚本过程中的催化剂。有了它就可以不用去死记硬背一些代码;有了它就不会再因为代码不小心编译错误而烦恼,比如最常见的拼写错误;有了它我们的编程速度会明显提升。因此,Complete Word不但对开发程序相当重要,对测试脚本的设计也同样起着至关紧要的作用!下面就来介绍如何在QTP中实现Complete Word。

首先打开QTP并依次点击上方菜单栏下的Edit→Advanced,在找到Complete Word后,读者会发现一个很尴尬的事情,就是QTP设定的Complete Word正是平常一直使用的切换中、英文的快捷键Ctrl+Space,而由于快捷键Ctrl+Space被优先认定为中、英文切换组合键,所以会导致QTP的Complete Word无效。

解决步骤。

(1)右键单击语言栏,点击设置。

(2)点击键设置,选择输入法/非输入法切换。

(3)点击更改按键顺序。

(4)如图1-139所示的选择,然后点击确定。

解决这个问题是很简单的,只不过如果读者平时习惯使用Ctrl+Space来中、英文切换,那为了使用QTP只能不用Ctrl+Space切换中、英文了。

在完成了以上4个步骤之后,就可以在Expert View中使用快捷键Ctrl+Space来调出Complete Word了,如图1-140所示。

接下来,来做一个实例,假设当前的Expert View中有以下两个函数:

Function test_hello_world_one
msgbox"test1"
End Function
Function test_hello_world_two
msgbox "test2"
End Function
现在,需要调用这两个函数,那么就可以直接使用Complete Word来效率地完成了,如图1-141所示。


是不是非常方便呢?再举一个例子,假设现在要使用Complete Word生成下面这段代码:

Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").Set "QTP自动化测试技术领航"
在这里,作者形象地写出生成这句代码的整个过程,使得读者可以掌握快速写代码的技巧,其实非常简单,读者看了以后就能学会,过程如下所示。

Step 1,敲击键盘Ctrl+Space,然后再敲击键盘上的字母B,此时,QTP会自动地找到以B开头的所有Complete Word(见图1-142),接着敲击回车,此时Browser这个Word就会输入到Expert View里,然后再敲击“左括号”,完成目前所有步骤后的效果见图1-143所示。


QTP中所有的代码编译都是基于英文输入法的,如果是中文输入法,检查语法的时候会显示错误。如果Step1中输入的是中文输入法下的左括号,那Browser的具体对象是不会跳出来的。

Step 2,从图1-143中可以看到,在敲击了左括号以后,QTP会自动将Browser控件的具体对象补全,(补充:这里QTP所补的具体对象一定要是对象库中存在的,换句话说,只有对象库编程才支持这种方法,另外,如果当前对象库中假设有两个Browser或其他任意对象(如Page、WebButton、WebEdit等所有),那么QTP会给出一个选择框来选择当前需要的对象,见图1-144),然后输入右括号来完成对象的描述,在这里描述的是Browser对象。

Step 3,完成了Browser对象后,现在需要调用它的子对象Page对象,此时只要敲击键盘上的“点”以后,就会弹出一个选择框,里面包含了Browser对象的所有方法、属性和子对象,然后敲击字母P使其直接定位到以P开头的Word,并最终定格在Page这个子对象的位置上,如图1-145所示。


接着就和Step2中一样了,使用左右括号来完成Page对象的描述。再以同样的方法完成WebEdit对象的编译后,就彻底完成了对象定位,如图1-146所示。


Step 4,完成最终对象定位以后,还没有真正的结束,最后一步就是给予最终定位到的对象一个“操作动作”,也就是常说的方法。在此,仍然需要敲击“点”来调用WebEdit对象下的各种方法或属性,在这里,选择的是实例要求中的Set方法,待所需的方法选择完成,最后一步是设置这个方法的参数值,这样,整个流程就完成了,如图1-147所示。


总结:Complete Word是目前QTP编写代码过程中使用率最高的一种方式,一旦操作熟悉以后,可以大大提高QTP自动化测试的工作效率。

第三种:对象拖动生成方式。

最后,作者要介绍的一种方式是把对象拖动到Expert View里来快速生成代码,这种方式只支持QTP10.0以上的版本,在之前的早期版本中没有此项功能,这项功能的出现也抢占了一部分使用第二种方式的市场份额。先来看一下这个新功能所在的界面,如图1-148所示。


如图1-148所示,可以看到所有的测试对象都出现在一个叫Available Keywords的窗口中,拖动对象生成代码必须也只能在这个窗口进行,其他位置(比如对象库)里就不支持对象拖动。在这个窗口中不光显示所有的测试对象,还会显示所有的Functions,包括外部调用的和脚本内部本身的Function,同时也可以看到右键单击某个对象后可以点击Open Resource,可以通过这样一种方式来进入对象库,并直接定位到所选的对象在对象库中的位置,可以说这个窗口是非常实用的一个功能。

那么接下来就介绍拖动生成代码的方法和一些必知的知识。拖动操作其实是非常方便的,只需要在窗口中定位到所需要的控件,然后Drag&Drop到Expert View中即可,如图1-149所示。


如图1-149所示,一句代码就自动生成了,生成最终对象WebEdit(“wd”)的同时也默认给出了一个最基本的方法Set,方法后的参数则需要自己填写,并且也可以看到,在生成完毕后,光标自动进到了第二行。在这里,读者需要知道,我们不仅仅可以定位最终对象,也可以对一些父对象进行拖动并生成代码,现在拖动Page(“百度一下,你就知道”)这个对象来试试看,如图1-150所示。


如图1-150所示,只用一句代码就生成了,这次生成的是Page连同其父对象,并默认给出了一个Sync方法(不用关心为什么默认会生成这个方法),如果需要使用其他方法,把.Sync删除,重新“点”一下即可。

总结: 随着代码拖动生成这个功能的实现,开发QTP脚本更加快捷了,当然这里有一个小小的不足就是会默认生成一个方法,这个方法往往不是想要的,只能手工去删除然后重新“点”出新方法,这样会浪费一点时间,但总体来说,代码拖动生成是目前为止最高效的一种方法,基本上使用QTP10.0以上版本的自动化测试工程师都会选择这种方式,也是作者强烈推荐的!当然,这个功能只能支持基于对象库的编程。
1.6.2.2 其他补充知识点
在上一个小节里,已经介绍了快速编译QTP脚本代码的3种方式,在本小节中,作者将补充一些QTP编码过程中的小技巧。

1.QTP IDE中的垂直分割选取
相信读者应该都知道在大多数开发的IDE中都会有垂直分割选取,它可以在文本中选取一个特定的垂直柱,并可以进行多行同时输入代码,如图1-151所示。

当然,QTP的IDE也不例外,同样也可以使用此功能,可以省去很多不必要的操作,让我们来做一个实例。

Step 1,新建一个Test,输入如图1-152所示的代码。


Step 2,现在可以使用垂直选取的方法轻松地对多行代码进行同时更改,首先,要选取到“垂直柱”。选取方法:在左上角点击鼠标左键往右拉一定距离不放手,与此同时,再点击一下鼠标右键,然后,就可以轻松地进行垂直段的选择了,如图1-153所示。


Step 3,选取垂直柱之后,可以输入想要更改的代码,比如这里输入“dim”,QTP就会同时对多行进行输入并覆盖原先的Public,如图1-154所示。

如图1-154所示,已经批量修改完毕了,同时这个小小的功能也就介绍完了,大家可别小看它,有时候往往能够帮助我们节省很多时间,提升工作效率。


2.代码换行符
假设现在有这样一句代码:Browser("51Testing软件测试网-中国软件测试人的精神家园").Page("51Testing软件测试网-中国软件测试人的精神家园").Image("51Testing软件测试网").Click,这句代码非常长,当前的Expert View无法完全显示这行代码,只能看到一半,这样的话看代码就会显得相当不方便,需要拖动滚动轴才能看到后面的代码。

如何解决?QTP提供了一个代码换行符号,它就是“_”符号。有了它,就可以将一句代码切分成好多行,缩短代码的长度,可以清晰地浏览代码,可以这样切分,比如:

'#1
Browser("51Testing软件测试网-中国软件测试人的精神家园")._
Page("51Testing软件测试网-中国软件测试人的精神家园")._
Image("51Testing软件测试网").Click
'#2
Browser("51Testing软件测试网-中国软件测试人的精神家园")._
Page("51Testing软件测试网-中国软件测试人的精神家园").Image("51Testing软件测试网").Click
'#3
Browser("51Testing软件测试网-中国软件测试人的精神家园")._
Page("51Testing软件测试网-中国软件测试人的精神家园")._
Image("51Testing软件测试网")._
Click
但是,我们不能这样切分,比如:

'#1 – “点”放在换行符号后面
Browser("51Testing软件测试网-中国软件测试人的精神家园")_.
Page("51Testing软件测试网-中国软件测试人的精神家园")_.
Image("51Testing软件测试网").Click
'#2 – 换行符号的插入导致描述一个对象(Image)的代码被分割成2段
Browser("51Testing软件测试网-中国软件测试人的精神家园")._
Page("51Testing软件测试网-中国软件测试人的精神家园").Image("51Testing _软件测试网").Click
'#3 – 在结束时不能使用换行符号
Browser("51Testing软件测试网-中国软件测试人的精神家园")._
Page("51Testing软件测试网-中国软件测试人的精神家园")._
Image("51Testing软件测试网").Click_
换行符号对于代码的可读性等方面起着重要的作用。其实,细心的读者应该已经在前面的章节中看到过这个“_”符号了,它将会是今后经常用到的工具

3.Alt+G快捷键
位置:依次选择QTP上方菜单栏→Edit→Advanced→Go to Function Definition。

这是一个比较有用的快捷键,假设目前的脚本有1000行代码,代码中有很多Function,此时如果有了这个快捷键,就能够将光标定位到调用Function的这行代码,然后按下Alt+G,快速跳转定位到该调用的Function在脚本中的位置,使得能够相当快速地查看到Function里的功能,演示如下:

'假设是第20行代码
Call func_test01 '调用func_test01函数 – 光标定格在本行,PRESS "Alt+G"



'假设这个函数从第850行开始
Function func_test01 'Alt+G后,光标会直接停留在此行,瞬间从第20行跳到850行


Msgbox"test01"


End Function
Alt+G功能介绍完了,读者需注意的是,它并不适用于外部调用的Function(函数)。

4.Ctrl+Shift+Space快捷键
位置:依次选择QTP上方菜单栏→Edit→Advanced→Argument Info。

在方法后往往需要设置一些参数,但是那么多参数难道都去背下来吗?显然不用,QTP会自动提示该方法的参数,如图1-155所示。

但是有时候会因为某些操作导致参数提示消失了,此时就可以使用Ctrl+Shift+Space快捷键来重新显示参数提示,这个小功能相当实用。

5.基于类和函数的Complete Word
在上一小节中,介绍了QTP可以使用Ctrl + Space快捷键来激活Complete Word的功能,增强脚本的编写效率,此方法只能对于一些vbs函数进行智能提示,对于类是不支持的。那么在这里,作者介绍QTP的一个支持类的Complete Word。方法很简单:Alt + .(Alt键加“点”键的组合)。

首先,打开QTP,输入以下代码:

Class libClass
Function libFunction

 Msgbox "libfunction"

End function
End Class
然后,使用Alt+.快捷键进行激活,如图1-156所示。


此方法只适用于QTP 9.2及其之前的版本。

6.学会使用With…End With
首先来一起看以下这段脚本:

'51Testing首页
Browser("51Testing软件测试网").Page("51Testing软件测试网")._
WebButton("WebButton").Click
Browser("51Testing软件测试网").Page("51Testing软件测试网")._
WebEdit("password").Set "Yu Jie"
Browser("51Testing软件测试网").Page("51Testing软件测试网")._
WebEdit("username").Set "Jerome Yu"
'百度首页
Browser("百度一下,你就知道").Page("百度一下,你就知道")._
WebButton("百度一下").Click
Browser("百度一下,你就知道").Page("百度一下,你就知道")._
WebEdit("wd").Set "QTP自动化测试技术领航"
在上面这段脚本中使用了很多代码换行符,这个在前面已经介绍过了。不知道读者看了上面这段脚本以后有没有发现一个问题,那就是每句代码中前面半段都是相同的,比如现在要操作51Testing首页中的一些对象,不难发现不同操作对象前的祖父对象和父对象都是一致的,遇到这种情况,就完全可以使用With来解决,见下面这个脚本:

'51Testing首页
With Browser("51Testing软件测试网").Page("51Testing软件测试网") '注意后面没有点

 .WebButton("WebButton").Click  '请注意“点”的位置,句首需要有一个“点”.WebEdit("password").Set "Yu Jie".WebEdit("username").Set "Jerome Yu"

End With
With就是用来提炼公共部分的,现在再去看脚本,是否一下子感觉清晰、有序了很多?又比如同一个脚本中需要操作两个网站,此时用With效果也非常好,见下面这个脚本:

'51Testing首页
With Browser("51Testing软件测试网").Page("51Testing软件测试网")

 .WebButton("WebButton").Click.WebEdit("password").Set "Yu Jie".WebEdit("username").Set "Jerome Yu"

End With
'百度首页
With Browser("百度一下,你就知道").Page("百度一下,你就知道")

 .WebButton("百度一下").Click.WebEdit("wd").Set "QTP自动化测试技术领航"

End With
如此一来,就可以很直观地读代码了,一目了然。With可以大大提高代码可读性,这同时意味着方便了我们以后的维护工作。

另外,可以随意“With”公共部分,也可以嵌套With,见如下脚本:

'百度首页嵌套在51Testing首页中
With Browser("51Testing软件测试网").Page("51Testing软件测试网")

 .WebButton("WebButton").Click.WebEdit("password").Set "Yu Jie".WebEdit("username").Set "Jerome Yu"With Browser("百度一下,你就知道").Page("百度一下,你就知道").WebButton("百度一下").Click.WebEdit("wd").Set "QTP自动化测试技术领航"End With

End With
'百度首页 -- 提炼其他公共部分
With Browser("百度一下,你就知道")

 .Page("百度一下,你就知道").WebButton("百度一下").Click.Page("百度一下,你就知道").WebEdit("wd").Set "QTP自动化测试技术领航"

End With
因为好用,所以With…End With是日常编程过程中经常使用的工具。

总结:

虽然本小节介绍的都是一些很小的应用技巧,但是往往能够给我们带来工作效率,QTP中的技巧也远远不止这些,相信更多的实用性技巧在于读者平时的挖掘与积累,作者认为,适合自己的才是最好的!

**1.6.3 封装对象模型—Test Objects VS Run-time Objects
1.6.3.1 解密测试对象与运行时对象**
在QTP里的封装对象共分两个概念,一个是Test Objects(俗称TO)“测试对象”,另一个是Runtime Objects(俗称RO)“运行时对象”。可能大部分读者已经不记得了,在上篇介绍Spy的那个章节中,作者在末尾处已经初步提到过TO与RO,我们来回忆一遍吧,以下是原文:“最后作者要说下,也算是一个预告吧,后者也就是Identification Properties以后会牵涉到对象库编程中的两个重大概念Test Objects(测试对象,俗称TO)和Run-time Objects(运行时对象,俗称RO),在为TO或RO进行编程的时候使用的就是QTP自己封装的这些对象属性。关于前者Native Properties也有其独特的调用方法。”

原文中提到了Spy中的Native Properties以及Identification Properties,后者就是要在本小节重点讲的封装对象的属性,而前者会在后面介绍对象自身接口的属性时介绍。不过无论是哪一个,都和对象库编程有着紧密的联系,基于对象库的编程就是基于这些属性来完成的。

继续回到主题,TO和RO这两个概念从字面上来看并不是很好理解,也容易混淆。作者现在就用最简单的描述来介绍测试对象(TO)与运行时对象(RO)的区别:TO就是被添加到对象库中的对象,RO其实就是被测试软件在运行时实际所运行的那个对象。但是,读者要记住,无论是TO还是RO,它们都属于QTP封装的对象,共同使用QTP封装好的一些属性,RO就有点特殊了,它也可以调用自身接口的属性,这个是在下个小节中要讲述的内容,读者在这里只要知道RO也调用QTP封装好的属性就可以了。

在上篇中已经讲解过QTP鉴别对象模型的机制Object Identification,QTP识别对象通常就是先在对象库里添加测试对象,这些对象全部都存有一些特征属性的值,然后在被测软件运行的时候,QTP会根据脚本里的对象名字,在对象库里找到相对应的测试对象,并根据这些对象的特征属性描述,在被测试软件里搜索并找到相匹配的实际正在运行的对象,最后就可以对这些实际运行的测试对象进行操作了。如果在这个过程中没有找到任何相匹配的对象,那么QTP就会报个“找不到该对象”的错误。最后,作者用最简单的一句话总结一下测试对象(TO)与运行时对象(RO)两者之间的紧密关系:测试对象是为了识别运行时对象而存在的。

1.6.3.2 三兄弟GETRO、GETTO、SETTO各显神通
在理解了Test Objects与Run-time Objects以后,就要开始学习如何获取到对象的属性了,毕竟自动化测试分成两大块,第一个就是自动操控被测对象。第二个就是获取各种所需要的对象属性,获取属性的作用也可以分成两部分,一个最重要的作用也是最常用的就是验证,验证离不开这些属性,只有这些属性才能证明软件的操作是正确的还是错误的,另一个用途就是获取到一些有利用价值的属性来做后续的事情。还有一个分支,就是给对象库里的对象通过代码自动设置一些属性,以达到特殊的测试目的和要求。所以,在自动化测试过程中,对于“属性”的掌控是很重要的,接下来就详细介绍操控属性的各种方法,待掌握以后再举一些项目中基本的实际使用例子来帮助读者理解各种方法的作用,并证明其实属性的获取是自动化测试过程的桥梁。所以,这些对属性操作的方法绝对是重点中的重点内容。那么就让我们看看对象属性的处理方法有哪些,并逐一进行介绍。

素材:www.baidu.com百度首页,所需添加对象如图1-157所示。

1.GetTOProperty()
基本含义:获取对象库中某个对象的某个属性的值。
公式:ReturnValue =对象.GetTOProperty("封装属性名")
基础示例:
ValueOfTo = Browser("百度一下,你就知道").Page("百度一下,你就知道").Link("新闻").GetTOProperty("text")
MsgBox ValueOfTo
运行结果与分析。
获得Link对象在对象库中记录的属性“text”的值,并返回给变量ValueOfTo,最后以对话框形式显示这个值,显示后的结果如图1-158所示。

从图 1-158 中可以看到,已经成功获取到了该对象的“text”属性值并弹出对话框显示。在这里,读者需要注意,如果在实际运行的过程中,“text”属性已经发生了改变,假设变成了“贴吧”,在这里仍然是获取到“新闻”这个值,因为GetToProperty这个方法就是获取对象库中的对象的属性值。

企业项目案例臆测。
如果项目中碰到这样一个需求:界面上有一个test1的下拉框控件,每次在刷新页面后都会选中默认值A,现在业务中需要选择其他值,我们需要用QTP做比较。像碰到这种案例时,就可以通过使用GetToProperty和GetRoProperty(后面会讲到)这两个方法协助完成,只要在下拉框选中默认值的时候将其加入对象库,这样对象库中的记录值就永远会是这个默认值了,然后在实际运行时选取其他值,并获取此时这个对象的实际选取的值,最后对两个值做一个比较,通过这个思路就能解决这个需求了。

2.GetTOProperties()
基本含义:获取对象库中某个对象的所有属性的值。
公式:ReturnValue =对象.GetTOProperties()。
基础示例:
Set TestObject = Browser("百度一下,你就知道").Page("百度一下,你就知道").Image("百度首页logo") '1

Set Properties = TestObject.GetTOProperties()  '2
PropertiesCount = Properties.Count  '3
Print "对象总计存在" & PropertiesCount & "个封装属性。"   '4
For i = 0 To PropertiesCount – 1  '5PropName = Properties(i).NamePropValue = Properties(i).ValuePrint  PropName & " = " & PropValue
Next
Set Properties = Nothing  '6
Set TestObject = Nothing  '7

运行结果与分析。
首先,GetTOProperties这个方法获取的是一个数组,这个务必要清楚。因为是数组,所以想要一个个打印属性值的前提条件就是,先要得到对象的属性个数,然后再通过循环的方法把一个个属性和属性值打印出来。但是,GetTOProperties并没有提供Count方法,所以,只能通过其他方式去获得对象属性的Count(见代码片中的1~3)。在获取到Count以后,就能够一个个将值读出来了(见3~5),当然,最后也别忘了释放对象(见6~7)。

为了更好地显示结果,所以才在这里使用了Print函数(QTP自带的函数,调用后会将一些信息填写到Print Log窗口中),最后就让我们一起来看一下打印结果,如图1-159所示。

企业项目案例臆测。
一般情况下,在项目中很少会使用到GetTOProperties这个方法,因为通常不会碰到需要使用到这个方法的需求。所以,GetTOProperties这个方法也是所有操作对象属性中最少使用的一个方法,也正是因为如此,作者才没将本小节的标题写成“四兄弟”。

3.SetTOProperty()
基本含义:设置对象库中某个对象的某个属性的值。
公式:对象.SetTOProperty“封装属性名”,“封装属性值”。
基础示例:
Browser("百度一下,你就知道").Page("百度一下,你就知道").WebButton("百度一下").SetTOProperty "name","百度一百万下"
MsgBox "时间停止,大家一起欣赏此时对象库中WebButton"百度一下"的name值!"
运行结果与分析。
SetTOProperty方法的作用就是改变对象库中的值,当然,使用代码形式的修改对象属性属于临时性的,只在脚本运行时有效,一旦脚本运行结束,对象库里的属性值就会还原,它的生命周期是短的,不过已经足够我们做很多事了。

在本段代码片中,要修改的是WebButton(“百度一下”)这个控件在对象库中的属性,为了证明修改最终是成功的,那么让我们一起先来看一下修改以前的name属性值,如图1-160所示。


从图1-160中可以看到,name的属性值是“百度一下”,然后作者把它改成了“百度一百万下”,我们前面讲过,由于SetTOProperty这个方法的生命周期很短,所以,如果要看到修改的效果,必须在脚本结束前,将脚本停住,所以,作者在脚本里加了一个MsgBox方法,并将本行设置断点,这样QTP就会停止下来,此时去刷新一下对象库就能看到百度一下这个按钮的name值已经改变了,如图1-161所示。


如图1-161所示,此时对象库中“百度一下”这个控件的name属性值已经变成了作者所设置的“百度一百万下”,到此也证明了实验已成功。需要注意的是,使用SetTOProperty方法,后面的参数是不需要加括号的,因为它没有返回值,当然这是VB中的知识点,在这里稍许提一下,如果在这种情况下加括号是一定会报错的,切记!

在QTP中,断点的快捷键是F9,使当前断点不生效/生效的快捷键是Ctrl+F9,取消所有断点的快捷键是Ctrl+Shift+F9。

企业项目案例臆测。
可以和GetToProperty那个案例结合,假设现在需要将对象库中的对象属性值转变成其他指定的值,这种情况下,就可以使用SetTOProperty方法了。另外,使用SetTOProperty这个方法还有其他好处,比如可以解决一些共享对象库的对象修改和管理问题等。

这里还有一个很经典的自动化测试案例告诉读者,假设某个窗口上有很多待检查的记录,每条记录右边都有一个Check按钮用来检查各条记录。但是,记录个数是不定的,所以Check按钮个数也就不定,只有一个Edit控件显示记录个数。要对每条记录进行检查,也就是要点击每个Check按钮。但是Check按钮由于个数不定,根本没法将每个Check对象都添加到对象库中,因为个数可能太多了(上百个),如果硬要一个个添加到对象库中,是很烦的事。在这里告诉大家一个好办法,就添加一个Check按钮对象,它设有两个特征属性,分别是:label=OK、index=0,然后用下面的脚本就可以完成该自动化任务了:

buttonNum = CInt(JavaWindow("Test").JavaEdit("Record Num").GetROProperty("value"))
For buttonIndex = 0 to buttonNum -1JavaWindow("Text").JavaButton("Check").SetTOProperty("index",buttonIndex)JavaWindow("Text").JavaButton("Check").Click
Next

分析:这段脚本的第一行代码是先通过Edit控件来获取页面上Check按钮的个数,然后通过循环并利用SetTOProperty方法一个个地去改变对象库中那个添加好的Check按钮对象的index,这样只需要添加一个对象就可以实现N个相同对象的操作了。

或者还有这样一个经典案例,假设窗口上有New、Modify、Delete、Check等好几个按钮对象,需要把这几个按钮一一按过去,这种情况下也只需要在对象库里只添加一个按钮对象就可以了,假设它叫“AnyButton”,label的特征属性值随意填写即可,然后用下面的脚本来实现:

JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label","New")
JavaWindow("Test").JavaButton("AnyButton").Click
JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label","Modify")
JavaWindow("Test").JavaButton("AnyButton").Click
JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label","Delete")
JavaWindow("Test").JavaButton("AnyButton").Click
JavaWindow("Test").JavaButton("AnyButton").SetTOProperty("label","Check")
JavaWindow("Test").JavaButton("AnyButton").Click

4.GetROProperty()
基本含义:获取实际在运行时的某个对象的某个属性的值(不是从对象库里面获取)。
公式:ReturnValue =对象.GetROProperty("封装属性名")。
基础示例:
ValueOfRo = Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("搜索内容编辑框"). GetROProperty("value")
MsgBox ValueOfRo
运行结果与分析。
首先,GetROProperty 方法访问的是实际正在运行的对象的封装接口,在这里做一个实验来证明这个方法的效果。第一步就是添加WebEdit这个“搜索内容编辑框”控件到对象库中(注意,在还没有输入过任何字符的时候进行添加),添加完以后可以看到对象库中该对象的value属性的值是空的,如图1-162所示。


如图1-162所示,value的值是空值,因为还没有在编辑框中输入任何值的时候添加的。接着做第二步,在编辑框中输入“QTP自动化测试技术领航”,如图1-163所示。

在完成这些操作后,执行下代码片中所写的脚本,其结果显示如图1-164所示。


图1-164中显示的结果已经很明显了,证明了GetROProperty的方法是获取实际在运行时对象的属性值“QTP自动化测试技术领航”,而不是该对象在对象库中的值“空值”。细心的读者一定会发现,刚才在查看对象库中WebEdit控件value值的时候,是通过点击Add Properties按钮,然后在弹出的界面中看到的,作者在这里只是看了一下这个属性的值,并没有将这个属性添加到Description Properties窗口中,知道为什么不能添加到该窗口吗?因为一旦添加进去,QTP就会报错了。在之前的内容中讲过QTP识别对象的机制,就是通过Description Properties窗口去匹配的,如果把value属性加到这个窗口下,那么在输入“QTP自动化测试技术领航”这些字符以后,实际运行时QTP就会因为识别不了对象而导致报错,因为Description Properties窗口下所有的属性都是必须要匹配到的识别属性。

企业项目案例臆测。
GetROProperty方法在项目中使用率就太广泛了,几乎所有的验证点都需要使用这个方法。比如注册功能,在提交一些注册信息以后,一般都要到接下来的确认页面去验证一些信息,这些值都是动态的,在这里就能使用GetROProperty这个方法来动态获取实际运行时的一些确认信息,然后和所预期的测试数据做对比就可以了,这样就达到了自动化测试的目的。

总结: 属性对于自动化测试的重要性就不再老生常谈了,在刚接触QTP的时候,对于对象的封装属性都还不熟悉,此时Spy对我们来说就太重要了,用好Spy就可以轻松查到封装对象有哪些属性了,从而选择那些可利用的关键属性来完成自动化测试业务需求。除了Spy,只要有其他工具能探测到对象属性,那也是一样的,比如可以自行开发一个探测工具。在这里,也推荐给读者一个Spy的黄金搭档(只针对Web系统),那就是微软的IEDevToolBar,它同样也是一个探测工具,它可以轻松探测到节点和节点的属性名及其值,有兴趣的话可以网上搜索一下或者到微软的官方网站下载。
另外,相信读者应该已经发现,在QTP中使用封装方法对测试对象进行操作,只提供了SetTOProperty这一个方法来对属性进行设置和修改,其他的方法都是在做一些获取属性的操作。但是,SetTOProperty这个方法只能修改对象库中对象的值,那有没有修改实际运行时对象的属性的办法呢?答案将会在后面揭晓……

1.6.3.3 对象封装属性的真正源头
在介绍Spy的那个章节中,我们就已经介绍过Identification Properties下会显示很多对象的封装属性,如图1-165所示。

如图1-165所示,WebEdit控件的封装属性数量还是相当可观的,不光图中显示的这些,还可以通过右侧拖动滚动条看到更多的属性。这些属性都是可以通过GetROProperty方法进行访问的,这个在上一节中刚讲过,这里就略过了。在这里主要是介绍一个特殊的属性,它就是Class Name(见图1-165中第一个属性),这个属性在介绍Spy的那节中就已经介绍过。刚才说过了,凡是封装属性的值都可以通过GetROProperty方法去获得,那么,现在执行下面的这段代码,看看是否能够获得Class Name的值,预期结果应该是“WebEdit”(见图1-165):

msgbox Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").GetROProperty("Class Name")
待QTP执行完这段代码以后,我们一起来看执行后的结果,如图1-166所示。

为什么获得的值是个空值?应该是“WebEdit”。图1-165中都是这么显示的。其实是因为QTP封装此属性的名称不是Class Name,而是micClass,不信?那我们执行下面这段代码再试试看,是不是会获取到“WebEdit”这个值:

msgbox Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").GetROProperty ("micClass")
QTP开始执行,结果如图1-167所示。


如图1-167所示,结果已经看到了,就是想要的预期结果。此时,读者一定会问,为什么是micClass,而不是Class Name呢?为什么作者就知道是micClass呢?连Spy里显示的都是Class Name啊!别急,答案很快就会揭晓!

首先,我们运行regedit来打开注册表,然后进入到以下位置:

HKEY_CURRENT_USER -> software -> Mercury Interactive -> QuickTest Professional -> MicTest -> Attributes
当展开Attributes这个目录时,会看到很多熟悉的属性。没错!这里就是QTP所有封装属性的集结地,如图1-168所示。


在这个目录下可以找到micClass属性(见图1-169),而Class Name属性是没有的,所以刚才打印出来的值是一个空值就是这个原因。


另外还有很多QTP隐藏的封装属性,并且这其中一部分属性在QTP的所有帮助文档中都没有提到过。在这里,作者就随便找一个Spy中没有的封装属性来试试,以source_index为例,来看下面这个脚本:

'获取封装属性source_index的属性值
index = Browser("百度一下,你就知道")._
Page("百度一下,你就知道").WebEdit("wd").GetROProperty("source_index")
'在这里对WebEdit控件使用了描述性编程就是为了证明source_index是个隐藏属性,Spy中是没有的,关于描述性编程,读者先不用关心,后续章节中会详细介绍
Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("source_index:=" & index).Set "QTP自动化测试技术领航"
执行上面这个脚本后,就可以看到百度搜索框成功输入了“QTP自动化测试技术领航”。它的原理主要是通过source_index获取对象的索引,并通过描述此属性成功对此对象进行控制。

通过这个实例,我们终于明白了对象封装属性的真正源头到底在哪里!在这个目录下不光可以看到一些平时所常用的一些隐藏属性,例如,creationtime、index等,还有很多从来没有看到过的隐藏属性,有兴趣的读者可以每个都去尝试一下。

每个属性都是有对应的对象的,比如creationtime属性只能用在Browser对象上,这点需要读者认知的。

**1.6.4 梳理运行时对象的封装与自身接口的属性区别
1.6.4.1 解读对象的自身接口**
在上一节中,作者已经介绍过实际上运行时的对象是有两种接口的,第一个就是上一节中主要讲解的对象封装接口,另一个就是将在本小节中重点介绍的对象自身接口。首先让了解一下两种接口的区别。

封装接口是对象的不完全属性,有些对象的属性值是封装接口无法获取得到的。
运行时的对象(RO)可以看见自身接口的所有属性,而对象库中的测试对象(TO)只可以看见被封装的一些接口。
封装属性是不能修改实际运行时的对象的,只能获取属性的值,而调用自身接口就可以。
以上3条就是封装属性与自身接口属性两者间的区别,其实读者应该不难发现这两者之间有本质上的一个特性,那就是封装接口既支持(或者叫涵盖吧)对象库中的测试对象,同时也支持运行时的对象,而自身接口就只支持运行时的对象,这点千万要注意,也不要搞混了,对于初学者来说这是一个难点和容易混淆的地方。

1.6.4.2 教你如何成为一名黑客
虽然现在读者已经了解了对象分测试对象与运行时对象,运行时对象除了有封装接口之外还有一个自身接口,但是这些都是概念上的内容,相信读者还是不明白自身接口到底是什么。在这里作者卖个关子暂且不告诉大家,先来玩一个有趣的“魔术”,作者在这里扮演一个黑客的角色,将这本书的推广方“51Testing”给黑掉。在袭击51Testing官方论坛首页之前,还是先让广大读者再看一下,因为过一会它将会变得面目全非:

如图1-170所示,目前51 Testing的论坛还是原样,一会,作者将“51Testing”网站给黑掉,如图1-171所示。


如图1-171所示,51Testing网站界面上的某些控件经过作者的“施法”已经被替换成了百度网站中的一些控件,一共发生了4处变化,已经在图1-171中标注,它们分别是。

(1)将WebButton控件“登录”改成“百度搜索”。

(2)将Image控件“51Testing的Logo”改成“百度的Logo”。

(3)将Link控件“加入51Testing(注册)”改成“加入百度(注册)”。

(4)将Link控件“登录”改成“baidu_login”。

读者现在一定是非常的兴奋(很正常,当初作者也是如此的兴奋),为什么作者的手段那么厉害,能如此轻易地攻击一个大型网站。首先,作者可以告诉广大新人,作者的“帮凶”不是别人,正是这个强大的自动化测试工具QTP。所以,作为新人的你是不是一下子对QTP产生了浓厚的兴趣?的确是这样的,一旦学会了如何去当一名“黑客”,你一定会对QTP兴趣倍增,而且一旦学会了黑客之道,也同时证明了你的QTP水平已经上了一个台阶。

接下来作者将这个“魔术”表演分享并分解给读者,首先作者展示实现这个“魔术”表演的QTP脚本代码如下:

With Browser("51Testing软件测试论坛").Page("51Testing软件测试论坛")

 .WebButton("搜索").Object.value = "百度搜索".Image("51Testing_Logo").Object.src = "http://www.baidu.com/img/baidu_sylogo1.gif".Link("加入51Testing(注册)").Object.innerText = "加入百度(注册)" .Link("登录").Object.innerText = "baidu_login"

End With
上面这个脚本就是完成这个“魔法”的“功臣”,现在就来揭晓为什么作者可以轻易地改变51Testing网站!其实,就是因为使用自身接口修改了正在运行时的对象,所以才出现了图1-171中的假象。在上一小节中作者就已经介绍过了封装对象接口和自身接口的区别,其最后一条说的就是“调用自身接口就可以修改实际运行时的对象的属性值”。不过,它的确是假象,只需要刷新网页,51Testing网站就恢复原貌了。不过如果不刷新网页,那么这个“魔术”还是继续有效。比如作者假设把“注册”功能屏蔽掉,那的确是不可能点击到“注册”按钮的。这个实验作者也将留给读者去尝试,作为本章节的练习内容。

在了解这个魔术背后的秘密之后,一起来看一下调用自身接口的公式。

对象.object.自身属性,示例如下:
Browser("百度").Page("百度").WebButton("百度一下").Object.innerText = "百度一百万下"。
分析:以上代码是将WebButton("百度一下")这个对象的自身接口属性innerText设置成其他属性值“百度一百万下”。

对象.object.自身方法,示例如下:
Browser("百度").Page("百度").WebButton("百度一下").Object.click。
分析:以上代码调用WebButton("百度一下")这个对象的自身接口的方法click,以自身接口的方式完成点击操作。

另外,自身接口不但可以设置运行时属性的值,同样也可以获取运行时属性的自身接口的属性值,先来看图1-172所示。

现在,要通过调用自身接口的方式来获取动态运行时的“百度搜索框”的内容,示例代码如下:

getContent = Browser("百度一下,你就知道").Page("百度一下,你就知道")._
WebEdit("wd").Object.value : MsgBox getContent
分析:以上代码是获取WebEdit("wd")这个对象的自身接口的属性“value”的属性值,然后弹出对话框显示出这个属性值,如图1-173所示。


注意到上段代码中MsgBox…和getContent…处于同一行代码了吗?难道没有疑问吗?这样QTP为什么没有报错?其实答案就在于在代码中加了“:”冒号。冒号在这里的作用就是连接本不相干的两句或N句代码使其合成一句。如果不加冒号,那QTP一定会报错。

到此,相信读者一定会产生这样一个疑问,那就是如何知道获取content就是用value这个自身接口属性?其实这个完全是凭经验的,作者一开始也不知道,做过了就明白了。新人在平时可以多用Spy去了解对象的属性(自身接口的、封装的一个都不能落下)并逐一尝试,过不了多久就可以熟悉了。

既然获取的时候用value这个属性值,那么,如果要对搜索编辑框输入一个值该怎么操作呢?同样也是要用到value这个自身接口属性值。先让我们来回顾一下如何用封装接口进行赋值操作,代码如下所示:

Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").Set "Yu Jie"
紧接着,用自身接口的方式,代码如下所示:

Browser("百度一下,你就知道").Page("百度一下,你就知道")._
WebEdit("wd").Object.value = "Jerome Yu"
最后,一起来见证是否调用自身接口也能为百度搜索框赋值,如图1-174所示。

在结束这个知识点的介绍前,作者再次强调自身接口是无法调用对象库中的对象属性值的,读者务必记住!此外,作者还要分享给读者一些需要注意的地方,相同的属性名在自身接口和封装接口中的显示有所不同,以最常见的INNERTEXT来举例,如图1-175和图1-176所示。


如图1-175和图1-176所示,我们可以看到,在自身接口中显示的是“innerText”,T是大写的,在封装接口中则显示的是“innertext”,全是小写。举个例子,假设前者innerText的值等于A,现在需要获取这个值,如果此时误写成innertext的话,获取的值将是一个空值,就完全与预期不一样了,所以,读者务必要注意到这点,一开始会很容易犯错,而这些小错误对于没经验的新人来说很难察觉到,因为代码并没有错,所以QTP也不会报错。

1.6.5 几种常见对象无法识别或识别错误的原因
对象库的整个学习过程即将结束了,无论是调用封装接口还是调用自身接口,它们都要有一个大前提,那就是对象能够被QTP识别。但是往往在自动化测试过程中,会碰到很多对象无法正确识别或识别错误的情况,作者进行了一下总结,以下几种原因是最常见的。

1.软件程序的对象控件无法被QTP识别
QTP毕竟不是万能的,很多软件的对象控件都无法识别到,尤其是C/S架构的软件程序,大多数控件都是WinObject。碰到这种情况,在第一章节中就说过了,此类项目是不适合用QTP做自动化测试的,当然如果必须要做自动化测试,通常有以下几种解决方案。

(1)设置虚拟对象。

先来知悉虚拟对象的方位,如图1-177所示。


如图1-177所示,该位置就是虚拟对象,存在两个功能,新增虚拟对象和管理虚拟对象。作者在这里不对此功能多做介绍,因为并不推荐这个方法,即使依赖虚拟对象解决了所有不能识别的对象,但以后的对象维护工作是根本没法继续下去的,而且虚拟对象本身就非常脆弱,即使对象没有发生变化,但是,只要对象在界面上的方位发生变化,虚拟对象就会识别失败。所以,读者只需要了解一下这个功能就可以了,感兴趣的读者不妨尝试着亲自设置一些虚拟对象。

(2)使用相对坐标然后配合WSH去定位对象。

当碰到对象无法识别的时候,还可以通过这种办法尝试解决。因为即使是一个WinObject对象,它仍然有坐标,所以,使用相对坐标则可以帮助动态定位对象的位置,然后再使用WSH去对这个WinObject做一些操作(当然,这些操作不可能非常全面)。还比如,虽然对象无法识别,但是它支持快捷键操作,比如使用“Ctrl+O”的快捷键组合可以打开某个东西,遇到此类情况,也可以使用WSH来巧妙地完成想要完成的业务(虽然对象仍然是不能识别的,但是只要能达到预期目标,任何方法都是好方法)。关于WSH的知识点会在后续的章节中详细介绍。在本小节中,读者只需要知道常见的对象无法识别案例和相应的解决方案即可。

(3)使用DOM组件接口应用技术。

DOM的全称是Document Object Model。这种办法只可用于Web项目。举个例子,淘宝网的密码输入框用正常的Set方法是无法操作的,此时就可以调用DOM的GetElementById方法,然后进行密码输入的操作。DOM也会在后面的章节中详细介绍,这里不多做阐述。

(4)使用QTP自定义扩展SDK Customer来进行二次开发使QTP能够识别对象。

这个属于QTP中最高深的技术。目前关于此方面的技术文章在QTP学习网站中都是非常少的。本书的作者曾录制过两个教学视频介绍此方面内容,如果读者有兴趣可以联系本书的两位作者,在本书的末尾有作者的联系方式。

(5)开发提供专属插件。

作者曾经有过类似的自动化测试项目经历,对象基本都无法识别,但是自动化测试需要做下去。于是开发了专职对象识别脚本,然后利用QTP这个平台去执行自动化测试。像这种情况,其实自动化测试的主力就已经不再是QTP了。

(6)把无法识别的对象的一些方法封装到一个dll中并使用QTP调用。

这个方法和上面的有所区别,自动化测试主力仍然是QTP,在QTP中有一个Extern对象,这个对象就是专门司职外部dll调用工作的,开发只需要把各种方法封装成一个dll即可,关于调用外部dll的技巧同样会在后面的章节中介绍到。

2.对象可以被QTP识别,但是加载的插件不正确
发生这种情况总体来说还是幸运的,因为毕竟这也许只是一个误操作,只需要重新加载相对应的正确插件,QTP就可以为你服务了。

3.同一个界面中存在两个或两个以上的属性相同的对象
有这么一种情况,同一个页面中存在多个属性相同的对象,这种时候QTP会报错并在报错信息中提示我们。像遇到这种问题时,最直接的解决办法就是为每一个对象做一个唯一标识符,最常见的就是设置Index。

4.实际运行时的对象发生了改变导致与对象库不匹配
在自动化测试过程中,很多对象都是动态的,在运行时,属性是一直在发生变化的,比如句柄。碰到类似的问题,解决思路就是先动态获取运行时的值,然后将这个值动态添加到对象库对象中,这样就可以轻松解决该问题了。如何动态获取运行时的值,如何将值动态添加到对象库对象中,这些都是前面的重点内容,读者如果有所遗忘,请重新回顾!

1.6.6 总结
本章节和上一个章节不同,主要是围绕如何去实现脚本。这两个章节合起来几乎涵盖了对象库编程所有的精华部分,读者务必要学精、学透。作者已经给了方法,接下来就是要通过大量的实践和反复的练习真正地驾驭好它。

对象库编程的确是相当好用的,QTP高效编程的3种方式也都是基于对象库的,这些高效的方法是不基于在下面的章节会介绍的描述性编程的。所以,一般情况下,作者建议使用对象库编程。

知识点巩固和举一反三练习

一、过把“魔术师”或黑客的瘾!

要求1:根据图1-178和图1-179中的数字标识依次按要求慢慢“吞噬”百度首页。


(1)将Title和Tab变成“QTP自动化测试技术领航”。

(2)将Logo变成51Testing首页的Logo,URL为www.51testing.com。

Logo图片来源:进入51Testing首页后,右键单击网站Logo后,在弹出的菜单中点击属性,复制URL,如图1-180所示。


(3)将贴吧变成“51Testing专家博客”。

(4)将搜索框禁用(无法输入任何文字)。

(5)将[百度一下]按钮变成“51搜索”。

(6)将“把百度设为主页”变成“把51Testing设为主页”。

(7)将“加入百度推广”变成“加入51Testing推广”。

(8)将“关于百度”变成“关于51Testing”。

(9)将“About Baidu”变成“About 51Tesing”。

(10)将该处文字替换成“©2011 51Testing测试自动化系列丛书-QTP自动化测试技术领航”。

要求2:提取公共部分代码,提高代码维护性、直观性。

二、分别使用已学过的QTP编程的3种方式来完成第一题。

要求1:熟练运用并掌握,然后评价出你觉得最适合你的一种方式。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

《精通QTP——自动化测试技术领航》—第1章1.6节对象库(下)之进阶编程篇相关推荐

  1. 《精通QTP——自动化测试技术领航》—第1章1.3节录制与回放—QTP的开关

    本节书摘来自异步社区<精通QTP--自动化测试技术领航>一书中的第1章1.3节录制与回放-QTP的开关,作者余杰 , 赵旭斌,更多章节内容可以访问云栖社区"异步社区"公 ...

  2. 《精通QTP——自动化测试技术领航》—第1章1.2节帮助文档(HELP)-QTP的说明书...

    本节书摘来自异步社区<精通QTP--自动化测试技术领航>一书中的第1章1.2节帮助文档(HELP)-QTP的说明书,作者余杰 , 赵旭斌,更多章节内容可以访问云栖社区"异步社区& ...

  3. 《精通QTP——自动化测试技术领航》—第1章1.5节QTP精华—对象库(上)之基础攻略篇...

    本节书摘来自异步社区<精通QTP--自动化测试技术领航>一书中的第1章1.5节QTP精华-对象库(上)之基础攻略篇,作者余杰 , 赵旭斌,更多章节内容可以访问云栖社区"异步社区& ...

  4. 软件测试技术qtp,51Testing独家连载:(四十一)精通QTP——自动化测试技术领航

    操控方式2: '获取DOM对象 setoDocument = Browser("Browser").Page("Page").Object '使用GetElem ...

  5. 51Testing独家连载:(七)精通QTP——自动化测试技术领航

    1.3 录制与回放-QTP的开关 阶段要点 录制在实际项目应用中的价值观(极低). 新手切记不可在项目应用时被禁锢在录制中. 录制及其相关功能的重点知识点提炼. 录制功能"旁门左道" ...

  6. QTP自动化测试技术——经典面试题

    文章目录 1) QTP 支持那些环境? 2) QTP 的对象库类型是什么? 3) 可以在其他测试中用脚本语言调用 QTP 测试吗?假设有四个测试,我想在一个主脚本中调用这些测试,这种 QTP 中可能吗 ...

  7. 《Selenium自动化测试指南》—第1章1.1节自动化测试基础

    本节书摘来自异步社区<Selenium自动化测试指南>一书中的第1章1.1节自动化测试基础,作者赵卓,更多章节内容可以访问云栖社区"异步社区"公众号查看. 1.1 自动 ...

  8. 《编译与反编译技术》—第1章1.7节C语言程序的编译流程

    本节书摘来自华章出版社<编译与反编译技术>一书中的第1章,第1.7节C语言程序的编译流程,作者庞建民,陶红伟,刘晓楠,岳峰,更多章节内容可以访问云栖社区"华章计算机"公 ...

  9. 【JSP笔记】第四章 JSP内置对象【下】

    2019独角兽企业重金招聘Python工程师标准>>> 1.什么是session 表示客户端与服务器的一次会话. Web中的session指用户浏览网站时,从进入网站到浏览器关闭的这 ...

最新文章

  1. socket-accept
  2. PaddlePaddle 中的若干基础命令中的问题
  3. 如何在服务器端写关闭窗口的代码?同时能够更新父窗口?
  4. 属于服务器操作系统的有,属于服务器操作系统的有
  5. Centos下lnmp编译安装详细过程
  6. ambari搭建注意事项
  7. 文字转语音开源软件-espeak
  8. 状态反馈不改变系统传递函数零点的证明
  9. python使用selenium大麦网抢票
  10. 《数据库原理与应用》课程实验报告三 --数据库的嵌套查询
  11. 这两天火爆全网的「蚂蚁呀嘿」App,被下架了...
  12. [渝粤教育] 西南科技大学 资源与环境概论 在线考试复习资料
  13. MT7682参考手册,MT7682芯片资料介绍
  14. matlab绘制分组条形图的误差棒errorbar
  15. 如何做机器学习模型质量保障及模型效果评测
  16. IP 地址详解(IPv4、IPv6)
  17. DAX 第八篇:【翻译】数据沿袭(Data Lineage )
  18. 线性代数(六) : 线性相关与线性无关
  19. 更换内存条需要注意什么
  20. 二十五个摸鱼,哦,不对,是炫酷(可以玩一整天)的网站!!!

热门文章

  1. 旧手机能拿来干什么有趣的事情?
  2. 畅所欲言吧!神器助你避开毕姥爷那样的饭局门
  3. 基于回归分析的广告投入销售额预测——K邻近,决策树,随机森林,线性回归,岭回归
  4. electron-vue打包win32失败处理
  5. 100个3D模型素材.zip
  6. Kerberos报错:kinit: Password incorrect while getting initial credentials
  7. 大学生1500元够用吗?
  8. 【HTML特效程序】① 给女神表白的程序(让女神看科技烟花),输入名字自动生成表白二维码
  9. c++ 懒羊羊找朋友
  10. LeetCode-804.唯一的摩尔密码词