发布新日志

  • QTP使用小技巧2

    2009-08-06 14:20:38

    3. 第2种方法只能在web中使用,那么如果其他类型的对象需要等待时间怎么办?可以使用QTP系统自带的同步点功能。
      还是上面的例子,在录制状态下,选择Insert-->Synchronization Point,选择要同步的对象,设置要同步的属性,我们可以对对象的Enable,visible一类表示状态的属性做同步点,生成如下脚本
      Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").WaitProperty "visible", True, 100000
      这句话的意思就是在100秒的时间内,等待WebEdit这个对象的visible属性,只要它的visible属性变为true,那么就执行下面操作,最后的100000单位是毫秒,如果在100000毫秒(100秒)后还没有等到visible = true,直接执行下面操作。
      4. 利用VBS语句。
      Do until Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").Exist(5)
      Wait(1)
      Loop
      判断WebEdite这个对象是否出现,如果没有出现,执行Wait(1),如果出现,跳出循环。
      5. 死等大法。
      就是用Wait( )语句设置等待时间,死等,比如Wait(10),就是脚本停止10秒,任何操作都不做,10秒之后继续往下执行操作。
  • QTP使用小技巧1

    2009-08-06 14:19:38

    脚本如下:(注意紫色部分脚本)
      Dialog("Login").WinEdit("Agent Name:").Set "Cheers.Lee"
      Dialog("Login").WinEdit("Password:").SetSecure "49df4eabed69867d55a22bbcdc7cceb6d10c9abc"
      Dialog("Login").WinButton("OK").Click
      Window("Flight Reservation").WinObject("Date of Flight:").Type "090410"
      Window("Flight Reservation").WinComboBox("Fly From:").Select "Frankfurt"
      Window("Flight Reservation").WinComboBox("Fly To:").Select "London"
      Window("Flight Reservation").WinButton("FLIGHT").Click
      Window("Flight Reservation").Dialog("Flights Table").WinList("From").Select "13564 FRA 03:12 PM LON 03:57 PM SR $162.10"
      Window("Flight Reservation").Dialog("Flights Table").WinButton("OK").Click
      Window("Flight Reservation").WinEdit("Name:").Set "Cheers.Lee"
      Window("Flight Reservation").WinButton("Insert Order").Click
      a=Window("Flight Reservation").WinEdit("Order No:").GetROProperty("text")
      do  while  a=""
      wait 1
      a=Window("Flight Reservation").WinEdit("Order No:").GetROProperty("text")
      Loop
      'msgbox a
      Window("Flight Reservation").Close

       当然这块也可以用条件语句:while ...wend; do ... until 来写。
      至此,问题解决OK!对于对象不存在的解决方法,也可以用此方法来解决对象偶尔回放不能识别的问题,再次不再详述.希望本文起到抛砖引玉的作用.
      在编写脚本时,经常要考虑到2个步骤之间的时间间隔问题,例如,1. 打开www.baidu.com2. 输入avepoint。由于网速的不同,打开百度网页之后会有一定的延迟,所以1,2两步之间要有一个短时间的等待,可以通过以下几种方法实现:
      1. 对象的默认等待时。qtp识别对象时,会有一个默认的等待时间,可以在File-->Settings-->Run-->Object synchronization中设置,默认时间是20秒,也就是说当执行到第2步时,网页还没有完全打开,这样的话QTP找不到第2步中需要的对象,那么它会在20秒内不断的尝试查找对象,如果百度这个网页在20秒之内完全打开,那么这个方法就可行(网页全部打开的话,第2步所需的对象就会被找到),如果超过20秒还不行的话
      2. 使用.Sync方法。
      还是打开百度,输入Avepoint,可用如下代码来实现
      Browser("Browser").Navigate http://www.baidu.com
      Browser("Browser").Page("百度").Sync
      Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").Set "Avepoint"
      第2句的意思就是等待百度这个页面全打开,才继续执行下面操作。
  • 摘录QTP识别和操作对象的原理4

    2009-08-06 11:19:19

    窗口中间有选择栏让你选择Run-time Object或者Test Object,
      当你选择Runtime Object时,它显示的就是对象的自身接口(自身的属性和方法)
      当你选择Test Object时,它显示的就是对象的封装接口(封装的属性和方法)
      (注意:GetROProperty访问的是实际对象的封装接口,GetTOProperty访问的是仓库对象的封装接口,
      两者访问的都是对象的封装接口,即Object Spy窗口里选Test Object时显示的属性。
      不要以为GetROProperty访问的是自身接口,即Object Spy窗口里选Run-time Object时显示的属性。
      QTP里的Test Object/Run-time Object的概念太容易让人混淆了!
      它既用来区分仓库对象和实际对象,又用来区分对象的封装接口和自身接口。)
      明白了这些,你还等什么呢?快拿起对象查看器,看看对象都有哪些封装接口和自身接口,肆意的操作它,玩弄它吧!
      比如执行
      JavaDialog("Add NE").JavaEdit("NE Name").object.setVisible(false)
      哈哈,你的JavaEdit对象就当场消失不见了!!!
      你可以拿这个做恶作剧,指着这个窗口逼问开发人员,JavaEdit对象哪去了?
      开发人员肯定瞪大眼睛看着这个窗口,当场翘掉!!!
  • 摘录QTP识别和操作对象的原理3

    2009-08-06 11:18:16

    具体格式如下:
      对实际对象的操作:
      对象.object.自身属性
      对象.object.自身方法()
      对象.GetROProperty("封装属性")
      对象.封装方法()
      对仓库对象的操作:
      对象.GetTOProperty("封装属性")
      对象.GetTOProperties()      ’获取所有封装属性的值
      对象.SetTOProperty("封装属性", "封装属性值")
      比如操作JavaEdit对象,通过QTP封装的封装接口,脚本如下:
      设置JavaEdit的内容:
      JavaDialog("Add NE").JavaEdit("NE Name").Set "NE1"
      读取JavaEdit的内容:
      msgbox JavaDialog("Add NE").JavaEdit("NE Name").GetROProperty("value")
      如果通过JavaEdit的自身接口,脚本如下:
      设置JavaEdit的内容:
      JavaDialog("Add NE").JavaEdit("NE Name").object.setText("NE1")
      读取JavaEdit的内容:
      Msgbox JavaDialog("Add NE").JavaEdit("NE Name").object.getText()
      QTP执行JavaEdit().Set语句时,是通过执行JavaEdit().object.setText()来实现的。
      QTP执行JavaEdit().GetROProperty("value"),是通过执行JavaEdit().object.getText()来实现的。
      JavaEdit对象的封装接口Set()和GetROProperty("value"),是QTP封装JavaEdit对象的自身接口setText()和getText()而得来的。
      对象的封装接口是QTP使用的缺省接口,我们录制出来的脚本都是使用封装接口,大家用的也都是封装接口。
      但是封装接口不如自身接口丰富,因为QTP只是封装了部分常用的自身接口嘛。
      所以我们在需要时,可以绕过封装接口,直接调用对象的自身接口。
      不过有些自身接口不够稳定,在实践中偶尔会出现问题,但是概率很少。
      封装接口有相应功能的话,就尽量用封装接口吧!
      理解了封装接口和自身接口的原理,我们就可以更加灵活的操作对象了。
      但是我们怎么知道对象都有哪些封装接口和自身接口呢?
      其实很简单,用对象查看器(Object Spy)查看对象,在查看窗口里有列出这些接口,包括属性和方法。
  • 摘录QTP识别和操作对象的原理2

    2009-08-06 11:15:16

    我在对象仓库里只设置一个按钮对象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
      另外,QTP还支持脚本描述的方法来定义和访问对象,即不需要在仓库里定义,也能访问和操作实际对象
       如上面两个任务,可以如下实现
      1. 不需要在仓库里定义Check按钮对象,直接用下面脚本来实现测试
      buttonNum = CInt(JavaWindow("Test").JavaEdit("Record Num").GetROProperty("value"))
      For buttonIndex = 0 to buttonNum - 1
      JavaWindow("Test").JavaButton("label:=Check", "index:="+CStr(buttonIndex)).Click
      Next

      2. 不需要在仓库里定义New、Modify、Delete、Check按钮对象,直接用下面脚本来实现测试
      JavaWindow("Test").JavaButton("label:=New").Click
      JavaWindow("Test").JavaButton("label:=Modify").Click
      JavaWindow("Test").JavaButton("label:=Delete").Click
      JavaWindow("Test").JavaButton("label:=Check").Click
      二、QTP操作对象的原理
      QTP为用户提供了两种操作对象的接口,一种就是对象的封装接口,另一种是对象的自身接口。
      对象的自身接口是对象控件本身的接口,只要做过软件开发,使用过控件的人应该很清楚。
      对象的封装接口是QTP为对象封装的另一层接口,它是QTP通过调用对象的自身接口来实现的。
      两种接口的脚本书写格式的差别在于:
      自身接口需要在对象名后面加object再加属性名或方法名,
    封装接口就不用在对象名后面加object。

  • 摘录QTP识别和操作对象的原理1

    2009-08-06 11:06:20

    一、QTP识别对象的原理
      QTP里的对象有两个概念,一个是Test Object(简称TO),一个是Runtime Object(简称RO)。
      这两个概念从字面上不大好理解,也容易混淆。
      但从实际作用上来看,应该说TO就是是仓库文件里定义的仓库对象,RO是被测试软件的实际对象。
      QTP识别对象,一般是要求先在对象仓库文件里定义仓库对象,里面存有实际对象的特征属性的值。
      然后在运行的时候,QTP会根据脚本里的对象名字,在对象仓库里找到对应的仓库对象,
      接着根据仓库对象的特征属性描述,在被测试软件里搜索找到相匹配的实际对象,最后就可以对实际对象进行操作了。
      仓库对象TO一般在录制/编写脚本时加入仓库文件,它不仅可以在录制编写时进行修改,也可以在运行过程中进行动态修改,以匹配实际对象。
      和TO、RO相关的几个函数有:
      GetTOProperty():取得仓库对象的某个属性的值
      GetTOProperties():取得仓库对象的所有属性的值
      SetTOProperty():设置仓库对象的某个属性的值
      GetROProperty():取得实际对象的某个属性的值
      (注:这几个函数访问的都是对象的封装属性,不是对象的自身属性,封装属性和自身属性的区别详见后面第二章QTP操作对象的原理)
      理解了TO的含义,你就可以自由的用SetTOProperty()定义TO,以灵活的操作RO
      比如有个测试任务,窗口上有很多待检查的记录,每条记录右边都有一个Check按钮,用来检查各条记录。
    记录个数不定,所以Check按钮个数也就不定,只有一个Edit显示记录个数。
      我们要对每条记录进行检查,也就是要点击每个Check按钮。
      但是Check按钮个数不定,不好录制,而且个数可能也很多(上百个),即使能一一录制,那也很麻烦。
      那我有一个好办法,只录制一个按钮对象,它设有两个特征属性 label=OK, index=0
      然后用下面的脚本,就可以完成测试
      buttonNum = CInt(JavaWindow("Test").JavaEdit("Record Num").GetROProperty("value"))
      For buttonIndex = 0 to buttonNum - 1
      JavaWindow("Test").JavaButton("Check").SetTOProperty("index", buttonIndex)
      JavaWindow("Test").JavaButton("Check").Click
      Next
      或者窗口上有New、Modify、Delete、Check等好几个按钮,要把这几个按钮一一按过去

  • QTP描述性编程原理介绍2

    2009-08-06 10:54:29

      由上面的叙述我们可以看出来,描述性编程没有严格的要求,只要遵循一个原则:在代码中告诉QTP足够他识别该对象的属性,QTP就可以不通过对象库,而是通过描述性编程的方式完成对指定对象的操作.所以描述性编程没有什么神秘的,他无非是把原来存储在对象库中的信息提到代码中来了而已.

    ------附

    QTP工作原理:

       1.录制的时候,QTP将我们操作过的所有对象都记录下来,保存在对象库object repository中,记录的形式是一个逻辑名加上若干识别属性

       2.运行脚本时,QTP分析该脚本要执行那个对象的操作,然后根据该语句中的逻辑名,在对象库中查找该对象的详细记录,然后在运行的真实披头散发软件中按图索骥,找到需要操作的对象,把语句规定的操作施加在该对象上.施加的主要动作就是把操作的相关消息时间放入到该对象窗口的消息循环队列中

        3.所以,一个完整的脚本测试应该包括两部分,一个是测试脚本的代码,一个是对象库

  • QTP描述性编程原理介绍1

    2009-08-06 10:53:08

    QTP的工作原理有点类似人类社会的某些场景.比如一个朋友委托你带东西给A,如果你认识A,这表明A的容貌特征以及一些联系已经在你脑海有了印象,那么你只要找到了A的住所,那么这个任务就很容易完成了,如果你根本就不认识A,则这个任务就很难完成了.
        那在QTP中有没有一种方法,无须在对象库中记录任何关于某个对象的信息,就可以完成对该对象的操作呢,有.那就是描述性编程,其工作原理就象上面这个例子.

        在QTP中,有一按钮对象,对它的操作如下:

        Dialog("Login").WinButton("OK").Click

        但是如果我们在对象库中删除这个对象后,执行这句话就会出错,提示找不到对象,在这个时候,我们就可以通过描述性编程给他指定对象及其他的一些属性,修改如下

        Dialog("Login").WinButton("text:=OK").Click

        上面脚本中,通过WinButton("text:=OK")明确告诉QTP去寻找文本属性为OK的按钮,于是QTP正确识别到该对象,顺利的执行了脚本

        这种不需要在对象库中存储对象的信息,就可以执行对象操作的方法,就是QTP中比较高级的用法:描述性编程(descrīptive progamming).描述性编程和传统的QTP脚本的区别是:他把需要识别的对象的属性从对象库中转移到了脚本里面,通过在脚本里面的特殊语法格式.来告诉QTP识别对象的方法.描述性编程更加灵活,因为他不需要经过录制这个步骤,可以直接通过编程的方式操作任何一个你想操作的对象,只要你在测试脚本代码里提供给QTP识别该对象的足够信息

        描述性编程的语法格式如下:

        micClasas("property1:=value1","property2:=value2")

        micClass标志某个对象的类别,括号里面通过jproperty:=value的形式告诉QTP识别该对象的必要属性.我们继续修改一下测试脚本:

        Dialog("Login").WinButton("text:=OK").Click

        修改后:

        Dialog("Login").WinButton("nativeclass:=Button","text:=OK").Click

        F5执行,结果运行顺利.这次修改,我们使用了一个通用的对象类WinObject,而把按钮当作一个基本属性nativeclass:=Button,同样可以完成对该按钮的操作

  • 摘录QTP的学习历程4

    2009-08-06 10:50:57

    问题六,解决办法有4个:
        1、测试的时候,让程序员把这块限制去掉,免去验证这关。
        2、让程序员提供一个万能验证码,测试可以绕过这一关。
        3、请程序员提供识别的方法,从获取的图片读出验证数据,再传给QTP。
        4、进行位图检查,将验证码分段进行图像验证。
        实际上,验证码的目的就是防止用程序灌水或机器录入信息。所以有点为难我们测试了。
    方法1,如果程序已在发布并有客户使用,危险性是可想而知的。方法2虽然可以解决验证这一关,但跳过了输入码与验证码一致性问题。方法3就需要程序员配合了,可能就需要调用DLL了。方法4却将图像分段,把获取的图像和已经的图像进行比对,比对通过取对应的值;这个在数字验证会好做一点,因为最多就四个图像的比对。
        关于网上的汉字验证码,那块的测试我就不知道他们是怎么做的了。真想了解一下! 
     
        以上就是我对过去QTP学习过程的一个总结。供天下各界朋友参观、发言、讨论,也是对我过去的一个写照,可能N年后,自己看到会很有感觉呢  。
        现在又有项目来了,我学习的时间慢慢也少了。新项目里融合了C++程序,QTP对C++的识别似乎很不理想,也许是需要插件支持吧。过程中我尝试了Rational的Robot,Robot对C++的识别很好,但Rational一套组件内容太多,对汉字的支持似乎也不是很好。用了一段时间我就把它从硬盘中给清掉了…… 
        QTP的学习就在此停住了,不能应用到项目中,单纯看着说明书的学习,我好像不太在行。  也许是真的需要活学活用,边学边用吧。或者我不够书呆子吧……
  • 摘录QTP的学习历程3

    2009-08-06 10:50:27

    问题四的解决过程:
         当我开始改代码时,定义一个动作,然后可以生成N个动作。假设N个动作产生了N个结果,你要对这结果进行处理时,你会发现这N个结果都不能被识别:

    网页上有个表格,是往数据库里加数据的。
    两个表格显示在同一个页面上,左边为父表,右边为子表。
    点击左表,右表显示其子项目。
    结构如下: 
    A
    ├─1
    ├─2
    ├─3
    └─4
    B
    ├─1
    ├─2
    ├─3
    └─4
                        ……
    思想很清晰:
    添加一个父项A、选中此父项A、对其添加子项1、2、3、4
    添加一个父项B、选中此父项B、对其添加子项1、2、3、4  ……

    代码也很简单:
    dim M          '定义父项数
    dim N          '定义每个父项包含的子项数

    For i=1 to M
          Call 添加父项( i )       
          选中父项( i )              '问题就出在这里 
       For j=1 to bwfl step 1
           Call 添加子项( j )
        Next       
    Next

    现在问题出来了,思路应该没有问题(除非这方法真的行不通),循环也是顺着思想来的。

    问题是,无法实现选中的父项(最多识别到一个)。
    由于此循环可以在录制过程进行,如果不改变变量名称,循环可且只可以成功运行一次。问题是这个名称都是从DataTable里获取的。
    因为,在运行过程中生成的项目没有加到对象库中,无法被识别。

       这个问题最后是从思想上解决的。答案是我做的是功能测试,为什么不先加父项,检查父项的功能是否正常,然后再去测子项的功能。不去改变名字,因为那没有必要。核心答案“功能测试、测试功能”。即对测试工具首先需要有正确的认识。
       当然,这个问题可以用代码去实现,但那需要有一定的编程功底且耗时,可维护性不一定好。有需要的朋友可以去试一下,然后把你的经验也共享一下。问题五,是对QTP很大的一个扩充。 
        对于QTP调用外部DLL的功能,由于我的编程功底不够,没有相关人士配合我,我只能望之垂涎了!
        如果能调用外部DLL的话,QTP的功能就可以变得很强大。自己写的程序,自己编一些过程用QTP进行测试,我想“后果很严重”  。真想有一次给我尝试的机会……

  • 摘录QTP的学习历程2

    2009-08-06 10:49:41

    问题一,解决办法有三种:
       1、更改QTP自身对某控件的识别方式,在 tools——Object Identification 中。在这里列出了所有QTP能识别的控件,以及控件的识别方式。你可以给他添加X、Y坐标进行识别。或更明显的,列表中的信息,不按名称识别,而是按ID识别。这个修改可以解决一些问题,具体的赶紧动手试试吧……
       2、使用虚拟物件,来定义一个控件,在 tools——Virtual Object 中。在这里可以自定义一个控件。例如在ASP的程序中,程序出错,在客户端的表现形式大部分是一样的,你可以把整个错误页面当成一个控件来识别(感觉不错)。如果加一个判断,出错后你想做什么就由你自己定了。
       3、使用低级录制或鼠标录制。用 Test——LowLevelRecording/AnlogRecording 吧,用它录制就不需要什么设置了,他会记录你的程序控件相对屏幕的位置。用LowLevelRecording还有代码可改,用AnlogRecording动作就被封装了(维护性极差)。两者因实际环境更取其长吧……

    问题二的解决过程:
    关于弹出提示的问题,我当时需要情况是这样的。一个信息录入系统,由于数据量很大,查询需要一段时间。QTP回放时动作比较快,点了保存,程序还没反应过来它就进行了下一步操作。这时的操作就和录制时不一样了,程序给出一个提示,但这个提示是录制过程没有的。弹出框是一般都是POP形势(至上)的,导致QTP无法继续回放,结果就是回放失败。 
    解决办法有两个:
            1、进行判断,当出现这个提示时,点是/否/取消按钮。
            2、通过 Tools——Recorvery Scenario Manager 设置默认操作。
        我最初就是用的第一种方法。写一个函数判断是否出现这个提示,如果出现就点“取消”然后wait(2)。    每个可能出现弹出框的动作后都调用一次这个函数。虽然可以解决这个问题,但回放的效率就低了,而且需要你预知提示框的信息。
        当我知道了第二种方法,显然更科学^_^。它可以对所有预知甚至不知的提示进行指定的操作。
        实际上,当程序出现了未预知的提示时,可能就是程序的BUG,所以使用上述办法解决工具问题时,也要考虑是否会掩盖程序的缺陷。

    问题三的解决办法:
          用好QTP后,会不自觉的和TD关联起来。但从TD直接启动QTP时,程序只会加载QTP自带的插件,如果你安装了其它插件(如.net、java、etc.),默认是不加载的。这会导致上传的脚本无法正确执行。解决办法很简单,去 Test——Setting里进行Modify 吧。从本地打开的脚本,这里不能进行Modify的。所以办法很简单,但如果不知道的话就很难了。当初为这个问题我可是废了八牛三虎之力呢……

  • 摘录QTP的学习历程1

    2009-08-06 10:47:53

    对于我来说,学习QTP是一个漫长而有艰苦的过程  。首先我不是计算机及相关专业毕业的(医学相关)。跳入测试部时,我正在接受程序员的培训课程。由于自己认为需要,于是开始学习QTP。
        刚开始使用QTP,就一直对着说明书,不停的“订飞机票”(订飞机票是说明书里的一个例子)。学会了一个步骤就拿到公司产品上玩玩,回忆起来还是挺有趣的。

       当我用一些简单的功能开始录制脚本时,发现保存ActiveXScreen的话,生成的脚本很中空间(因为程序会保存每个不同的录制页面),多录一些硬盘空间就满了,而且回放过程会很慢。  但如果不保存活动页(ActiveXScreen),对脚本的再改造/维护起来就相对困难一些。

       于是我开始去了解“关键字”视图里的内容,尝试了解代码。慢慢的,我了解到“关键字”视图显示了整个操作步骤,第个组件相对于程序里一个元素。同时还记录了录制过程对该元素的操作和结果。

        然后我又开始在论坛在找些资料看看,从有点所谓的高级应用中,我发现脚本的维护并不一定要有“活动页”。实际是QTP所有对象的识别,都存在脚本的一个对象库里了。QTP经常出现无法识别对象的问题,可以从这里着头修改。 
       为了减少QTP脚本占用空间大、录制慢的问题。我查阅了一些资料,可以在设置中进行修改,让脚本中不保存活动控件(ActiveX)或仅保存出错时的录制页面。干脆,我就从此录制页面了。所有的调试都从“关键字”视图和“专家”视图中进行修改。而且关于对象库,QTP也有个选项,可以设置加载页面上所有的对象,我修改成只保存页面上录制过程使用的对象。  这样,脚本的容量问题就解决了,录制后的脚本会比以前小很多,来了个彻底的瘦身。关于录制速度的问题,和保存“活动页”、动态脚本也有一定的关系,另外可以减小启动的加载项(如:去掉VB插件、.net插件,不需要的就不加进来)。这样的脚本上传到TestDirector上,或从TestDirector上调用就不会太慢了。

       然而真正的问题,棘手的问题就不是上面所述的那么简单了。不过都是有办法解决了的,嘿嘿……
       以下是我经常遇到的问题:
           一、无法识别控件。
           二、错误回放过程未知弹出窗口。
           三、加载.net插件后和TD的关联问题。
           四、动态加载元素的识别问题。
           五、调用外部dll的问题。
           六、随机验证码的问题。

  • QTP index和creationgtime熟悉总结

    2009-07-23 09:31:45


    总结1:
       Index和CreationTime属性的特点是一样的,唯一不同的地方史,index一般用来表示页面中的对象,元素的先后创建,CreationTime只用来表达浏览器(还有其他的window)相对于QTP启动时间上的顺序关系.
    总结2:
       index是一个辅助识别属性
    (有时可以没有"在已经唯一标识一个对象的情况下"有时又必须"某些对象什么属性都相同")
    这就决定了在"相同描述的对象"出现多个的情况下就一定有index,在一个对象现有"描述属性"已经能唯一标识一个对象的情况下,index是不会出现的.
    比如"性别=男"这个"描述属性"在"全家"里因为有多个,所以就一定要Index来辅助描述.
    那么"称呼=爸爸"这个"描述属性"在"全家"里只有1个,所以我们说"爸爸"就马上知道是谁
    总结3:
       index在对象是唯一的情况下,没有任何意义和价值
    也就是说,只要这个对象在这个页面中确实是唯一的,那么无论你的index是什么值都能够正确识别这个对象
    比如当前页面中只有一个叫"风景"的图片,那么这个"风景"图片在任何index属性下都能正确识别
    总结4:
       当index,CreationTime属性在对象库中为none的时候,不能使用SetTOProperty赋值index属性,
    这个现象的原因目前还不明,不过现象是赋值能够成功,
    但是你无法使用赋值后index属性来正确识别你想像中的对象.
    总结5:
       index属性是QTP自己标识的.和程序编程里的index无关.
    学过编程的人,容易带入编程里面的概念,然而在QTP中,index属性是QTP自动生成的,和程序编程的时候使用的index是没有任何关系的,
    index属性的生成是按照相同对象出现的顺序来排列的,就是你用ChildObjects方法获得的对象集合中item(i)索引的顺序.
  • qtp

    2009-07-15 15:40:09

Open Toolbar