发布新日志

  • QTP描述性编程

    2008-06-18 16:09:23

    例1:获取单元格中的值
    thisText = Browser(…).Page(…).Frame.(…).WebTable("sample").GetCellData(2,1)
    例2:获取图片的名称
    ObjectName = Browser(…).Page(…).Image("Find").GetProperty("Name")
    例3:检查某个对象是否存在,如果存在弹出对话框说明对象存在。
    If Browser("Browser").Page("Page").Applet("login.html").JavaEdit("username").Exist Then
    MsgBox("The object exists.")
    End if
    例4:描述性编程(descrīptive programming)
    1、descrīptive programming概述
    通常情况下,当在录制一个操作时,QTP会将被操作对象加入到对象库里(Object Repository)。一旦对象存在于对象库里,我们就可以在专家视图里通过添加相关的对象方法来对该对象进行操作。我们可以通过引用层次型对象库里的对象描述(Object Descrīption)来添加相应的方法。
    因为QTP对象库中的每个对象都具有唯一名称,所以在引用时对象名是必须需要指定的。然后在测试运行期间,QTP在对象库中根据这个对象的名称和父对象来查找对象,并使用为这个测试对象存储的测试对象描述,在网站或应用程序中标识该对象。
    例如我们用QTP录制Yahoo Mail登录情况时我们需要输入用户名,于是在录制时我们就会录下一个WebEdit对象,它的缺省逻辑名为“login”,该编辑字段位于名为“Yahoo! Mail - The best” 的页面上,并且该页面在浏览器中使用名称Yahoo!进行录制。如图所示,即为录制时的对象库的内容:


     
    那么如果我们想要应用该对象,就可以在专家视图输入以下信息:
    Browser("Yahoo!").Page("Yahoo! Mail - The best").WebEdit("login").Set “xxx”
    或者我们也可以调用一些方法,获取改对象在运行时的对象名,如:
    Browser("Yahoo!").Page("Yahoo! Mail - The best").WebEdit("login").GetROProperty(“name”)
    然而,我们可以发觉到,上面的例子在处理对象时,对象已经存在于对象库里,因此我们可以应用这个对象的逻辑名。实际使用中,情况往往并非如此简单,我们经常会遇到很多在页面上动态产生的对象,换而言之,对象库里没有这些对象,我们也无从引用。因此我们必须采用其他的技术来完成这类操作,这也就是我们需要讲解的Descrīptive Programming。
    为了满足上面提到的动态对象的处理问题,QTP允许用户通过将对象属性编码到测试脚本里来动态识别对象,这就是我们通常意义下称为的Descrīptive Programming。通过这种方式,我们可以指示QTP不通过引用对象库和对象名来对实际对象进行操作。具体操作中,我们只需要为QTP提供对象的一组属性和值,这样QTP就可以来识别相应的对象并对其进行操作。这相当于,告诉QTP要识别对象的一些关键特征,根据这些特征QTP就可以一一匹配然后识别出来这个对象。
    而且,更为重要的是,通过这种Descrīptive Programming的方式,还可以让QTP识别具有某些相同属性的对象。我们先来举个例子来看一下:我们假设当前的Windows系统中打开了若干的Yahoo主页面(多于一个),现在我们要关闭所有的正在浏览Yahoo主页面的浏览器。
    对于上面那个例子来说,我们先看一个简单一点的情况,假设只有且仅有一个Yahoo主页面:那么我们可以用下面的方法来
    Window("Text:=Yahoo! - Microsoft Internet Explorer").Close
    我们可以看到语句里我们要查找的对象是Window窗口标题为“Yahoo! - Microsoft Internet Explorer”,然后把它关闭,具体的语法说明我们稍后为解释。但是上面的语句仅仅适合前面提到的条件“只有且仅有一个Yahoo主页面”,如果有多个同样的窗口就会出错,原因是通过语句可以匹配到多个对象,而QTP不知道应该对哪个对象进行关闭动作。我们需要进一步的缩小匹配范围:
    Dim i
    i = 0
    while (Window("Text:="Yahoo!" - Microsoft Internet Explorer", "index:="&i).exist)
    Window("Text:=Yahoo! - Microsoft Internet Explorer", "index:="&i).close
    i = i +1
    wend
    这里我们可以看到,对于具有相同属性的对象,我们可以通过index参数来对其进行区别,第一个对象为index=0,第二个为index=1等等,依次类推。当然我们还可以通过CreationTime和Location参数来定位对象,这里就不详细叙述了。
    通过上面的例子,我们对Descrīptive Programming有一个基本了解了,下面我们详细讲解一下Descrīptive Programming:在具体实现中,我们有两种类型的Descrīptive Programming方法。可以列出直接在测试语句中描述对象的属性和值的集合;或者向Descrīption 对象中添加属性和值的集合,然后在语句中输入Descrīption 对象的名称。下面我们分别举例介绍。
    2、直接在语句中输入编程描述
    通过多个指定描述对象的property:=value对,可以直接在语句中描述对象,这是最直接有效的方法。
    常规语法为:
    TestObject("PropertyName1:=PropertyValue1", "..." , "PropertyNameX:="PropertyValueX""}
    TestObject - 测试对象的类。
    PropertyName:=PropertyValue - 测试对象的属性及其值。各个property:="value" 对之间应用逗号和引号分开。
    例如:以下语句指定Mercury Tours 页面中名为author且索引值为3 的WebEdit 测试对象。当测试运行时,QTP 将查找具有匹配属性值的WebEdit 对象,并输入文本jojo。
    Browser("Mercury Tours").Page("Mercury Tours").WebEdit("Name:="Author"", "Index:="3"").Set "Mark Twain"
    我们也可以从从描述中的特定位置(从Page 对象描述开始)开始使用Descrīptive Programming。
    Browser("Mercury Tours").Page("Title:="Mercury" Tours").WebEdit("Name:="Author"", "Index:="3"").Set "jojo"
    此外,如果我们希望在在一个测试或组件中多次使用相同的Descrīptive Programming,则可以将创建的对象赋值给变量,这样使用会方便很多。
    例如:我们需要完成下面一系列操作
    Window("Text:=HyperSna").WinButton("Caption:=日期").Click
    Window("Text:=HyperSna").WinButton("Caption:=时间").Click
    Window("Text:=HyperSna").WinButton("Caption:=确定").Click
    那么,为了方便其见,我们可以将Window("Text:=HyperSna")赋值到一个变量,然后再使用,参见下面的代码:
    Set WinHyper = Window("Text:="HyperSna"")
    WinHyper.WinButton("Caption:=日期").Click
    WinHyper.WinButton("Caption:=时间").Click
    WinHyper.WinButton("Caption:=确定").Click
    如果使用了VBscrīpt里面的With语句,还可以简化为以下代码:
    With Window("Text:="HyperSna"")
    .WinButton("Caption:=日期").Click
    .WinButton("Caption:=时间").Click
    .WinButton("Caption:=确定").Click
    End With
    下面我们来看一个更为详细的例子,在QTP产品缺省安装里面自带了一个网上订机票的示例称为Mercury Tour,我们看一下在订票过程中何时需要用Descrīptive Programming。
    首先登入系统后,如果需要订票,就要先搜索航班,此时系统要求输入订票乘客的数量,假设我们在第一次录制脚本时选择了1个Passenger,并成功完成订票。然后,我们需要参数化乘客数量来测试订票系统,我们会发现回放会失败。原因在于,不同的乘客的数量导致在订票时需要输入每个乘客的姓名,而录制时,只输入了一个乘客的姓名。而乘客姓名的输入框是随着乘客数量的变化而动态生成的,我们不可能从对象库里得到没有录制的对象,因此必须使用Descrīptive Programming。


     
    在录制单个乘客时,我们得到的录制语句是:
    Browser("Welcome: Mercury Tours").Page("Book a Flight: Mercury").WebEdit("passFirst0").Set "Michael"
    Browser("Welcome: Mercury Tours").Page("Book a Flight: Mercury").WebEdit("passLast0").Set "Wang"
    显然WebEdit("passFirst0")和WebEdit("passLast0")是录制时产生的对象并存放到对象库里的。通过对象库,我们可以看到对象的属性如下


     
    系统对于发生多个FirstName时,命名规则是passFirst0,passFirst1…依次类推。因此只要通过简单的Descrīptive Programming就可以完成动态FirstName与LastName的识别工作。这里我们假设参数化的乘客数已经赋值给intPassNum,下面是脚本中的关键语句:
    counter = 0
    For i = 0 to (intPassNum)
    Browser("Find a Flight:").Page("Book a Flight:").WebEdit("name:="passFirst""&i).Set "Michael"
    Browser("Find a Flight:").Page("Book a Flight:").WebEdit("name:="passLast""&i).Set "Wang"
    counter = counter + 1
    Next
    3、使用descrīption对象
    使用Descrīption 对象可以返回包含一组Property 对象的Properties 集合对象。Property 对象由属性名和值组成。然后,可以在语句中指定用返回的Properties 集合代替对象名。(每个property 对象都包含一个属性名和值)。
    要创建Properties 集合,可以使用以下语法输入Descrīption.Create 语句:
    Set MyDescrīption = Descrīption.Create()
    创建Properties 对象(例如,以上示例中的MyDescrīption)后,就可以输入语句,以便在运行会话期间在Properties 对象中添加、编辑、删除或检索属性和值。这样,就可以在运行会话期间,使用动态方法确定哪个属性以及多少个属性应包含在对象描述中。
    在Properties 集合中填充一组Property 对象(属性和值)后,可以在测试语句中指定用Properties 对象代替对象名。
    例如,假设我们需要完成以下一个操作:
    Window("Error").WinButton("text:=OK", "index:="1"").Click
    我们可以通过Descrīption对象来实现同样的功能,参加下面的代码:
    Set MyDescrīption = Descrīption.Create()
    MyDescrīption("text").Value = "OK"
    MyDescrīption("index").Value = 1
    Window("Error").WinButton(MyDescrīption).Click
    Set MyDescrīption = Nothing
    【小结】以上是对QTP中有关处理动态对象中的Descrīptive Programming的简单介绍,希望对大家能够有所帮助,就总体而言,如果能够熟练掌握Descrīptive Programming,那么有很多实际中的问题就可以迎刃而解。当然Descrīptive Programming只是QTP中的一个功能,QTP在实际功能测试中还有很多强大的功能,作为QTP学习的一个系列有机会我会一一介绍。

  • 使用QTP9.0的一点心得——对象仓库

    2008-06-18 15:59:42

    QTP9.0的大部分功能与QTP8.2没什么区别,使用后最大的感受是对象仓库的功能增强了,不光有对象仓库窗口,还增加了对象仓库管理窗口、连接对象仓库窗口。

            
    我们知道对象仓库模式可分为每个对象库和共享对象库两类,在QTP8.2中,新建的测试默认情况下使用每个对象库,要使用共享对象库的话,应按如下方法进行设置:

            Ø   
    选择测试”——>“设置”——>“资源选项卡。

            Ø   
    对象库类型区域,选择共享

            Ø   
    请指定要用作对象库的共享对象库文件。要指定文件,请输入对象库文件名,或单击浏览按钮并从打开对话框中选择资源文件。要新建共享对象库文件,请在共享框中输入新文件名。

            Ø   
    对象库文件的默认文件扩展名是 .tsr,但是文件可以使用任何扩展名。在打开对话框中浏览现有对象库文件时,在文件类型框中选择所有文件

            Ø     
    注:请在新测试开始录制前进行设置,已有测试的对象库模式不能进行修改。




            
    QTP9.0中,对象仓库的使用相对灵活,每个action录制产生的对象都是存放在本地对象仓库中的,在对象仓库窗口(Resources...-> Object Repository...)中进行导出(File->Export Local Objects...)操作,可生成共享对象库,默认文件扩展名是 .tsr

            
    共享对象库的使用:打开连接对象仓库窗口(Resources...->Associate Repository...),选择共享对象库文件,然后进行连接。

            
    将某一action本地对象仓库的对象加入到共享对象库中的方法:

    方法一:

            Ø   
    先将该action与共享对象库连接,然后进行录制

            Ø   
    保存后关闭该测试文件

            Ø   
    打开对象仓库管理窗口(Resources...-> Object Repository Manager...)

            Ø   
    打开共享对象库文件
    (File->Open->*.tsr)

            Ø   
    从本地对象库进行更新 (Tools->Updated from Local Repository...),选择刚才的测试文件及要更新的action,更新(Update All->Save


    方法二:

            Ø   
    将该action本地对象仓库的对象也导出成一个共享对象库文件

            Ø   
    打开对象仓库管理窗口(Resources...-> Object Repository Manager...)

            Ø   
    将两个共享对象库文件进行整和(Tools-> Object Repository Merge Tool…),保存为另一个共享对象库文件。




            
    QTP9.0中,还可以在对象仓库中更新对象的属性,如果用来识别对象的属性在添加到对象仓库以后被改变了,QTP在回放脚本的过程中就无法识别这一对象,会导致出错。使用更新应用中对象这一方法,可以重新定义这些属性,使对象能被识别,所以非常有用。具体操作如下:

            Ø   
    打开对象仓库管理窗口(Resources...-> Object Repository Manager...)

            Ø   
    选择要更新的对象


            Ø   
    选择更新应用中对象Object > Update from Application)或工具栏上的

            Ø   
    在应用中找到该对象并点击它,选择与对象仓库中相同类的对象


            
    QTP中,对象识别是其核心的技术,正确识别到对象是保证自动化测试脚本成功运行的关键,QTP9.0中强大的对象仓库处理技术将给对象的识别、管理和使用带来很大的便利。

  • QTP精华问题

    2007-10-17 15:56:40

    QTP问与答

    1.Q:runaction 后面能不能接变量(动态调用action,所以从数据库取数据做action名字了,但是调用总是找不到)?  
      A:脚本中原有RunAction "testbase [case1]", oneIteration
        把引号中的内容放到Global表中的第22行,然后将代码修改为:
        datatable.getsheet("Global")
        datatable.setcurrentrow(22)

        strLogin=DataTable("ActionName","Global")
        RunAction strLogin, oneIteration
       
        help中也有相关帮助
        如:
        Syntax
        RunAction ActionName, [IterationMode , IterationRange , Parameters]
        ActionName : String : The name of the action



    2.Q:QTP8.2 中调用VB函数的问题(用VBscrīpt写了一些测试脚本需要的几个通用函数,有没有办法可以用类似include的方式进行调用,而不需要每次都把这些函数Copy到新的脚本中)?
      A:程序开头加上ExecuteFile "..\..\..\project\DeVariable.vbs"



    3.Q:QTP 如何做回归测试(300多个TestCase,TD是否可以管理) ?
      A:TD可以实现,可以生成测试集,一个测试集可以包含若干个测试脚本
        QTP8.2本身提供一个工具Test Batch Runner但是运行完没有报告。
        MI有另一个工具叫MTM(multitestmanager)



    4.Q:qtp 自动节图功能

    A: 具体可参考此帖:[url]http://www.51testing.com/cgi-bin[/url] ... d=17663&fpage=1



    5.Q: 在QTP中如何设置使用别的浏览器(XP系统,用IE访问程序时,每次总提示屏蔽安装ActiveX插件,需要手动安装.但把这个过程录制到QTP后,回放一次是成功的。当我给某个输入框参数化了好多数据后,回放过程中,某些就会失败.
        可能有两个方面可以解决这问题1、每个动作设置延迟时间 2、设置为用别的浏览器。)
        (失败的提示信息是  object not visible)
      A:1.延迟可用WAIT X(X单位是秒)
        2.可以安装插件添加新的浏览器
           SystemUtil.Run "file” "params" "dir" "op'' "mode"
           QTP运行可执行文件的方法及其参数
         ps: 建议是用IE浏览器,或者IE内核浏览器做测试



    6.Q:checkpoint 检查网页,是否能实现只要网页出现乱码就返回错误报告?
      A:Text not displayed能解决问题
        关于 Text Checkpoint 的总结。
        1)Text Checkpoint 的检查部分分为三个部分。Checked Text 、Text Before 、Text After。在默认的情况下,Checked Text执行的是精确检查,其余两个部分执行的是模糊检查。Text Before(After)检查的内容可以比实际的内容少。但是不能有和是实际内容不相符的地方,否则就失败。
        2) Exact match选项。如果选择了这个选项,三部分完全都进行精确检查。个人觉得和只检查checked Text部分没有区别。
        3) Text not displayed。这个选项本质上就是一个结果取反的过程。就是把检查的结果给反过来,把pass变成Fail,Fail变成pass。我觉得这样就很容易理解。



    7.Q:WSH 的应用方法
      A:WSH 实际上是一个脚本语言的运行环境,它之所以具备强大的功能,是在于其充分挖掘了脚本语言的潜力。因此,如果抛开脚本语言而空谈 WSH ,那实际上就没有了意义。而如果再展开来讲述脚本语言,显然就离开了今天的主题。

    在这种情况下,只好采取一种折衷的方法:给大家推荐几个脚本文件利用 WSH 执行任务的实例,希望大家能通过这些例子对 WSH 的使用有一个初步的认识。

      脚本文件的编写十分方便,你可以选用任意一个文字编辑软件进行编写,编写完成后,只需将它保存为 WSH 所支持的文件名就可以了(如.js 文件和.vbs 文件)。最常用的就是记事本编辑器,下面的实例都是以它作为工具编写的。

    打开记事本编辑器,在上面编写如下内容:
      Wscrīpt.Echo("走近 WSH")
      将它保存为以 .vbs 或 .js 为后缀名(千万不要写成了 .txt)的文件并退出记事本。双击执行这个文件。
      这一次,我们要利用 WSH 完成一次创建十个文件夹的工作。代码如下:
      dim objdir
      set ōbjdir=wscrīpt.createobject("scrīpting.filesystemobject")
      for k=1 to 10
      anewfolder="c:\chapter" & k
      objdir.createfolder(anewfolder)
      next

    同样,将它存为 .vbs 文件并退出。运行后,我们会发现,C 盘根目录下一次性多出了十个新文件夹。

        最后,再举一个在服务器上的运用。下面的代码将帮助你重新启动指定的 IIS 服务:  ' define a constant for stopped services
      Const ADS_SERVICE_STOPPED = 1

    ' get an ADSI object for a computer
      Set ōbjComputer = GetObject("WinNT://MYCOMPUTER,computer")

    ' get an object for a service
      Set ōbjService = objComputer.GetObject("Service","MYSERVICE")

    ' check to see if the service is stopped
      If (objService.Status = ADS_SERVICE_STOPPED) Then

    ' if the service is stopped, then start it
      objService.Start

      End If

    将它以 startsvc.vbs 为名保存在 C: 盘根目录。并通过如下命令执行:Cscrīpt C:\STARTSVC.VBS。运行后,经你指定的 IIS 服务项将被重新开启。

    其实,在 Windows 的 samples 目录下,有个 WSH 文件夹,那里面有不少很具代表性的 .vbs 和. js 脚本文件。

    此外,利用 WSH 还可以自己编写脚本文件来提高网络管理方面的效率。


    8.Q; 从 EXCEL 中导出数据进行测试

    datatable.AddSheet("51sheet")
    datatable.ImportSheet "f:\test.xls","testsheet","51sheet"

    Dim i,RowCount ' 定义两个变量
    i=0
    RowCount=datatable.GetSheet("51sheet").GetRowCount ' 设置 RowCount 等于 51sheet 中的行数。
    msgbox RowCount
    Do while i<rowcount
    i=i+1 ' 第一次进入循环,执行这句后, i=1
    'datatable.getsheet("51sheet").setcurrentrow(i)   这句话被我注释掉了,正确的写法应该是下面这样,分开写。

    datatable.getsheet("51sheet")
    datatable.setcurrentrow(i)

    ' 执行过上面两句后, CurrentRow 是第一行。

    tempData=DataTable.GetSheet("51sheet").GetParameter("Name").Value
                      
    ' 现在,我们调用 msgbox 看看下面这种调用方法得到的是什么值?没错,是第一行的值,下一次循环呢?
    ' 得到的是第二行的值么?
    msgbox "GetParameter-Name:"&tempData ' 这里弹出我们要看的值。
    ' 下面我们用另外一种方法来得到。
    msgbox "GetParameter-i:"&DataTable.GetSheet("51sheet").GetParameter(1).Value ' 这里我用 GetParameter(1) 去得到 sheet 中第一列的值。
    loop



    9.Q: 关于 dtGlobalsheet 与 dtGlobalsheet

    1) dtGlobalsheet 只有一个,它的 index 值比较特殊,它有两个 index 值,一个是 1 还有一个是内置的默认的 1000 。
    你可以用 1 或者 1000 去引用它都是正确的。当然了,如果你用 dtGlobalsheet 来引用它也是正确的。这个 sheet 的 Name 叫做 "Global" 。注意: SheetName 是区分大小写的。
    2) dtLocalsheet 可以用 index:1001 来引用,当然,也可以用 2 来引用。至于其它自定义的 sheet 嘛,你就只能用 index:3 来引用了。
    它没有内置的默认的类似前两个那样的 index 值。
    3) datatable 这个对象只有一个。就是所有 sheet 的集合。或许你把它理解为 excel 文件比较好。
    dtsheet 呢?就是其中的每个 sheet 。所不同的就是 MI 为他们做了一些默认值。在我们的应用中,可能会有多个 action, 如: actiion1,actiion2,actiion3
    这些 action 也分别对应有各自默认的 LoaclSheet. 即: actiion1 , actiion2 , actiion3 。

    如果每个 action 中,我们都只用到一个 sheet ,那就好办了,在每个 action 中都可以用 localsheet 来引用,但是如果我们有两个及两个以上的 sheet. 那么就比较容易乱套了。



    10.Q: 移动当前位置的行

    For i=1  to 3
    datatable.getsheet("Global")
    datatable.setcurrentrow(i)
    DataTable("C","Global") = DataTable("nodename","Global") ‘把表Global中的nodename字段中的内容取出来。
    Next



    11.Q: 如何能记录到页面的校验码?(Output value能不能得到web页面的校验码,一般的校验码是由图片随即生成的 ,用QTP怎么录脚本在登陆前得到校验码并输入到校验码一栏)
       A:1)一个很简单的方法:测试时叫开发屏蔽掉检验码的功能后,再录制脚本。检验码的功能可以手工很简单测试出来。
         2)想得到图片的校验码,唯一的方法就是跟程序员拿程序,然后自己在脚本里面写FUCNTION!
            其它就要手动输入了!



    12.Q:QTP 正则表达式的帮助
       A:见附件word文档

    附件: QTP regular expression usage.doc (2005-9-8 18:32, 26.5 K)



    13. 自动测试实施计划
       1)分析实施自动化测试可能存在的风险:就是决定是否实施, 用成本 时间 效果 。。
       2)制定实施的时机:也就是在什么阶段
       3)研究所要测试的功能 性能
       4)分析在测试中可能遇到的问题 和困难
       5)预估所需要的人时和相应的硬件
       7)确定负责人员和相关测试人员
       6)制定详细的测试计划 方案
       7)最后是执行计划



    14.Q: 一个Action里如何调用在另一个Action中定义的函数、过程(或变量、常量)
       例如:
       -----------------------------------
       'Action_A
         Public strURL   
            ...... ......
        Function QueryList()
            ...... ......
            ...... ......  
        End Function
       ------------------------------------
       'Action_B
       '如何调用 QueryList函数和strURL
       A:1)可以把这些变量和Function放在vbs文件作为resource文件共享,在每个Action中添加该文件.         

    如果function中出现控件调用,那么必须确保该控件在相应的Action的object repository中是存在的.
      2)定义一个可被调用的ACTION里面唯一的放一个FUNCTION

    wing1799 2007-10-3 15:17

    15.Q: 如何管理QTP的源代码?(QTP生成的源代码比较多,而且和环境控件都有关,假如需要多人同时开发, 请问如何管理源代码?)
       A: 一个是代码你可以通过vss,cvs等来进行管理
         一个是通过td或者qc的基于用例的代码管理      

    其实第一种方法是基于版本控制来进行的,第二种方法是基于用例管理进行的
         角度不同,管理方法也不同,不过团队协作需要的大家分工明确,进度控制。代码管理可以借鉴开发的方法。



    16:Q: 脚本不能回放,IE中的AtiveX设置有问题??
       A: TOOL---OPTIONS----Ative screen
         然后点开advanced..,把LOAD  ACTIVEX CONTROLS打勾
         TOOL---OPTIONS----Ative screen
         然后点开advanced..,run scrīpts-->disabled!



    17 .Q: 如何参数化link

    Browser("Browser").Page("Page").Sync
    Browser("Browser").Navigate "http://www.51testing.com/cgi-bin/index.php"
    Browser("Browser").Page("51Testing 软件测试论坛---软件测试,软件质量工程师").Sync

    Set tags=Browser("Browser").Page("51Testing软件测试论坛---软件测试,软件质量工程师").Object.links
    Dim i,j, arr()
    i=0
    For Each element in tags
        If Ucase(element.tagname)="A" and left(element.InnerText,1)="[" Then
                            ReDim Preserve arr(i+1)
                        arr(i)=element.InnerText
        i=i+1
            end if
    Next



    For j=0 to i
                            Browser("Browser").Page("51Testing软件测试论坛---软件测试,软件质量工程师").Link("[ 版主讨论区 ]").SetTOProperty "Text",arr(j)
                Browser("Browser").Page("51Testing软件测试论坛---软件测试,软件质量工程师").Link("[ 版主讨论区 ]").Click
                            Browser("Browser").Back
    Next

    这段代码先是打开一个空的页面,然后输入url.
    到达论坛首页。

    然后得到所有版面的名称,也就是link的名称。
    存到数组里面。
    然后使用SetTOProperty更换录制时候录下的link的属性。
    这时候再click





    18. Q:QTP 在Debug狀態,在Export View 區域不能寫入任何東西

    A: 如果你的目的是在debug过程中修改已执行过的命令,可以在Debug view的Command中执行命令,如重新执行已经执行过的命令,修改变量的值等等。

    如:Window("Flight Reservation").WinEdit("Name:").Set "51testing"
    已经执行,如果现在想修改“51testing”为“testing”,可以在command中执行
    Window("Flight Reservation").WinEdit("Name:").Set "testing"



    19 .Q: 动态变化值如何获取

    A:VAL=Browser("欢迎使用我的工作台").Page("欢迎使用我的工作台").Frame("managePlace_7").WebRadioGroup("userAccountId_0").GetROProperty("Value")
    Browser("欢迎使用我的工作台").Page("欢迎使用我的工作台").Frame("managePlace_7").WebRadioGroup("userAccountId_0").select val



    20 .Q: 如何一一获得Table中 某栏 link 的 text?

    A:通过上面link 的学习. 我终于融会贯通,完成了我的问题: 与大家共享:


    //////////////////////////////////////////////////////////////////////////////////////
    Browser("Login").Page("Page").Frame("contents").ViewLink("treeview").Image("Tplus").Click
    Browser("Login").Page("Page").Frame("contents").ViewLink("treeview").Image("Tplus_2").Click
    Browser("Login").Page("Page").Frame("contents").ViewLink("treeview").Link("开课设置").Click
    Browser("Login").Page("Page").Frame("main").WebList("drpStatus").Select "任意"
    Browser("Login").Page("Page").Frame("main").WebButton("查找").Click
    Browser("Login").Page("Page").Sync

    Dim finded,findCode,Nowout
    'define a constrat for find
    findCode = 110901   
    finded = false

    Function MaxPage(pageString)
       'msgbox pageString
       Dim ilen,i,j
       ilen = len(pageString)
       i=ilen
       While i>0
            j = mid(pageString,i,1)
               'msgbox j
               If instr("123456789",j)>0 Then
               MaxPage = j
                       'msgbox MaxPage
                       Exit function
               End If
               i=i-1
       Wend
    End Function

      
    Dim trowcount,maxp
    trowcount = Browser("Login").Page("Page").Frame("main_8").WebTable("开课代码").RowCount
    msgbox "Rowcount: "&trowcount
    Nowout = Browser("Login").Page("Page").Frame("main_8").WebTable("开课代码").GetCellData(trowcount,1)
    Nowout = trim(Nowout)
    maxp = MaxPage(Nowout)
    msgbox "max page: "& maxp

    Dim nowPage,checkid
    For nowPage = 1 to maxp
       If  finded Then
               Exit for
       End If
      ' link to the 当前所需page
      If nowpage>1 Then
        Browser("Login").Page("Page").Frame("main_8").Link("[2]").SetTOProperty "Text","["&nowpage&"]"
        Browser("Login").Page("Page").Frame("main_8").Link("[2]").Click
        Browser("Login").Page("Page").Sync
       end if

      ' Get the rowcount of table in now page
       trowcount = Browser("Login").Page("Page").Frame("main_8").WebTable("开课代码").RowCount
       msgbox "Rowcount: "&trowcount

      'link every record in the table of the page
       for i = 2 to trowcount  - 2
            Nowout = Browser("Login").Page("Page").Frame("main_8").WebTable("开课代码").GetCellData(i,2)
            'msgbox i&": "&Nowout

        checkid = "dgCourse:_ctl" &(i+1)& ":_ctl0"
        Browser("Login").Page("Page").Frame("main_8").WebCheckBox("dgCourse:_ctl3:_ctl0").SetTOProperty "name",checkid
        Browser("Login").Page("Page").Frame("main_8").WebCheckBox("dgCourse:_ctl3:_ctl0").Set "ON"
            
        Browser("Login").Page("Page").Frame("main_8").Link("0901").SetTOProperty "Text",Nowout
        Browser("Login").Page("Page").Frame("main_8").Link("0901").Click
        Browser("开课设置详细信息").Page("开课设置详细信息").Sync
            'wait(1)
            msgbox "begun"
            msgbox findCode
            msgbox Nowout
            msgbox "finished"
            If  trim(findCode) = trim(Nowout) Then
            finded = true
                    msgbox "find is ok!"
                    wait(2)
                    Exit for
            End If
        Browser("开课设置详细信息").Close
        Browser("Login").Page("Page").Sync
      next

    Next



    21 .Q:网页下拉框的选择

    A:For i =1 to 10
        Randomize
        IndexNum=Int((10 - 5 + 1) * Rnd + 5)
        Browser("Mercury Tours").Page("Find Flights_2").WebList("arrive").Select "#"&IndexNum
        wait(3)
    Next



    Sub ChildObjects_Example()
    'The following example uses the ChildObjects method to find all the
    'list objects on a Web page, and then to select an item in each list.

    Set ōDesc = Descrīption.Create()
    oDesc("micclass").Value = "WebList"
    Set Lists = Browser("Mercury Interactive").Page("Mercury Interactive").ChildObjects(oDesc)
    NumberOfLists = Lists.Count()
    For i = 0 To NumberOfLists - 1
    Lists(i).Select i + 1
    Next


    End Sub



    22 .Q: 将测试数据单独拿出来

    A: 取得一个
    Browser("Browser").Page("").WebList("fid").GetItem (1)
    取得全部
    Browser("Browser").Page("").WebList("fid").GetROProperty("all items")



    以下可以在自带的例子中实现
    Window("Flight Reservation").WinComboBox("Fly From:").Select "Frankfurt"
    a=window("Flight Reservation").wincombobox("Fly From:").GetItem(1)
    reporter.ReportEvent 2,"下拉列表的值",a



    23 .Q:和TD连接

    A:在QTP中不是有个Quality Center Connection,选择服务器连接,服务器处输入类似http://computer_name/tdbin,其中computer_name为服务器的名字,连接后在测试结果中添加defect就可以与TD相连了。



    24 :Q:处理Windows弹出窗口

    A:IF Not Window("Flight Reservation").Exist(1) Then
                            'Calling  open flight
                   If    not Dialog("Login").Exist(1)  Then
                                                        Browser("管理系统").Dialog("Microsoft Internet Explorer").WinButton("确定").Click

                                             End If



    25 .Q:查询结果的比较

    这是查询一个字段的,对查询结果多页的情况也涉及了,其实应该把所有查询字段联合起来的,也就是改改sql语句和判断条件。

    [i]Set Conn = CreateObject("ADODB.Connection")
    Set Rs = CreateObject("ADODB.Recordset")
    Conn.Open "Descrīption=kml-it;DRIVER=SQL Server;SERVER=KML-IT;UID=sa;PWD=password;APP=QuickTest Professional;WSID=KML-MICHELLE;DATABASE=kml_db"
    sql="select distinct grn_no from grn_dtl where grn_no like '%"&grnNo&"%' order by grn_no DESC"
    Rs.open sql,Conn,1,3
    Dim i,j,cell
            i=1
            j=2 'j=2 的原因是因为页面上table是的数据是隔一行一条,不知   道怎么回事,开发人员弄的怪把
                    Do while not rs.eof
                            If i=13 Then  '13是每页显示出的最大行数,是个常数
                                    i=1
                                    j=2
                                     Browser("::").Page("::").Frame("mainFrm_5").Link("下一页").Click
                            end if
                            cell=Browser("::").Page("::").Frame("mainFrm_5").WebTable("收货单号").GetCellData(j,2)
                            If cell<>rs("grn_no") Then
                    Reporter.ReportEvent 1, "查询功能"&cell, "查询结果错误."
                                    Exit do
                            else
                                    Reporter.ReportEvent 0, "查询功能"&cell, "查询结果正确."
                            End If
                            rs.movenext
                            j=j+2
                            i=i+1
                    Loop
    rs.close
    conn.close
    set conn=nothing[/i]
  • QTP中的描述性编程

    2007-10-12 16:29:51

    使用编程性描述(Using Programmatic Descrīptions

    在录制脚本时,QTP会将被测对象添加到对象仓库中。只要对象存在于仓库中,我们就可以在专家视图中使用该对象进行手动添加脚本。在脚本中,我们一般都使用对象的名称(该对象名称不区分大小写)作为对象描述。

    例如:

    在下面的语句中“username”是一个编辑框的名称。这个编辑框位于某页面(Page)之上(该页面的名称为“Mercury Tours”),并且该页面属于名为“Mercury Tours”的浏览器(browser)。

    Browser("Mercury Tours").Page("Mercury Tours").WebEdit("username")

    因为对象仓库中的对象的名称是唯一的,因此你只要在脚本中指定对象的名称即可。QTP根据指定的对象名称以及它的父对象在对象仓库中找到该对象,然后根据仓库中对象的详细描述从被测试程序中查找并识别对象。

    其实,在QTP脚本中,不使用对象仓库或对象名称,也可以对被测程序中的对象进行操作。为了做到这一点,我们需要在QTP脚本中提供对象的属性及其值的列表。这就是编程性描述。

    当对象不存在于对象仓库之中,而我们又希望操作该对象时,编程性描述就非常有用。如果有多个对象,它们具有某些相同的属性,通过编程性描述,我们可以在这些对象上进行相同的操作;或者某个对象的属性无法确定,需要在运行过程中指定,我们也可以使用编程性描述,来对该对象进行操作。

    例如:在一个页面有多个check box,你不能预知其个数,也不知道所有check box的准确描述,然而你希望选中所有的check box。在这种情况下,你可以使用编程性描述来解决。你只需要让QTP对所有描述为 HTML TAG=input,TYPE=check box的对象执行一个 Set “ON”的操作即可。

    编程性描述的方法有两种:

    方法一:在语句中直接列出对象的属性及值的列表;

    方法二:使用Descrīption对象,为Descrīption对象添加属性及值的集合,然后在语句中直接使用Descrīption对象的名称即可。

    使用第一种方法要简单一些,但是在很多情况下,第二种方法更显得功能强大并更有效率。

    在语句中直接使用编程描述(Entering Programmatic Descrīptions Directly into Statements

    在语句中不使用对象的名称,而是使用对象的描述(指定多对property:=value值)。

    通常语法如下:

    TestObject(“PropertyName1:=PropertyValue1”,”,“PropertyNameX:=PropertyValueX)

    TestObject:指的是测试对象的类名

    PropertyName:=PropertyValue:指的是测试对象的属性及值。每对property:=value用双引号标记,并用逗号隔开。

    注:property value可以是变量。

    注意:在编程性描述中,QTP将所有的property value视为正则表达式。因此,当property value中包括正则表达式特殊字符(如*,?,+)时,要在特殊字符前加“\”

    下面的语句中,使用到了Mercury Tours网页中的一个WebEdit对象,它的NameAuthorIndex3。在运行过程中,QTP就会从网页中查找NameAuthor并且Index3WebEdit对象,并在WebEdit中输入文字“MarkTwain”。

    Browser("Mercury Tours").Page("Mercury Tours").WebEdit("Name:=Author", "Index:=3").Set "Mark Twain"

    注意:如果你对测试对象层级关系中的某个上级对象使用了编程性描述,那么在同一语句中,从该对象开始,它的所有下级对象都必须使用编程性描述,否则QTP不能识别该父级对象的下级对象。

    例如:语句中,层级关系中所有的对象都使用了编程性描述:

    Browser("Title:=Mercury Tours").Page("Title:=Mercury Tours").WebEdit("Name:=Author", "Index:=3").Set "Mark Twain"

    下面的语句中,从层级关系中的某个点开始,使用编程性描述(从Page对象开始):

    Browser("Mercury Tours").Page("Title:=Mercury Tours").WebEdit("Name:=Author", "Index:=3").Set "Mark Twain"

    但是,你不能象下面的语句这样使用编程性描述。(它对BrowserPage对象使用了编程性描述,但是对于WebEdit对象,却又想使用对象仓库中的名称)

    Browser("Title:=Mercury Tours").Page("Title:=Mercury Tours").WebEdit("Author").Set "Mark Twain"

    QTP偿试根据WebEdit的名称在仓库中定位对象,但是却无法在仓库中找到它的父对象。

    For more information on working with test objects, see Working with Test Objects.

    如果在脚本中你要多次使用到相同的编程性描述,可以将对象指定到变量。

    例如,有如下脚本:

    Window("Text:=Myfile.txt - Notepad").Move 50, 50

    Window("Text:=Myfile.txt - Notepad").WinEdit("AttachedText:=Find what:").Set "hello"

    Window("Text:=Myfile.txt - Notepad").WinButton("Caption:=Find next").Click

    你可以将脚本改进为:

    Set MyWin = Window("Text:=Myfile.txt - Notepad")

    MyWin.Move 50, 50

    MyWin.WinEdit("AttachedText:=Find what:").Set "hello"

    MyWin.WinButton("Caption:=Find next").Click

    你还可以使用With语句,将脚本改进为:

    With Window("Text:=Myfile.txt - Notepad")

           .Move 50, 50

           .WinEdit("AttachedText:=Find what:").Set "hello"

           .WinButton("Caption:=Find next").Click

    End With

    For more information about the With statement, see With Statement.

    在编程性描述中使用Descrīption对象(Using Descrīption Objects for Programmatic Descrīptions

    你可以使用Descrīption对象,来返回一个Properties collection对象,该集合对象包括一系列Property对象。每个Property对象由Property namevalue组成。

    然后在语句中用Properties collection对象替代被测对象的名称。

    注意:默认情况下,所有被添加到Properties collection中的Property对象的值被当成正则表达式对待。因此,当Property Value中包含正则表达式的特殊字符(如*?+)时,要在特殊字符前使用“\”符号。

    你也可以在Properties Collection中,将RegularExpression属性值设置为False,这样即使在Property Value中用到了正则表达式的特殊字符,也会被视为普通字符。更多信息参考QuickTest Professional Object Model ReferenceUtility部分。

    要创建Properties collection,使用Dexcription Create语句,语法如下:

    Set MyDescrīption = Descrīption.Create()

    一旦创建了Properties 对象(例如上例中的Mydescrīption,在运行过程中,你就可以使用语句向Properties对象添加、编辑、移除或获取属性及属性值。这使你在运行过程中可以动态的决定:在对象描述中使用哪些属性、使用多少属性。

    当你将一系列的属性及属性值加入到Properties collection中以后,你就可以在脚本语句中用Properties对象替代被测对象的名称。

    例如,有如下语句:

    Window("Error").WinButton("text:=OK", "width:=50").Click

    通过改造,成为:

    Set MyDescrīption = Descrīption.Create()
    MyDescrīption("text").Value = "OK"
    MyDescrīption("width").Value = 50
    Window("Error").WinButton(MyDescrīption).Click

    注:当为一个ActiveX对象创建编程性描述时,如果该对象的run-time对象是windowless的(即没有相应的window handel),就必须在属性描述中将它的windowless property设置为Ture

    例如:

    Set ButDesc = Descrīption.Create
    ButDesc("ProgId").Value = "Forms.CommandButton.1"
    ButDesc("Caption").Value = "OK"
    ButDesc("Windowless").Value = True
    Window("Form1").AcxButton(ButDesc).Click

     

    获取Child ObjectsRetrieving Child Objects

    通过ChildObjects方法,可以获取指定对象下的所有子对象,或只获取那些符合编程性描述的子对象。为了获取某对象的子对象的子集,首先需创建一个descrīption对象,然后在该对象的descrīptions collection中添加一系列的属性及属性值,这些属性及属性值必须符合子集的要求。

    注意:你必须使用Descrīption对象来为ChildObjects描述参数 创建编程性描述,不能使用property:=value语法直接将编程性描述添加到参数中。

    一旦你已经在descrīption对象中“built”了描述,就可以使用下面的语法来获取与描述匹配的子对象:

    Set MySubSet=TestObject.ChildObjects(MyDescrīption)

    例如:下面的语句使QTP选中网页中的所有选择框:

    Set MyDescrīption = Descrīption.Create()

    MyDescrīption("html tag").Value = "INPUT"

    MyDescrīption("type").Value = "checkbox"

    Set Checkboxes = Browser("Itinerary").Page("Itinerary").ChildObjects(MyDescrīption)

    NoOfChildObjs = Checkboxes.Count

    For Counter=0 to NoOfChildObjs-1

           Checkboxes(Counter).Set "ON"

    Next

    For more information about the ChildObjects method, refer to the QuickTest Professional Object Model Reference.

    WebElement对象使用编程性描述(Using Programmatic Descrīptions for the WebElement Object

    如果没有录制WebElement对象,也可以使用编程性描述,来对Web网站中的任何一个WebElement对象进行操作。

    例如:

    Browser("Mercury Tours").Page("Mercury Tours").WebElement("Name:=UserName", "Index:=0").Click

    set WebObjDesc = Descrīption.Create()

    WebObjDesc("Name").Value = "UserName"

    WebObjDesc("Index").Value = "0"

    Browser("Mercury Tours").Page("Mercury Tours").WebElement(WebObjDesc).Click

    QuickTest clicks on the first Web object in the Mercury Tours page with the name UserName.

    关于WebElement对象的更多信息,参考QuickTest Professional Object Model Reference

    在编程性描述中使用Index属性(Using the Index Property in Programmatic Descrīptions

    在需要唯一识别一个对象时,index属性有时候可能非常有用。index属性是对象在源代码中出现的顺序,第1次出现时,index值为0

    Index属性是object-specific的。因此,当你用index属性值“3来描述一个WebEdit对象时,QTP会在被测程序的当前页面中查找第4WebEdit对象。

    如果你使用index属性值3来描述一个WebElement对象时,QTP会在被测程序的当前页面中查找第4Web对象。

    例如,当前页面中存在下面的对象:

    • 一个名为QppleImage对象
    • 一个名为UserNameImage对象
    • 一个名为UserNameWebEdit对象
    • 一个名为PasswordImage对象
    • 一个名为PasswordWebEdit对象

    下面的语句中指的是列表中的第3个对象,因为它要求指向的是第1个名为UserNameWebEdit对象。

    WebEdit("Name:=UserName", "Index:=0")

     

    下面的语句中指的是列表中的第2个对象,因为它要求指向的是第1个名为UserNameWebElement对象。

    WebElement("Name:=UserName", "Index:=0")

    注:如果当前只有一个对象,使用index=0将无法查找到对象,因此就不能在对象描述中使用index属性。

Open Toolbar