发布新日志

  • (转) QTP测试报表table内容的思路

    2008-12-20 11:48:48

    使用QTP对报表中的webtable内容进行正确性验证。

        基本思路是:

        一:使用getcelldata(i,j)的方法遍历webtable把表格内容存入一个数组中,一般为二维数组

        二:使用数据库连接组件ADODB连接后台数据库,使用数据结果集对象保存select查询结果,也是一个二维数组

        三:此时区分是否需要验证排列顺序,如果需要,直接对两个二维数组进行一对一遍历比较

        四:不需要验证排列顺序,或者顺序无法控制的情况下,我们需要对显示内容和查询预期内容进行比较,这时候牵涉到两个结果集的数据顺序问题,如果采用单对多遍历的情况,效率会十分低。

        这时候我们换一种思路考虑,既然是验证内容,那我们就可以把二维数组的验证转换成排序一维数组比较,实现方式是,采用join方法将二维数组的每一行转换成一个字符串(内容没有变化,只加入拼接符),两个二维数组进行相同转换,成为两个一维的字符串数组。

        然后使用快速排序法对两个一维数组进行一次排序,同样的机制下,如果原本内容相同,那么排序出的内容也应该相同。然后直接进行一维数组一对一比较。

        下面是vbs的快速排序代码,合适数字和字符串数组:

    Public Function QSort(ByRef ReArr, ByVal head, ByVal tail)

    'ReArr 是待排序数组, head和tail是该数组的最小下标和最大下标
    Dim lef, rig
    Dim pivot

    If head < tail Then
     lef=head
     rig=tail
     pivot=ReArr(lef)
     While (lef <> rig)

      While (lef < rig and ReArr(rig) >= pivot)
       rig = rig-1
      Wend
      If lef <rig Then
       ReArr(lef) = ReArr(rig)
       lef = lef+1
      End If

      While (lef < rig and ReArr(lef) <= pivot)
          lef = lef+1
      Wend
      If lef <rig Then
       ReArr(rig) = ReArr(lef)
          rig = rig-1
      End If
     
     Wend

     ReArr(lef) = pivot
     call QSort(ReArr, head, lef-1)
     call QSort(ReArr, lef+1, tail)
     
    End If
    End Function

  • (转)学习QTP后的总结

    2008-12-20 11:37:30

    1、拆分语句split
    例:取得当前日期后拆分
    riqi=date()
        my=split(riqi,"-")
        riqi=my(1)&"月"&my(2)&"日"
        datatable("riqi",DtGlobalSheet)=riqi
        本地表:DataTable("a", dtLocalSheet)
    riqi= year(date)& "-" & Right("0"& month(date),2) & "-"&Right("0"&   Day(Date),2)

    2、取得表格中某行某列的值GetCellData
    例:飞机票取票价
    shuA=Browser("Welcome: Mercury Tours").Page("Book a Flight: Mercury").WebTable("New York to Zurich").GetCellData(3,3)


    3、取距某年某月某日的天数datediff
    例:计算距2008-08-08奥运天数
    datediff("d",now,"2008-8-8")


    4、描述性编程text:=
    例:取得某页面上某文字的链接
    Browser("").Page("").Link("text:=娱乐").Click
         或
         neirong="娱乐"
         Browser("").Page("").Link("text:="&neirong).Click


    5、网页中HTML编辑器的录制
    功能:验证126邮箱的发信功能正确
    操作步骤:
          a.录制脚本,动作包括整个发信的过程。
          b.修改脚本,在输入信件主题代码后加wait 10语句
           c.回放脚本,观察在邮件正文中输入的内容,回放时QTP是否写入
          d.重新修改脚本,保证回放时QTP在邮件正文中写入内容

    英文解决方案:
        Browser("网易126免费邮--你的专业电子邮局").Page("网易电子邮箱 - xueqinzhaoqing@126.co").Frame("indexFrame").WebEdit("subject").Click
        wait 1
         Setting.WebPackage( "ReplayType")=2      '配置使用浏览器事件或鼠标运行鼠标操作的'方式.1 - 使用浏览器事件运行鼠标操作,2 - 使用鼠标运行鼠标操作。
         Set ōbj=createobject("wscrīpt.shell")
         obj.sendkeys "{TAB}"
         wait 2
         obj.sendkeys "abc1111"
         wait 1
         Setting.WebPackage( "ReplayType")=1
    中文解决方案

    strCopy = "软件测试." 
    Set ōbjIE = CreateObject("InternetExplorer.Application") 
    objIE.Navigate("about:blank") 
    objIE.document.parentwindow.clipboardData.SetData "text", strCopy 
    objIE.Quit

    wait 1
    Setting.WebPackage( "ReplayType")=2
    Set ōbj=createobject("wscrīpt.shell")
    obj.sendkeys "{TAB}"
    wait 2
    obj.sendkeys "^v"
    wait 1
    Setting.WebPackage( "ReplayType")=1

    6.使用Multi Test Manager添加文件时可以直接往里拖的哦。

    7.函数:新建记事本,改名为public.vbs例:
       function ZHIRSS
    ZHIRSS="RSS行业资讯分类维护"
    end function
      使用语句executefile "d:\zhaopin\case\denglu.vbs"或设置QTP test/settings/resources/+函数目录

    8.设置动作循环:右击/actiong call properties/run on all rows

    9.设置动作允许被调用:右击/action properties/general/reusable action打勾

    10.QTP与MTM连接:Tools/option/run/allow other mercury products to run...

    11.插入已存在的动作1)insert/call to copy of action...复制可修改
                       2)insert/call to existing of action...复制不可修改

    12.QTP报告自动跳出设置:Options>Run>View results when run session ends

    13.判断表格是否存在:
    If Browser("数商3.0后台管理系统").Page("Page").Frame("main_5").WebTable("标题").Exist then
    reporter.ReportEvent 0,"pass","系统显示了所有的资讯列表!"
    else
      reporter.ReportEvent 1,"fail","系统没有显示资讯列表!"
    end if

    14.获取表格行数:Browser("数商3.0后台管理系统").Page("Page").Frame("main_5").WebTable("标题").RowCount

    15.注释脚本存在位置:qtp/dat/ActionTemplate.mst

    16取本地文件名称Function ShowFileList(folderspec)
       Dim fso, f, f1, fc, s
       Set fso = CreateObject("scrīpting.FileSystemObject")
       Set f = fso.GetFolder(folderspec)
       Set fc = f.Files
       For Each f1 in fc
          s = s & f1.name
          s = s &   "  "
       Next
       ShowFileList = s
    End Function
    wenjian=ShowFileList("D:\下载\本地下载1\")

    17.取本地文件删除:del= DeleFile("D:\下载\本地下载1\")
    Function DeleFile(folderspec)
       Dim fso, f, f1, fc, s
       Set fso = CreateObject("scrīpting.FileSystemObject")
       Set f = fso.GetFolder(folderspec)
       Set fc = f.Files
       For Each f1 in fc
             f1.delete
       Next
    End Function

    18.sousuo2=Browser("Browser").Page("Page_4").Check (CheckPoint("2007-11-08 14:21"))
    If (sousuo2)eqv(true) Then
        reporter.ReportEvent 0,"",""
    else
       reporter.ReportEvent 1,"",""
    End If

    19.取参数化数据的行数,只在某几行进执行某些语句
    row=datatable.GetSheet(3).getcurrentrow
    If row = 3 Or row = 4 Then

    20.单选框置灰zhihui=Browser("下载中心--新增下载文件").Page("下载中心--新增下载文件_4").WebRadioGroup("downloadType").GetROProperty("disabled")
    If  zhihui=1 Then
    End If

    29.取树结构
    Set Desc=descrīption.create
    Desc("micclass").value="WebTable"
    Set List=Browser("Browser").Page("Page").Frame("main").ChildObjects(Desc)
    yuqi=List(0).GetROProperty("innertext")
    msgbox yuqi
    yuqi=split(yuqi," ")
    msgbox yuqi(1)

    30.关闭所有IE
    SystemUtil.CloseProcessByName("iexplore.exe")

    31.创建action template.
        当希望在每一个新建action时都增加一些头部说明,比如作者、创建日期、说明等,用action template
        来实现最简单快捷。
        方法:用记事本等文本编辑器,输入如下类似的内容:
              'Company: xxxx
              'Author: xxx
              'Product: xxx
              'Date: xx
             然后将文件保存为ActionTemplate.mst,并存放到QTP安装目录下的dat目录。

    32.启动IE的语句:SystemUtil.Run "iexplore.exe", "http://www.***.com"
       关闭IE或其他程序的语句:SystemUtil.CloseProcessByName "app.exe"
         or  SystemUtil.CloseProcessByWndTitle "Some Title"

    33.获取图片的名称
    ObjectName = Browser(…).Page(…).Image("Find").GetProperty("Name")

    34.检查某个对象是否存在,如果存在弹出对话框说明对象存在。
    If Browser("Browser").Page("Page").Applet("login.html").JavaEdit("username").Exist Then
    MsgBox("The object exists.")
    End if

    35.同步点
    Browser("数商3.0制作平台").Dialog("Microsoft Internet Explorer").WaitProperty "visible", True, 120000
    设置test/test settings/object synchronizationg timeout 一致

    36.视图框显示为乱码时:调整原页面编码,在QTP/tools/change active screen

    37.添加附件:
       Browser("**").Page("**").WebFile("filePath").Click
    Browser("**").Dialog("**").WinEdit("文件名(N):").Set "D:\**.jpg"
    Browser("下载中心--新增下载文件").Dialog("选择文件").WinButton("打开(O)").Click
    添加相应的对象


    38.在图片上右击添加:tools/web event recording configuration/custom settings
    webedit/event/add/onblur,onchange,onfocus,onpropertychan,onsubmit
    webdlement/event/add/onclick,onmousedown,onmouseup/listen always

    39.数据执行保护
      方法一、右击我的电脑/高级/性能/设置/数据执行保护/为除下列选定程序之外的所有程序和服务启用DEP/添加被保护的程序。
      方法二、C:/BOOT.INT修改noexecute=alwaysoff

    40.在图片上右击添加:tools/web event recording configuration/custom settings
    webedit/event/add/onblur,onchange,onfocus,onpropertychan,onsubmit
    webdlement/event/add/onclick,onmousedown,onmouseup/listen always

    41.去掉前后空格
    If trim(mingcheng)=trim(yuqi) Then

    42.分类树问题解决
    Set Desc=descrīption.create
    Desc("micclass").value="WebTable"
    Set List=Browser("Browser").Page("Page").Frame("main").ChildObjects(Desc)
    yuqi=List(0).GetROProperty("innertext")
    msgbox yuqi
    yuqi=split(yuqi," ")
    msgbox yuqi(1)


    43.引用自定义环境变量
    Environment.LoadFromFile "D:\询价\case\环境\huiyuan.xml"

    44.环境变量有2种,一种是QTP的内置变量,一种是用户自定义的变量。内置变量是可以直接就可以用,自定义环境变量需要在菜单中选择“文件”——>“设置”——>“环境”,在变量类型中选择“用户自定义”,然后进行添加,可以对添加的变量全部导出,导出的文件为.xml格式的文档。既然可以导出,那么必然可以导入.xml文件,你可以在该对话框中的选中“从外部文件导入”,然后添加其文件路径即可。(当然这些操作都可以直接使用脚本来实现,如:Environment.LoadFromFile(“FileName”))
    例如:在桌面建立一个Var.xml,如下
    -<Environment>    //以这个开始的内部都是定义环境变量,直到以</Environment>结束
    - <Variable>                           // 变量定义起始标识
                     <Name>aa</Name>               // 变量名称
                     <Value>11</Value>               // 变量值
            </Variable>                            // 变量定义结束标识
    - <Variable>
                     <Name>bb</Name>
                     <Value>22</Value>
            </Variable>
    - <Variable>
                     <Name>cc</Name>
                     <Value>33</Value>
                  </Variable>
      </Environment>
    然后导入本测试的环境变量文件中,在专家视图里编写下面的脚本代码:
    Dim aParam3
    aParam3=Environment.Value(“aa”)          // 调用环境变量
    msgbox aParam3
    运行测试,会输出”11”

    45.在HTML编辑器中写入数据
    用低水平录制写入编辑器过程,增加编辑部器前的对象,加入click事件,再用TAB
    例如:
    Browser("广告管理").Page("广告管理").WebEdit("descrīption").Click
    Window("Microsoft Internet Explorer").WinObject("Internet Explorer_Server").Type mictab
    Window("Microsoft Internet Explorer").WinObject("Internet Explorer_Server").Type "aaa"

    46.Browser("creationtime:=1").close
       两个页面title相同无法识别时使用描述必编辑
        Browser("creationtime:=1").page(title:=****).WebEdit("name:=***").Set "***"
        或Browser("creationtime:=1").page(index:=1).WebEdit("index:=0").Set "***"

    47.场景恢复:
       当某些提示框会在不定期时有提示时,如果自动点击确定或某些按钮
       1、tools/recovery scenaril manager,制作相应的提示框和要点击的按钮,并保存
       2、test/settings/recovery,添加刚保存的.qrs

    48.输入验证码,先提示一个输入框,在输入框内输入验证码,点击[确定],把输入的验证码框
       Dim a
      a = InputBox("输入名字")

    49.对象库中对象名称不分为_2,_3...设置:tool/options/web/page/fram options/
         crate a new page test object for为different test object descrīptons
         crest a new frame. test object for为different test object descrīptions

    50.验证测试输入框输入的最大允许字数功能的正确

    QTP脚本代码中编写
    Set aa=Browser("Browser").Page("Page").Frame("main").WebEdit("PayTypeName")
    if konglen(aa,20) eqv true then
    reporter.ReportEvent 0,"添加支付方式,支付方式输入框允许输入的最大字符功能正确",""
    else
    reporter.ReportEvent 1,"添加支付方式,支付方式输入框允许输入的最大字符功能错误",""
    end if

    此函数的功能为:验证测试输入框输入的最大允许字数功能的正确,函数可写在public.vbs中
    Function konglen(duixiang,guifanshu)
    duixiang.Click
    wait 1
    Setting.WebPackage( "ReplayType")=2
    Set ōbj=createobject("wscrīpt.shell")
    i=0
    ōld="a"
    xin="b"
    while old<>xin
    ōld=duixiang.GetROProperty("value")
    i=i+1
    wait 0,20
    obj.sendkeys "1"
    wait 0,20
    xin=duixiang.GetROProperty("value")
    wend
    'msgbox i
    If i-1=guifanshu Then
    konglen=true
    else
    konglen=false
    End If
         Setting.WebPackage( "ReplayType")=1
    End Function

    51.超时设置:Setting("DefaultTimeout") =1000000

    52.共享对象库:Set App = CreateObject("QuickTest.Application")
    App.Test.Settings.Resources.ObjectRepositoryPath = "path"

    53.取颜色   browser("b").page("p").Object.currentStyle“:.color
    54.显示行号设置:Tools- --> Editor Options...-->General-->Show line number,


    55.不同数据库检查点手动SQL写法
    QTP插入数据库检查点,手动指定SQL语句的写法。
    一、SQL Server格式(本地无需安装SQL Server)
    connectionstring(连接字符串):
    1.本地没有创建数据源的方式
    DRIVER=SQL Server;SERVER=数据库IP地址;UID=用户名;PWD=密码;APP=Microsoft Office 2003;WSID=本地主机名;DATABASE=数据库名

    实例:
    DRIVER=SQL Server;SERVER=10.160.11.10;UID=sa;PWD=sa;APP=Microsoft Office 2003;WSID=RJHLJUN;DATABASE=dcwork

    2.本地已创建数据源的方式
    DSN=数据源名称;UID=用户名;PWD=密码;APP=Microsoft Office 2003;WSID=数据库的主机名;DATABASE=数据库名

    实例:
    DSN=LocalServer;UID=sa;PWD=sa;APP=Microsoft Office 2003;WSID=RJDCWORKTEST;DATABASE=dcwork

    3.SQL语句实例(从数据库表HR_LANGUAGE_TYPE中,查询字段语言名称LANGUAGE_NAME,条件语言名称=中文,按语言名称升序排序结果)
    source(SQL语句):
    SELECT HR_LANGUAGE_TYPE.LANGUAGE_NAME  FROM dcwork.dbo.HR_LANGUAGE_TYPE HR_LANGUAGE_TYPE  WHERE (HR_LANGUAGE_TYPE.LANGUAGE_NAME='中文')  ORDER BY HR_LANGUAGE_TYPE.LANGUAGE_NAME


    二、DB2格式:(本地至少安装DB2 Run-Time Client Lite)
    connectionstring(连接字符串):
    1.本地没有创建数据源的方式
    DRIVER={IBM DB2 ODBC DRIVER};UID=用户名;PWD=密码;MODE=SHARE;DBALIAS=数据库名;

    实例:
    DRIVER={IBM DB2 ODBC DRIVER};UID=db2admin;PWD=db2admin;MODE=SHARE;DBALIAS=DCWORK;

    2.本地已创建数据源的方式
    DSN=数据源名称;UID=用户名;PWD=密码;MODE=SHARE;DBALIAS=DCWORK;

    实例:
    DSN=DWCORKDB2;UID=db2admin;PWD=db2admin;MODE=SHARE;DBALIAS=DCWORK;

    3.SQL语句实例
    source:SQL语句
    SELECT HR_LANGUAGE_TYPE.LANGUAGE_NAME  FROM DB2ADMIN.HR_LANGUAGE_TYPE HR_LANGUAGE_TYPE  WHERE (HR_LANGUAGE_TYPE.LANGUAGE_NAME='中文')  ORDER BY HR_LANGUAGE_TYPE.LANGUAGE_NAME


    三、Oracle格式:(本地需要安装Oracle ODBC DRIVER)
    connectionstring(连接字符串):
    1.本地没有创建数据源的方式
    DRIVER={Oracle in OraHome92};SERVER=数据库服务名;UID=用户名;PWD=密码;DBQ=数据库名;DBA=W;APA=T;EXC=F;XSM=Default;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;GDE=F;FRL=Lo;BAM=IfAllSuccessful;MTS=F;MDI=Me;CSR=F;FWC=F;PFC=10;TLO=O;

    实例:
    DRIVER={Oracle in OraHome92};SERVER=DCWORK;UID=DCWORK;PWD=DCWORK;DBQ=DCWORK;DBA=W;APA=T;EXC=F;XSM=Default;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;GDE=F;FRL=Lo;BAM=IfAllSuccessful;MTS=F;MDI=Me;CSR=F;FWC=F;PFC=10;TLO=O;



    2.本地已创建数据源的方式
    DSN=数据源名称;UID=用户名;PWD=密码;DBQ=数据库名;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;GDE=F;FRL=F;BAM=IfAllSuccessful;MTS=F;MDI=F;CSR=F;FWC=F;PFC=10;TLO=0;

    实例:
    DSN=dcworkoracle;UID=DCWORK;DBQ=DCWORK;DBA=W;APA=T;EXC=F;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;GDE=F;FRL=F;BAM=IfAllSuccessful;MTS=F;MDI=F;CSR=F;FWC=F;PFC=10;TLO=0;

    3.SQL语句实例
    source:SQL语句
    SELECT HR_LANGUAGE_TYPE.LANGUAGE_NAME  FROM DCWORK.HR_LANGUAGE_TYPE HR_LANGUAGE_TYPE  WHERE (HR_LANGUAGE_TYPE.LANGUAGE_NAME='中文')  ORDER BY HR_LANGUAGE_TYPE.LANGUAGE_NAME



    四, mysql
    Set Conn = CreateObject("ADODB.Connection" )
    str="DRIVER={MySQL ODBC 3.51 Driver};SERVER=192.168.1.100;DATABASE=wp_blog;user id=zzz ; password=123456"
    Conn.open str
    Set Rs = CreateObject ("ADODB.Recordset" )
    sql = "select * from `wp_blog`.`blg_webcategory` limit 0, 5000;"
    Rs.open sql,conn,1,3
    If (not Rs.eof) then
    Rs.MoveFirst
    MsgBox Rs(0)
    MsgBox Rs(1)
    MsgBox Rs(2)
    MsgBox Rs(3)
    end if

    Rs.close
    Set Rs = Nothing
    Conn.close
    Set Conn = Nothing
    (转载于 http://bbs.51testing.com/thread-42921-1-1.html )

    五. access

    Set Conn = CreateObject("ADODB.Connection" )
    str="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:/db1.mdb"
    Conn.open str
    Set Rs = CreateObject ("ADODB.Recordset" )


    56.*.xml
    Environment.LoadFromFile "D:\新建文件夹\a.xml"
    Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").Set Environment("HuiYuanB")

    57、类似时间控件,不能手到输入的文本档
       1)手工添加对象,
       2).object.value="2008-4-12"

  • (转) QTP自动添加所有存在记录

    2008-12-20 11:25:00

    题目的内容是这样的,实现自动插入flight小程序的数据库中的所有记录(任意数量)。

        这时候我们需要考虑很多问题,登陆不是主要事件,忽略,当你进入order订单界面的时候,我们主要考虑动态变化的元素,主要有3个元素:flyfrom;flyto;以及确定了from和to之后的flights列表.

        根据分析我们可以发现,flyfrom永远是10取1,index从0-9,而flyto则是去掉被选定的from之后剩余的9取1,index从0-8;这两个动态元素比较容易控制.

        难点是flights弹出列表的记录数,这个记录数根据选定的from,to进行对应变化,也就是说有10的10次方种列表,我们无法写出简单的脚本对其进行自动读取.

        改变一下思路,我们事先不知道flights列表的index,那我们就添加额外步骤去确认每一次的index,只要我们控制好循环,就可以完成其遍历所有存在记录的目的.

    以下是自动添加1000条相互不同记录的脚本

    登陆部分(忽略)

    Dialog("Login").WinEdit("Agent Name:").Set "abanban"
    Dialog("Login").WinEdit("Agent Name:").Type  micTab
    Dialog("Login").WinEdit("Password:").SetSecure "47a173562d6104f53d107ca1be4ccb82c48020f1"
    Dialog("Login").WinEdit("Password:").Type  micReturn

    循环插入记录,重点部分,三层循环

    '定义插入记录数,插入计数器

    'InsertCount用来控制指定数量插入不同记录
    InsertCount=1000
    InsertNum=0

    '取往来地点的最大值,固定,Maxfrom是flyfrom,Maxto是flyto
    Maxfrom = Window("Flight Reservation").WinComboBox("Fly From:").GetItemsCount
    Maxto=Maxfrom-1

    '最外层循环,Fly from
    For i=0 to Maxfrom-1

    '第二层循环,Fly to 
     For j=0 to Maxto-1

    '这一段用作取当前往来的所有可选航班,可变,在每一次往来变化中动态获得flightsnum,
    '用来作为do while 循环的退出条件
      Window("Flight Reservation").WinButton("Button").Click
      Window("Flight Reservation").ActiveX("MaskEdBox").Type "1111111111"
      Window("Flight Reservation").WinComboBox("Fly From:").Select i
      Window("Flight Reservation").WinComboBox("Fly To:").Select j
      Window("Flight Reservation").WinButton("FLIGHT").Click

    '取flightsnum,每确认一次from,to取一次

      flightsnum=Window("Flight Reservation").Dialog("Flights Table").WinList("From").GetItemsCount

    '因为该步骤只是取不断变化的flights数量,所有cancel掉

      Window("Flight Reservation").Dialog("Flights Table").WinButton("Cancel").Click

         k=0
    '取flightsnum完成,初始化第三层循环计数器K

    '第三层循环,按照from i, to j, 航班 k遍历,k不断自增到flightsnum-1

      Do While 1  '死循环,无限

       Window("Flight Reservation").WinButton("Button").Click

       Window("Flight Reservation").ActiveX("MaskEdBox").Type "1111111111"
       
       Window("Flight Reservation").WinComboBox("Fly From:").Select i
       Window("Flight Reservation").WinComboBox("Fly To:").Select j
       Window("Flight Reservation").WinButton("FLIGHT").Click
       Window("Flight Reservation").Dialog("Flights Table").WinList("From").Activate k

       Window("Flight Reservation").WinEdit("Name:").Set "aban"
                Window("Flight Reservation").WinEdit("Tickets:").Set RandomNumber(1, 10)

       Window("Flight Reservation").WinButton("Insert Order").Click

       
       Window("Flight Reservation").ActiveX("Threed Panel Control").WaitProperty "text", "Insert Done...", 10000

    '计数器自增
       k=k+1

       InsertNum=InsertNum+1


    '插入记录数到达指定数,退出
       If InsertNum=InsertCount Then
        ExitTest
       End If

    '判断当前动态航班表flights是否遍历结束,结束则跳出第三层循环
       If flightsnum=k Then
        Exit do
       End If
       
         Loop

    '第二层循环,下一个flyto

     Next

    '第一层循环,下一个flyfrom

    Next

  • (转)在QTP中使用描述性编程(实例)

    2008-12-20 10:45:00

    QTP中使用描述性编程是一个提高QTP脚本利用率的很好的方式。
    通常QTP是通过对象库来识别不同的对象,而描述性编程是QTP另外一种能够识别对象的途径,它不依赖于对象库,通过增加一些对象的描述来识别对象的。
     
    说明:本例子是以Flight飞机订票系统的登陆界面为测试页面进行描述的。
     
    步骤一:录制脚本
    Dialog("Login").WinEdit("Agent Name:").Set "Holly"
    Dialog("Login").WinEdit("Password:").SetSecure "46ef0dc7efe5834c73673898279af1204fea51a7"
    Dialog("Login").WinButton("Cancel").Click
    共录制3步操作,输入Agent Name, Password, 点击Cancel按钮
     
    步骤二:初级描述性编程
    Dialog("Regexpwndtitle:=Login").WinEdit("Attached text:=Agent Name:").Set "Holly"
    Dialog("Regexpwndtitle:=Login").WinEdit("Attached text:=Password:").Set “Mercury
    Dialog("Regexpwndtitle:=Login").WinButton("Class Name:=WinButton", "text:=Cancel").Click
    在这里要注意有三点:
    1)如果需要两个以上特性来描述一个对象,需要使用逗号(,)对描述性语言进行分割
    2)使用:=来连接属性和属性值,并且:=两边不能有空格
    3)使用SPY查看对象的属性名和属性值(Tools -> Object Spy)
     
    步骤三:描述性编程提高
    Dim descEditLogin
    Set descEditLogin = Descrīption.Create()
    descEditLogin("Class Name").Value = "Dialog"
    descEditLogin("Regexpwndtitle").Value = "Login"
     
    Dialog(descEditLogin).WinEdit("Attached text:=Agent Name:").Set "Holly"
    Dialog(descEditLogin).WinEdit("Attached text:=Password:").Set "Mercury"
    Dialog(descEditLogin).WinButton("Class Name:=WinButton", "text:=Cancel").Click
    在这里需要注意有两点:
    1)把经常使用到的对象定义为一个对象变量,方便以后调用,减少代码工作量和错误
    2)使用SPY获取对象的属性和属性值
     
    步骤四:使用自定义的环境变量
    在File>>Settings>>Environment中选择user-defined,增加一个变量
    dlgLogin = “Login”
     
    这样脚本可以被修改为:
    Dim descEditLogin
    Set descEditLogin = Descrīption.Create()
    descEditLogin("Class Name").Value = "Dialog"
    descEditLogin("Regexpwndtitle").Value = Environment.Value("dlgLogin")
     
    Dialog(descEditLogin).WinEdit("Attached text:=Agent Name:").Set "Holly"
    Dialog(descEditLogin).WinEdit("Attached text:=Password:").Set "Mercury"
    Dialog(descEditLogin).WinButton("Class Name:=WinButton", "text:=Cancel").Click
    当然,参数化的方式很多,这边介绍的是使用环境变量
     
    步骤五:从XML文件导入环境变量
    <Enviroment>
           <Variable>
                  <Name>dlgLogin</Name>
                  <Value>Login</Value>
           </Variable>
    </Environment>
    可以使用手工导入,也可以使用LoadFromFile自动导入
     
    总结:
    优点是当对象的一些属性变更后,脚本更容易维护。
    比如说对于一个通用对象,比如save, reset, cancel等按钮,一个页面有3个,30个页面就有90个对象,
    假如save变成保存,reset变成重置,cancel变成取消,那么对象库就会产生很大的变动。
    而使用了描述性编程只需要在导入的XML文件中修改一个值就可以了。
    当然描述性编程的作用远远不止这些,这次只是抛砖引玉,希望大家共同进步。
  • (转)QTP 经常要用到的程序和函数

    2008-12-20 10:38:44

    1. 创建一个vbs文件:TestVbs.vbs
    内容如下:
    '##################################################################################
    '##################################################################################
    Sub CloseWeb()

    '         此处可以用到描述性编程,把先期打开的IE窗口全关闭
    Dim WinIe,Ie,i,m
    Set WinIe=descrīption.Create()
    WinIe("regexpwndtitle").value=" Microsoft Internet Explorer"  '所有页面的regexpwndtitle属性值都是" Microsoft Internet Explorer",也可以用
    其他属性
    Set Ie=desktop.ChildObjects(WinIe)
    m=Ie.count
    For i=1 to m
            Ie(i-1).close                 ' 0为最后打开的一个,可关闭打开的几个,,循环改成for i=1 to m
    Next
    End Sub
    '##################################################################################



    function TestVbs(format)
            msgbox "参数是" & format
    end function


    '#################################################################
    '#################################################################
    '往文件里面写内容
    '第一个参数 文件的路径
    '第二个参数:写入的内容
    '第三个参数:写入的格式("Appending/Writing")
    ' See also "FileSystemObject"
    Sub Write2File(FilePath,content,style)
       Dim fso,f
       Dim stl
            If Ucase(style)="APPENDING" Then
                    stl=8
            else
                    if Ucase(style)="WRITING" then
                                    stl=2
                    else
                                            reporter.ReportEvent 1,"参数错误","Writing <" & FilePath &">:<"& content &">With<" & style. & ">"
                                    Exit Sub
                    end if
            End If  
       Set fso=CreateObject("scrīpting.FileSystemObject")
       Set f=fso.OpenTextFile(FilePath,stl,true)
       'content="写入的第一行内容"
       f.WriteLine(content)
       f.Close
       Set f=nothing
       Set fso=nothing

    End Sub
    '#################################################################




    '#################################################################
    '#################################################################
    ' 连接
    数据库子程序
    ' 第一个参数:根据数据库的类型,设计连接字符串(参见udl文件)
    ' 第二个参数:连接数据库之后,进行查询的相应语句
    ' 第三个参数:查询记录返回到res
    Sub OpenDB(conn,sql,res)
       Set cnn=CreateObject("adodb.connection")
       cnn.open conn
       Set res=CreateObject("adodb.recordset")
       res.open
    sql,cnn,1,1
       
    End Sub
    '#################################################################




    '#################################################################
    '#################################################################
    ' 关闭数据库的连接
    sub CloseDB
       Set res=nothing
            Set cnn=nothing
    end sub
    '#################################################################

    2. QTP导入这个TestVbs.vbs 文件:
    菜单:Test-->Setting-->Resource
    在“Associated Library Files” 添加入该文件
    这里建议可以使用 相对路径,如..\TestVbs.vbs

    3.
    测试封装的子程序:
    用“Run from steps”运行模式(专家视图 右键,第四个菜单项,脚本从光标处运行)
    在QTP 中添加测试代码:

    CloseWeb()    '实现关闭当前所有的IE窗口
    stop


    ' 调用外部函数 Write2File
    Write2File "c:\File.txt","Writhing a Line","Writing"
    Write2File "c:\File.txt","Appending a Line","Appending"
    Write2File "c:\File.txt","Appending a Line","Appending!"   ' 参数不正确
    Write2File ".\vbs\File.txt","Appending a Line","Appending"
    stop


    '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ' 设置连接数据库所需要的初始值,包括:
    ' conn :数据库连接字符串
    ' sql:查询的SQL语句
    ' res:查询的返回记录

    Dim conn,sql,res
    conn="Provider=MSDASQL.1;Persist Security Info=False;Data Source=QT_Flight32"
    sql="select * from Orders"
    Set res=nothing

    ' 调用外部子程序 OpenDB 进行连接数据库
            OpenDB conn,sql,res
                    'msgbox res.RecordCount&"行," & res.fields.count & "列"
                    res.MoveFirst
               ' res.MoveNext    没有它的话,记录就成了死循环
              
                    'reporter.ReportEvent 2,"测试连接数据库","数据库获取数据:" & res.fields(0)

            RowCount=res.RecordCount
            ColumnCount=res.fields.count
            While not res.eof
                    Record=""
                    For i=0 to ColumnCount-1
                            Record=Record & ":" &res.fields(i)
                    Next
                            Record=mid(Record,2)
                            reporter.ReportEvent 2,"数据库记录:",Record
                    res.MoveNext
            Wend
      
    ' 调用外部子程序 CloseDB关闭数据库
            CloseDB
  • (转)QTP中Link的解决办法

    2008-12-20 10:31:03

    Dim aa,bb,cc,dd

    aa=Browser("CYBRE - OREV Concluded").Page("CYBRE - OREV Concluded").WebTable("Date Received").RowCount'先获得表格的行数

    bb="200802-7501-024"'设置的变量

    For i=1 to aa
        cc= Browser("CYBRE - OREV Concluded").Page("CYBRE - OREV Concluded").WebTable("Date Received").GetCellData(i,5)'得到表格中单元格的值
      msgbox cc
      If (bb=cc) Then'进行比较
       msgbox bb
       dd=i'获得变量所在的行
       Exit for
      End If
    Next
    msgbox dd
    Browser("CYBRE - OREV Concluded").Page("CYBRE - OREV Concluded").WebTable("Date Received").ChildItem(dd,8,"Link" , 0).Click'根据变量所在的行去点击相应单元格中的链接。

    '如果当前也没有,先在最外层增加多少页的循环,然后在内层的循环中,可以增加else,进行翻页。

  • (转)在QTP中随机取下拉菜单的值

    2008-12-20 10:25:32

    摘要:产生期望的随机数来选取到动态的下拉菜单的值。
    关键字:随机数;GetROProperty
            有网友在论坛上提出问题,在使用QTP中如何随机选取动态的下拉菜单。在此笔者总结了一些测试经验,利用51testing的登录界面(http://bbs.51testing.com/logging.php?action=login)作为测试页面进行讲解。
            首先我们拿登录页面中的  安全提问  这个下拉菜单作为测试对象。
             

            我们可以先录制一段选取下拉菜单的脚本。
            Browser("51Testing软件测试论坛 测试 | 软件测试\").Page("51Testing软件测试论坛 测试 | 软件测试").WebList("questionid").Select "您个人计算机的型号"。
            备注:无

            这边有个技术处理就是使用#加数字来选择我们的下拉菜单。
            Browser("51Testing软件测试论坛 测试 | 软件测试").Page("51Testing软件测试论坛 测试 | 软件测试").WebList("questionid").Select "#2"
            备注:这个方法在论坛上也出现过,比较适合这个例子。

            下面我们要取得下拉菜单中选项的个数。
            Browser("51Testing软件测试论坛 测试 | 软件测试").Page("51Testing软件测试论坛 测试 | 软件测试").WebList("questionid").GetROProperty ("items count")
            备注:这边使用GetROProperty,应该算比较常见的,所以不多做解释。

            接下来是要个随机函数,参考帮助。
    Randomize
    x=RandomNumber (0,2)
            备注:这边是随机生成0-2之间的三个数字中的一个。

            我们可以把随机函数写成function,方便以后使用。
    Function Get_Ran(i)
       Randomize
      Get_Ran=RandomNumber (0,i)
    End Function
            备注:这边需要注意的就是使用了函数返回值

            最后我们把脚本整合起来
    Function Get_Ran(i)
       Randomize
      Get_Ran=RandomNumber (0,i)
    End Function


    Get_Count=Browser("51Testing软件测试论坛 测试 | 软件测试").Page("51Testing软件测试论坛 测试 | 软件测试").WebList("questionid").GetROProperty ("items count")
    Ran_Number=Get_Ran(Get_Count-1)
    Browser("51Testing软件测试论坛 测试 | 软件测试").Page("51Testing软件测试论坛 测试 | 软件测试").WebList("questionid").Select "#"&Ran_NumberBrowser("51Testing软件测试论坛 测试 | 软件测试").Page("51Testing软件测试论坛 测试 | 软件测试").WebList("questionid").GetROProperty ("items count")
    Browser("51Testing软件测试论坛 测试 | 软件测试").Page("51Testing软件测试论坛 测试 | 软件测试").WebList("questionid").GetROProperty ("items count")
            备注:需要注意的就是在下拉菜单选择的时候从#0开始计算的,所以随机数字从0开始,传入的值也需要减去1。

            题外话:这边主要是使用QTP自带的随机数字函数这个方法来实现随机选择下拉菜单的内容,其实这个随机数字可以开展到随机字符串。因为我们经常会有一些输入域的测试,有的就需255个字节,多的就更可怕,使用随机函数能大大减少我们的工作量。而下面这个例子是实现在abc这三个字母中随机取出来拼成字符串。
    Function makestring(inputlength)
    If IsNumeric(inputlength) Then
    For I = 1 To inputlength
    'you may add a random function here
    A = Array("a","b","c")
    Randomize
    x=RandomNumber (0,2)
    B = A(x)
    makestring =makestring +B
    Next
    msgbox ("output the string:"&makestring )
    else
    msgbox ("error format:"&inputlength)
    End If
    End Function
    Call makestring("8")

  • (转)QTP的分页,另一种方法

    2008-12-20 10:21:55

    '功能:分页
    '说明:对于需要调用此方法的使用者,可以自己改造,例如对于
    ' 检查页面值时,可以使用While...Wend 语句,判断当前页是否包括
    '如果没有点击下一页或者上一页。

    'intTotal_Page 总页数 intCur_Page 当前页
    '************************************************************************
     Public Sub Pagination ()
        Reporter.ReportEvent micDone ,"调用 Pagination ()","Start"
     intTotal_Page=Browser("name:="&strBrowserName).Page("title:="&strPageName).Frame("title:="&strFrameName).WebElement("html id:=total_page").GetROProperty("innertext")
        msgbox  intTotal_Page
     intCur_Page=Browser("name:="&strBrowserName).Page("title:="&strPageName).Frame("title:="&strFrameName).WebElement("html id:=cur_page").GetROProperty("innertext")
     msgbox  intCur_Page
        If (intTotal_Page=0and intCur_Page=0)or (intTotal_Page=1and intCur_Page=1) Then
       Reporter.ReportEvent micpass ,"分页","没有分页"
      End If
      if  (intCur_Page<intTotal_Page)  then
       Browser("name:="&strBrowserName).Page("title:="&strPageName).Frame("title:="&strFrameName).Image("file name:=pages_go.gif").Click
       end if
      If  (intTotal_Page= intCur_Page) then
       Browser("name:="&strBrowserName).Page("title:="&strPageName).Frame("title:="&strFrameName).Image("file name:=pages_back.gif").Click
       end if 
        Reporter.ReportEvent micDone ,"调用 Pagination ()","End"
    End Sub

  • (转)Qtp的Database check point

    2008-12-20 10:15:05

    Qtp很强大,强大在它的定制性上,许多控件的属性,都可以灵活地进行运行时动态定义取值。

        对鄙人来说,比较感兴趣它的check point,特别是里面的数据库测试点部分。

        案例:如果我们需要测试某一条选定的记录,那check point中的constant部分就可以实现了,这一点比较简单,不过实际测试过程中我们会遇到许多复杂的情况,比如Qtp附带的flight程序中页面显示的单条购票的总价Total值是否计算正确?

        分析测试需求,我们发现首先需要了解flight的数据库结构,我们能够在flights表中找到航班单价,能够在orders表中找到定票数量和航班的等级属性class(定义一等,商务,经济舱),数据库中没有保存total值,这时候我们就不能直接光用Database check point对数据库进行数据比较了,经过考虑,有2种思路可以实现测试需求。

        1.正向测试:使用Qtp录制一段插入记录的动作,然后修改脚本,参数化航班信息(random使数据更真实),在一个循环中不断插入记录,同时取下显示界面上的total值,再设置Database check point进行total值和从表中取出值计算后结果的比较。

        2.反向测试:利用原有已经存在表中的数据进行测试,录制利用记录号打开记录的动作,修改脚本,利用一个循环遍历所有存在记录,同时取下显示界面上的total值,再设置Database check point进行total值和从表中取出值计算后结果的比较。

        实行时的难点在于:

        1.Database check point的预期值和实际值都是动态变化的,需要参数化

        2.界面上的total取值中含有价格符号以及小数精度。eg:(¥3.00)

        3.反向中的循环次数会有意外(如果记录中存在删除的记录,则就会有记录号不连续的情况)

        最终考虑选取正向测试方案,参数化插入记录属性。

        在循环中取到total的text,使用Environment("total")= trim(CSng(mid(var,2)))来处理该值

        var是getroproperty的输出,mid去除¥符号,CSng转换成单精度数,trim去除多余的0(3.80会成3.8;2.00会成2)

        再设置一个环境变量(保存动态 select 命令)

        Environment("select")="select a.Ticket_Price*b.Tickets_Ordered*choose(b.class, 3, 2, 1) from Flights a, Orders b where a.Flight_Number=b.Flight_Number and b.Order_Number="&tordnum

        tordnum是从界面上取出的插入的order number,choose函数替换输出class,整句sql语句计算得出该条记录正确的总价。

        在循环插入的循环体最后插入Database check point,预期值参数化成Environment,选择total,然后再去资源选项resources中修改这个check point的source部分,将其也参数化成Environment,选择select,这样整个check point就会动态地进行循环判断。

        最终得到我们的测试报告,从result中查看结果!

  • (转)QTP学习笔记

    2008-12-19 16:57:56

    1、连接数据库查询例子,无参数化
    //
    查询收文操作,通过数据库查询记录数是否正确
    //1
    、输出记录数值,例如78  2、获取输出的记录数值  3、连接数据库,查询记录数
    4
    、输出记录数值和从数据库中查询记录数值,相比较,相等则成功,不等则失败
    Browser("
    湛江信息化测试登录").Page("湛江东兴石油企业有限公司办公自动化系统").Frame("mainFrame").Output CheckPoint("78")
    Dim mm
    'mm=DataTable.GlobalSheet.GetParameter("mainFrameOutput_Text_out").Value  
    //
    注释,获取datatable值与DataTable("mainFrameOutput_Text_out", dtGlobalSheet)一致
    mm=DataTable("mainFrameOutput_Text_out", dtGlobalSheet)
    MsgBox mm
    Dim res,cmd,sql
    Set res=createobject("adodb.recordset")
    Set cmd=createobject("adodb.command")
    Cmd.activec
    Cmd.CommandType = 1
    sql="select count(*) from oa_receivebumf  where BUMFNAME
    like '%收文测试%'"
    'sql="select  count(*)  from oa_receivebumf  where BUMFNAME='"&nn&"'"
    //
    注释,sql语句,等于时sql语句
    // sql="select  count(*)  from oa_receivebumf  where BUMFNAME like '%nn%'" //like
    sql语句
    Cmd.CommandText = sql
    Set res = Cmd.Execute()
    //msgbox res("name")

    MsgBox res(0)
    If   Cstr(res(0)) = Cstr(mm)Then
          Reporter.ReportEvent micPass, "test\",   "
    查询成功"     
      else
    Reporter.ReportEvent micfail, "test",   "
    查询失败"
    End If
    Set res = nothing
    Set cmd.ActiveConnection = nothing
    Set Cmd= nothing
    2
    、登记用户,查看是否登记成功
       //
    登记用户,查询用户是否存在在数据库中
         1
    参数化 2、取参数化值  3、查询语句中,赋值给查询条件
         4
    、从数据库中查询出用户名,与参数化中值做比较
       
    脚本如下:
    Browser("
    测试登录").Page("办公自动化系统").Frame("mainFrame_2").WebEdit("addressVO.name").Set DataTable("p_Text", dtGlobalSheet)
    Dim xname
    xname=DataTable("p_Text", dtGlobalSheet)
    MsgBox  xname


    Dim res,cmd,sql
    Set res=createobject("adodb.recordset")
    Set cmd=createobject("adodb.command")
    Cmd.activec
    Cmd.CommandType = 1
    sql="select  name from address_list t where name ='
    "&xname&"'"
    Cmd.CommandText = sql
    Set res = Cmd.Execute()
    'msgbox res("name")
    MsgBox res(0)
    Set res = nothing
    Set cmd.ActiveConnection = nothing
    Set Cmd= nothing

     

     

    第二部分

    1Datatable方法GetRowCount
       DataTable.GetSheet("Action1").GetRowCount   //
    获取总行数
      
    使用如:
      CountNum=DataTable.GetSheet("Action1").GetRowCount

    2
    Datatable方法SetNextRow
       DataTable.GetSheet("Action1").SetNextRow     //
    取得下一行
       datatable.setcurrentrow(n)   //
    取得某一行

    3
    Datatable方法getcurrentrow    //获得当前行数
       
    例如:datatable.getcurrentrow

    4
    、获取datatable
       4.1  DataTable("p_Text", dtLocalSheet)  //
    取得datatable中参数名称为:p_Text的值
       4.2  DataTable.GlobalSheet.GetParameter("p_Text").Value   //
    获取参数值方法和DataTable("p_Text", dtLocalSheet)一样
       
    例如:xname为变量,dim xname
       xname=DataTable("p_Text", dtLocalSheet)
       xname=DataTable.GlobalSheet.GetParameter("p_Text").Value

    5
    datatable.value("num")只在global形式下的一种省略形式;完整形式是:
    datatable.value("num",dtlocalsheet)

    -----
    向某一列的单元格赋值:
    datatable.value("column_name",dtlocalsheet)="nanjing"

    6
    、字符转换Cstr
       dim mm
       Cstr(mm)

    7
    、获取对象属性名称用法:
    GetRoProperty----
    从应用程序界面上获取对象属性(即,是脚本运行时,获取的对象动态属性值)
               
    例如:获取对象库中index属性值,似乎只能用GetToProperty,因为应用程序界面上对象没有该属性,只是
          QTP为识别该对象创立的描述属性;
    GetToproperty----
    从对象库中描述对象的属性,静态值
    GetToProperties----
    获取用于标识对象的属性集;对于这个集合,有count等属性方法

    8
    、如果弹出对话框就获取上面提示信息并与表中的信息对比,不统一证明弹出的提示出错,主要用来验证
    if browser("web_name").dialog("dialog_name").exist(1) then'
    如果不出现=false
         error_message=browser("web_name").dialog("diaglog_name").static("
    用户密码错误!".getRoproperty("text")
       if error_message<>(datatable.value("error_info"))then
             msgbox(error_message)
          end if
         browser("web_name").dialog("diaglog_name").close
      end if
    这里总结了两点技巧:
      一是:对于dialog中,虽然提示信息对象名称是"用户密码错误",但如果信息对象名称是该用户不存在,不用更改会自动识别,我想主要是录制第一遍时,用户密码错误只是让运行时能找到这个控制,而不管它是什么内容,因为在对象仓库中,text不是决定该对象的属性
       
    二是:如果对于提示信息比较长的,可以用mid(error_message,n,m)取一部份特征提示信息进行验证,这样我想可以节省处理时间,又可以避免长度以及空格等字符的处理

    9
    、数据库检查点模块:
    sub database_check
    set con=createobject("adodb.connection")
    con.open "Descrīption=IBM_ODBC;DRIVER=SQL Server;SERVER=IBM;UID=sa;"&_
                     "PWD=123456;APP=Quick Test Pro;WSID=IBM;DATABASE=IBM_table"
    'access
    方式:con.open "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=d:\test.mdb"
    'Orocle
    方式:con.open "DRIVER={Oracle in OraHome92};SERVER=CESHI;UID=CND_TEST;PWD=CND;DBQ=CESHI;DBA=W;APA=T;EXC=F;XSM=Default;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;GDE=F;FRL=Lo;BAM=IfAllSuccessful;MTS=F;MDI=Me;CSR=F;FWC=F;PFC=10;TLO=O;"
    set record=createobject("adodb.recordset")
    sql="select*from ibm_one_table"
    record.open sql,con
    DO
    if(record("ibm_table_column")="kai")then'//
    查找表格中有多少kai
    num=num+1;
    end if
    record.movenext
    loop until record.eof=true
    record.close
    set record=nothing
    con.close
    set con=nothing
    end sub

    10
    "is+*"类型function
    isarray'
    是否是数组
    isconnected'
    判断QTP是否连接到TD
    isdate'
    是否是合法的日期类型
    isempty'
    判断是否初始化
    isNull'
    判断是否为空值
    isNumeric'
    判断是否是数字型
    isobject'
    判断是否一个功能对象
    isready'
    判断设备是否准备就绪
    isRootFolder'
    是否是根目录

    11
    for方法1,参数化时选择:dtLocalSheet
    Dim CountNum
    CountNum=DataTable.GetSheet("Action1").GetRowCount
    For i=0 to CountNum-1
    ----xunhuanti------
    DataTable.GetSheet("Action1").SetNextRow    //
    使用SetNextRow方法
    Next

    12
    for方法2,参数化时选择:dtLocalSheet
    dim countNum
    countNum = DataTable.GetSheet("Action1").GetRowCount
    For i=1 to countNum
    DataTable.GetSheet("Action1").SetCurrentRow(i)  //
    使用SetCurrentRow(i)方法
    ―――ddd―――
    next
    13
    while方法1,参数化时选择:dtLocalSheet
    Dim CountNum,i
    i=1
    CountNum=DataTable.GetSheet("Action1").GetRowCount
    While i<=CountNum
    ------xuhuanti---
    DataTable.GetSheet("Action1").SetNextRow
    i = i+1
    Wend

    14
    while方法2,参数化时选择:dtLocalSheet
    Dim CountNum,i
    i=1
    CountNum=DataTable.GetSheet("Action1").GetRowCount
    While i<=CountNum

    DataTable.GetSheet("Action1").SetCurrentRow(i)
    ----xuhuanti---
    i = i+1
    Wend

     

     

    第三部分

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

    datatable.getsheet("Action1")
    datatable.setcurrentrow(i)

    ----xunhuanti----
    loop

    16
    、取对象属性(Property)值

    Dim usname
    usname =Browser("
    测试登录").Page("办公自动化系统").Frame("mainFrame_2").WebEdit("addressVO.name").GetRoProperty("Value")   '获取对象属性(Property)值,如PropertyValue
    MsgBox usname

    17
    、取得要删除的id,并删除
    'url
    在查看该新增记录的信息页面对象中取得,所以录制的时候,登记,查看(修改),删除

    Dim strUserid,id,strId

         id=Browser("
    测试登录").Page("办公自动化系统").Frame("mainFrame_4").GetROProperty("url") 'url这个属性值中存在我需要删除记录的ID信息
      strId=Mid (id,instr(60,id,"=")+1)  '
    这一步是把需要的id值取了出来,例如:strId=Mid (id,instr(1,id,"=")+1)
         strUserid =strId  'strUserid
    是我要删除的记录前的复选框属性值当中的ID信息
    Browser("
    测试登录").Page("办公自动化系统").Frame("mainFrame").WebCheckBox("value:="&strUserid).Set "ON" 这样就把想删除的记录选中了。
    Browser("
    测试登录").Page("办公自动化系统").Frame("mainFrame").WebButton(" ").Click '这样就删除掉啦,呵呵

    17.2
    通过数据库取得id值,并赋值进行删除

    Browser("
    测试登录").Page("办公自动化系统").Frame("mainFrame_2").WebEdit("addressVO.name").Set DataTable("p_Text", dtGlobalSheet)
    Browser("
    测试登录").Page("办公自动化系统").Frame("mainFrame_2").WebEdit("addressVO.address").Set DataTable("p_Text1", dtGlobalSheet)

    Browser("
    测试登录").Page("办公自动化系统").Frame("mainFrame_2").WebEdit("addressVO.unitTel").Set DataTable("p_Text2", dtGlobalSheet)

    Dim xname,address,unitTel
    xname=DataTable("p_Text", dtGlobalSheet)   '
    datatable中取值
    address=DataTable("p_Text1", dtGlobalSheet)
    unitTel=DataTable("p_Text2", dtGlobalSheet)

    Dim res,cmd,sql
    Set res=createobject("adodb.recordset")
    Set cmd=createobject("adodb.command")
    Cmd.activeconnection="DRIVER={Oracle in OraHome92};SERVER=HKORACLE;UID=USER22;PWD=ZJLH;DBQ=HKORACLE;DBA=W;APA=T;EXC=F;XSM=Default;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;BTD=F;BAM=IfAllSuccessful;NUM=NLS;DPM=F;MTS=T;MDI=Me;CSR=F;FWC=F;FBS=60000;TLO=O;"
    Cmd.CommandType = 1
    'sql="select  addressid from address_list t where name ='"&xname&"'"
    'sql="select  

  • (转)数据库和环境变量

    2008-12-19 16:57:50

    利用数据库(DB)

    在当今IT界没有数据库的话,大家想象一下,会是什么样子?

    Mercury公司为QTP也提供了对数据库的数据进行操作的方法,同时也有数据库检查点的设置,我在测试过程中,就是使用SQL Server2000进行数据管理的。目前我还没有学习到Oracle(^_^,很惭愧)。

    利用数据库来进行测试数据的管理有几个优点:1. 数据便于统一管理2. 方便修改、查询3. 便于进行对已经修改的数据进行数据库检查点设置来检查数据是否修改成功4. 脚本的可重用性提高 5. 脚本与数据分离,脚本的维护工作量减少

    QTP的脚本调用数据库中的数据有2种方法:1. 利用用户DSN数据源 2. 直接连接数据库

    1.       本地没有创建数据源的方式
    DRIVER=SQLServer;SERVER=数据库IP地址;UID=用户名;PWD=密码;APP=Microsoft Office 2003;WSID=本地主机名;DATABASE=数据库名

    2.       本地已创建数据源的方式
    DSN=数据源名称;UID=用户名;PWD=密码;APP=Microsoft Office 2003;WSID=数据库的主机名;DATABASE=数据库名

    注:虚线框中的是引用别人的

           你可以建立一个DBFunction.vbs文件,将你编制的数据库调用的函数(如:连接、查询、修改。。。)全部放在这个文件中(建议:DBFunctions与你的公共函数不要放在一起),然后通过QTP引用资源文件,在菜单中选择“文件”——>“设置”——>“资源”,然后将你的函数库文件添加到这个关联函数库文件下。这样你的脚本就可以使用这些函数了。

           当然,有人不愿意这样做。还有一个方法,就是在每个脚本的开头使用下面的脚本代码引用你自定义的函数库文件:

           ExecuteFile “FileName”  //例如:ExecuteFile “D:\Functions\DBFunction.vbs”

           当数据库中的数据需要修改时,调用完修改数据库数据的函数后,在此函数后的一行脚本脚本可以添加数据库检查点来检查你刚才修改的数据是否成功,数据库检查点的方法见:QTP的帮助文档。

    OK,这样就设置完成了数据库的数据驱动方式

    利用环境变量

    我觉得Mercury公司考虑事情很周到,连环境变量的功能也添加进去了(不知道我高兴是不是有道理,目前的知识面不是很广,大家不要见怪啊)

    环境变量的的适用范围就是本测试,本测试中的所有操作都可以调用。

    环境变量有2种,一种是QTP的内置变量,一种是用户自定义的变量。内置变量是可以直接就可以用,自定义环境变量需要在菜单中选择“文件”——>“设置”——>“环境”,在变量类型中选择“用户自定义”,然后进行添加,可以对添加的变量全部导出,导出的文件为.xml格式的文档。既然可以导出,那么必然可以导入.xml文件,你可以在该对话框中的选中“从外部文件导入”,然后添加其文件路径即可。(当然这些操作都可以直接使用脚本来实现,如:Environment.LoadFromFile(“FileName”))

    例如:在桌面建立一个Var.xml,如下

    -<Environment>    //以这个开始的内部都是定义环境变量,直到以</Environment>结束

    - <Variable>                           // 变量定义起始标识

                     <Name>aa</Name>               // 变量名称

                     <Value>11</Value>               // 变量值

            </Variable>                            // 变量定义结束标识

    - <Variable>

                     <Name>bb</Name>

                     <Value>22</Value>

            </Variable>

    - <Variable>

                     <Name>cc</Name>

                     <Value>33</Value>

                  </Variable>

      </Environment>

    然后导入本测试的环境变量文件中,在专家视图里编写下面的脚本代码:

    Dim aParam3

    aParam3=Environment.Value(“aa”)          // 调用环境变量

    msgbox aParam3

    运行测试,会输出”11”

           OK,完成环境变量的初级知识的学习。

  • (转)QTP中常有的VB函数

    2008-12-19 16:39:11

    Left 函数
            返回 Variant (String),其中包含字符串中从左边算起指定数量的字符。

    语法

    Left(string, length)

    Left 函数的语法有下面的命名参数:

    部分     说明
     
    string  必要参数。字符串表达式其中最左边的那些字符将被返回。如果 string 包含 Null,将返回 Null。
     
    length  必要参数;为 Variant (Long)。数值表达式,指出将返回多少个字符。如果为 0,返回零长度字符串 ("")。如果大于或等于 string 的字符数,则返回整个字符串。
     

    说明

    欲知 string 的字符数,使用 Len 函数。

    注意    LeftB 函数作用于包含在字符串中的字节数据。所以 length 指定的是字节数,而不是要返回的字符数。

    Mid 函数
            从字符串中返回指定数目的字符。

    Mid(string, start[, length])

    参数

    string

            字符串表达式,从中返回字符。如果 string 包含 Null,则返回 Null。

    Start

            string 中被提取的字符部分的开始位置。如果 start 超过了 string 中字符的数目,Mid 将返回零长度字符串 ("")。

    Length

            要返回的字符数。如果省略或 length 超过文本的字符数(包括 start 处的字符),将返回字符串中从 start 到字符串结束的所有字符。

    说明

            要判断 string 中字符的数目,可使用 Len 函数。

            下面的示例利用 Mid 函数返回字符串中从第四个字符开始的六个字符:

    Dim MyVar

    MyVar = Mid("VB脚本is fun!", 4, 6) 'MyVar 包含 "scrīpt"。

    注意   MidB 函数与包含在字符串中的字节数据一起使用。其参数不是指定字符数,而是字节数。

     

    Len 函数
            返回字符串内字符的数目,或是存储一变量所需的字节数。

    Len(string | varname)

    参数

    string

            任意有效的字符串表达式。如果 string 参数包含 Null,则返回 Null。

    Varname

            任意有效的变量名。如果 varname 参数包含 Null,则返回 Null。

    说明

            下面的示例利用 Len 函数返回字符串中的字符数目:

    Dim MyString

    MyString = Len("VBscrīpt") 'MyString 包含 8。

    注意   LenB 函数与包含在字符串中的字节数据一起使用。LenB 不是返回字符串中的字符数,而是返回用于代表字符串的字节数。

     

    Right 函数
            从字符串右边返回指定数目的字符。

    Right(string, length)

    参数

    string

            字符串表达式,其最右边的字符被返回。如果 string 参数中包含 Null,则返回 Null。

    Length

            数值表达式,指明要返回的字符数目。如果为 0,返回零长度字符串;如果此数大于或等于 string 参数中的所有字符数目,则返回整个字符串。

    说明

            要确定 string 参数中的字符数目,使用 Len 函数。

            下面的示例利用 Right 函数从字符串右边返回指定数目的字符:

    Dim AnyString, MyStr

    AnyString = "Hello World"      ' 定义字符串。

    MyStr = Right(AnyString, 1)    ' 返回 "d"。

    MyStr = Right(AnyString, 6)    ' 返回 " World"。

    MyStr = Right(AnyString, 20)   ' 返回 "Hello World"。

    注意   RightB 函数用于字符串中的字节数据,length 参数指定返回的是字节数目,而不是字符数目。

     

    InStr 函数
            返回某字符串在另一字符串中第一次出现的位置。

    InStr([start, ]string1, string2[, compare])

    参数

    start

            可选项。数值表达式,用于设置每次搜索的开始位置。如果省略,将从第一个字符的位置开始搜索。如果 start 包含 Null,则会出现错误。如果已指定 compare,则必须要有 start 参数。

    string1

            必选项。接受搜索的字符串表达式。

    string2

            必选项。要搜索的字符串表达式。

    compare

            可选项。指示在计算子字符串时使用的比较类型的数值。有关数值,请参阅“设置”部分。如果省略,将执行二进制比较。

    设置

            compare 参数可以有以下值:

    常数
     值
     描述
     
    vbBinaryCompare
     0
     执行二进制比较。
     
    vbTextCompare
     1
     执行文本比较。
     

    返回值

    InStr 函数返回以下值:

    如果
     InStr 返回
     
    string1 为零长度
     0
     
    string1 为 Null
     Null
     
    string2 为零长度
     start
     
    string2 为 Null
     Null
     
    string2 没有找到
     0
     
    在 string1 中找到 string2
     找到匹配字符串的位置
     
    start > Len(string2)
     0
     

    说明

    下面的示例利用 InStr 搜索字符串:

    Dim SearchString, SearchChar, MyPos

    SearchString ="XXpXXpXXPXXP"   ' 要搜索的字符串。

    SearchChar = "P"   ' Search for "P".

    MyPos = Instr(4, SearchString, SearchChar, 1)   ' 在位置 4 进行的文本比较。返回 6。

    MyPos = Instr(1, SearchString, SearchChar, 0)   ' 在位置 1 进行的二进制比较。返回 9。

    MyPos = Instr(SearchString, SearchChar)   ' 默认情况下,进行的是二进制比较(省略了最后的参数)。返回 9。

    MyPos = Instr(1, SearchString, "W")   ' 在位置 1 进行的二进制比较。返回 0(找不到 "W")。

    注意   InStrB 函数使用包含在字符串中的字节数据,所以 InStrB 返回的不是一个字符串在另一个字符串中第一次出现的字符位置,而是字节位置。

     

    LTrim、RTrim与 Trim 函数
            返回不带前导空格 (LTrim)、后续空格 (RTrim) 或前导与后续空格 (Trim) 的字符串副本。

    LTrim(string)

    RTrim(string)

    Trim(string)

    string 参数是任意有效的字符串表达式。如果 string 参数中包含 Null,则返回 Null。

    说明

            下面的示例利用 LTrim, RTrim, 和 Trim 函数分别用来除去字符串开始的空格、尾部空格、 开始和尾部空格:

    Dim MyVar

    MyVar = LTrim("   vbscrīpt ")   'MyVar 包含 "vbscrīpt "。

    MyVar = RTrim("   vbscrīpt ")   'MyVar 包含 "   vbscrīpt"。

    MyVar = Trim("   vbscrīpt ")   'MyVar 包含 "vbscrīpt"。

     

    Rnd 函数
    返回一个随机数。

    Rnd[(number)]

    number 参数可以是任意有效的数值表达式。

    说明

            Rnd 函数返回一个小于 1 但大于或等于 0 的值。number 的值决定了 Rnd 生成随机数的方式:

    如果 number 为
     Rnd 生成
     
    小于零
            每次都相同的值,使用 number 作为种子。
     
    大于零
            序列中的下一个随机数。
     
    等于零
            最近生成的数。
     
    省略
            序列中的下一个随机数。
     

            因每一次连续调用 Rnd 函数时都用序列中的前一个数作为下一个数的种子,所以对于任何最初给定的种子都会生成相同的数列。

            在调用 Rnd 之前,先使用无参数的 Randomize 语句初始化随机数生成器,该生成器具有基于系统计时器的种子。

            要产生指定范围的随机整数,请使用以下公式:

    Int((upperbound - lowerbound + 1) * Rnd + lowerbound)

            这里, upperbound 是此范围的上界,而 lowerbound 是此范围内的下界。

    注意   要重复随机数的序列,请在使用数值参数调用 Randomize 之前,立即用负值参数调用 Rnd。使用同样 number 值的 Randomize 不能重复先前的随机数序列。

     

    Randomize 语句
    初始化随机数生成器。

    语法

    Randomize [number]

            可选的 number 参数是 Variant 或任何有效的数值表达式。

    说明

            Randomize 用 number 将 Rnd 函数的随机数生成器初始化,该随机数生成器给 number 一个新的种子值。如果省略 number,则用系统计时器返回的值作为新的种子值。

            如果没有使用 Randomize,则(无参数的)Rnd 函数使用第一次调用 Rnd 函数的种子值。

    注意 若想得到重复的随机数序列,在使用具有数值参数的 Randomize 之前直接调用具有负参数值的 Rnd。使用具有同样 number 值的 Randomize 是不会得到重复的随机数序列的。


  • (转)QTP对Excel文件的读写操作

    2008-12-19 16:37:28

    重要方法   ImportSheet后面的参数说明:文件路径,global名字,global 颋x呵??? 
    Function WriteExcel() ⒌:%忋1WA  
       Dim ExcelContent(3) 逷厁蒩?#  
       strFileName = "E:\cntesting.xls"  'Excel文件路径 eO4I=汽u?  
       For j = 0 to 3 罦烗d蔥蔵h  
       ExcelContent(j) = "" 'jM\?vS  
     Next

     ExcelContent(1) = DataTable("I_orderId", dtGlobalSheet) 斊 ?祗J  
     ExcelContent(2) = DataTable("I_orderAmountEqual", dtGlobalSheet) 睆ON彨壠? 
    ' 写数据到Excel文件 kR?t?d蘇  
     Dim Obj, Look, Sheet 麥9囧芆  
     Set Obj = CreateObject("Excel.Application")  镹:}/蝡擝  
     Obj.Application.Visible = True gK?DV席T? 
     Set Look = Obj.WorkBooks.Open(strFileName) u<冈郟"氙X  
     Set Sheet = Look.Worksheets(1) 胑墰旲猠拽  
     For j = 1 to 2 wXV9纸?? 
       Sheet.cells(2,j) = ExcelContent(j) ?:-V鑲?? 
     Next 3?cM_?? 
     Obj.DisplayAlerts = False ?j0贾朝  
     Look.Close(True) ?鞀鄧鵤}? 
     Obj.Quit I璍2鰆? 
     Set Obj = nothing J遴届fg?g  
    End Function

    '--------------------------------------------------------------

    '从Excel读数据 r\i? ? 
    Function ReadExcel() 1iE敡昰qB  
     datatable.AddSheet("Global")' ~9`J褹釋  
     datatable.ImportSheet "E:\cntesting.xls","test\","Global"

     Dim i,RowCount FhnP`/软e? 
     i=0 Y-;宿,/? 
     RowCount=datatable.GetSheet("Global").GetRowCount ' 设置 RowCount 等于 Global中的行数。 ' 脡思Y缿牀  
     msgbox RowCount [羛Yp}t戓  
     Do while i<rowcount P4蟴 ?? 
     i=i+1 汱/9栍? 
     datatable.getsheet("Global") ' ?搆*讈?  
     datatable.setcurrentrow(i) 嶤芠衖阜!  
     msgbox DataTable.GetSheet("Global").GetParameter(i).Value '取得第一列的值 ?昴吻? 
      h;?Y繯歕  
     datatable.setcurrentrow(n) 厖榷z腌]  
     msgbox Datatable.GetSheet("Global").GetParameter(i+1).Value '取得第二列的值 怫錮洎Ac5  
     msgbox datatable.getsheet("Global").getparameter("I_orderAmountEqual").RawValue'取得特定的I_orderAmountEqua列的值 窼??魋? 
     loop hLn幕V塒  
    End Function @湥曷?N|  
    WriteExcel   '写入函数调用 k髣朙p6p?  
    ReadExcel    '读出函数调用

  • (转)如何让QTP在名单列表中勾选出需要的人?

    2008-12-19 16:16:53

    要在一列姓名列表中找出所需要的人,并在其前面勾选上。录制的脚本直接按row来数行数
    '~X$K I,[2D\Dgz138711
    (padb&I+BCl2a/|138711Browser("AA").Window("AB-Web").Page("AB").WebCheckBox("all_2").Set "ON"
    '}p+f0dKq138711Browser("AA").Window("AB-Web").Page("AB").WebCheckBox("all_3").Set "ON"
    ha FlRA)Z:{138711
    Kuq%H$J3|/e138711这也能解决问题,但存在一个潜在隐患:如果姓名列表发生变动,脚本就不正确了。
    2V ]%gk mQ13871151Testing软件测试网"n7~'O7F spWht
    我想一劳永逸。如何能够让QTP自动寻找到目标姓名行,并在其前面完成勾选动作?
    5a~_^o2F138711
    yZ g Z+z138711参见附图:

    我的思路是:
    DifIWu |1387111. 按照innertext属性来找到对应的行,再在对应的复选框里勾上
    ?1s4}UchDe X d1387112. 或者直接按复选框的outerhtml属性来查找、选择。 但spy可以看到outerhtml属性,选到对象库里就看不到这项属性了,不知能否办到51Testing软件测试网)w,]#\}4\.t;Z't

    9Hc/wF)wQ!A138711***********************************************************51Testing软件测试网4gH$M-q$I
    补充1:
    z#~7LTnCfR138711***********************************************************51Testing软件测试网r^H#fe-~%p
    WebCheckBox的value属性是按排序从0递增的
    _!{*CY"r TJ13871151Testing软件测试网I.p/znIn
    另: 在我的环境里用Highlight in Application查看,WebCheckBox是在WebElement里面的.这两个对象的outerhtml属性有一段是相同的,51Testing软件测试网.^;r^,P!}$~.RF2w
    WebChekBox的outerhtml属性:51Testing软件测试网#Xd&Ul G[
    <INPUT type=checkbox value=11 name=all is_used="1" user_name="aaron.gao">51Testing软件测试网4Oy&AD6I.bW
    WebElement的outerhtml属性:
    !o*t_ r,tEP8@A138711<TD><INPUT type=checkbox value=11 name=all is_used="1" user_name="aaron.gao"> aaron.gao </TD>
    +l nwR2R j,g4z*O1r138711而且这段里包含有我需要的user_name51Testing软件测试网s9Ka!yfp
    不晓得能否利用到这一点51Testing软件测试网4C,_K3[!c?

    GI"t&v^JCkCx138711是否可以将outerhtml取出,用正则表达式判断用户名是否在里面,是则选中??51Testing软件测试网8C;^~(?$?(n4_8iy$K:t

    !fxIB*{:DN13871151Testing软件测试网.{a$U pZ:w }
    ***********************************************************
    v];f;JBH7seUi|p138711补充2:
    N X0t5w@N-]3xVG138711***********************************************************51Testing软件测试网xw)F!}(N{i1M+w

    ,q p:G"a H`&^H138711又有一个思路,名单就是个只有一列的表,把这个表的内容取出来查,这样比较好实现.
    u4f^\ h138711
    _I&s Z)l&Q;\+Y4X138711还有,把 WebCheckBox 做为 WebElement 的 ChildItem去操作,似乎可以解决两者关联问题.
    pf k"?%C Gc\13871151Testing软件测试网4gD6p5f`sbl
    不过,这里要设计到VB scrīpt循环语句, ChildItem, 循环次数的设定……51Testing软件测试网w8DCP/]"V
    51Testing软件测试网\1{9y!G,I;_E`
    待我研究下----真给逼上梁山了
    ?C+`Z9q,Dy9]3R:]138711
    *Tf$zs _o4k(K"]138711***********************************************************
    k#rp#i:` L~i138711解答1:
    i%_"a }#r0d&D138711***********************************************************51Testing软件测试网/HOJ2h c"xZ
    51Testing软件测试网v _5U1Z*ws{%_
    吼吼!!!问题解决了!!!
    Iv [ZMm K8[P13871151Testing软件测试网+MsV];h,ON;|"M^
    row = Browser("AA").Window("AA-Web").Page("AB").WebTable("ALL").RowCount51Testing软件测试网(z.\&C0q'f8jR#|
    For i=1 to row -1 51Testing软件测试网 L `}a:Y
        If  Browser("AA").Window("AA-Web").Page("AB").WebTable("ALL").GetCellData(i, 1) = " sheila.shi "    Then51Testing软件测试网 iGXtP_(ND
      Browser("AA").Window("AA-Web").Page("AB").WebTable("ALL").ChildItem(i,1,"WebCheckBox",0).Set "ON"
    7E_Kx4S#y138711(
    F:OXte138711上句也可换为:
    @7M^QK+y'Y/p138711Set ōbj = Browser("AA").Window("AA-Web").Page("AB").WebTable("ALL").ChildItem(i,1,"WebCheckBox",0)
    $nK@0Ru138711obj.Set "ON"
    yXFB}9A6?@138711)
    ZP.P!z Mm138711    Exit for
    ]@'YL/l5p+h138711    End If
    +l'TEB0Wc138711Next51Testing软件测试网-Op/P6D m _,I7SQ
    51Testing软件测试网J _x-?7U;wvAd3?
    下面就是对" sheila.shi "参数化了.51Testing软件测试网 k$Dr Y*a$zq$o
    参数化就用这句:51Testing软件测试网#z:^+u9W.^*B$J2z4{'~4Z

    cS9VhC138711If  Browser("AA").Window("AA-Web").Page("AB").WebTable("ALL").GetCellData(i, 1) = DataTable("ConfCall_All", dtLocalSheet)    Then51Testing软件测试网8Av'RHjZ7?:W

    b5An'U,H9P#HL138711注意:
    *Rt+M UrZ!T#I1387111. WebTable("ALL")必须是包含且只包含所有WebElement的表格, 注意和其他WebTable的区分.
    !Du2[2U S%l5Oh1N }1387112. If语句里=后的 " sheila.shi " 要注意引号里的空格, 是否该有空格可以通过table checkpoint里的configure value来确定.如果和checkpoint里的不一致会找不到目标对象.本环境中引号与姓名之间各有一个空格,参数化后EXCEL表里姓名前后也要各留一个空格。8晓得怎么会这样。
    LvC8PS!w a6]1K13871151Testing软件测试网W|h9B/i#}
    51Testing软件测试网%WGAh)dT;bJ/Pp x

    4?*?ho~%}5d'a138711这是最后一个思路的解决办法. 前面的思路似乎也是可行的.
    *Lcl9{0Sm/`W P138711
    0?9cI4}4X}&? M_138711哪位高手能给出前面思路的解法?

     
    yabest给出了一个根据坐标来定位某个对象相应的WebCheckbox的通用函数,可以一劳永逸的解决类似问题,适合各种情况。(强啊,我的汗呐!)
    8bS2e(aX138711
    '================================================================
    oUjs e7wq\!T`138711' FUNCTION NAME:51Testing软件测试网2P6G{8N;oq
    '        FindCheckBox51Testing软件测试网 g3_sx1Jv
    ' FUNCTION DEscrīptION:
    ~Qd,p~138711'        Find the corresponding webcheckbox of title object in parent object, and output the webcheck
    Nj e.G:_Z-BA/P138711' FUNCTION USAGE:51Testing软件测试网 ]"AAx(Lg
    '        Set parentObject = Browser("ATS Login").Page("ATS Login").Frame("mainRight")
    t+w0\nP g?(J:b138711'        Set titleObject = Browser("ATS Login").Page("ATS Login").Frame("mainRight").Link("test\")
    !odS8a F I2adX9|138711'        ret = FindCheckBox(parentObject, titleObject, checkBoxObject)
    joe#AqzF138711'        checkBoxObject.Set "ON"51Testing软件测试网 J;@*U4W2u V
    ' FUNCTION PARAMETER51Testing软件测试网g n:|Sz M
    '        ParentObject: The parent object of title object and webcheckbox object
    ,Mr @p eq#j5xw^nF138711'        TitleObject:        The title object 51Testing软件测试网6@Mcf _F
    '        CheckBoxObject: [Output Param] Output the corresponding webcheckbox object of title object51Testing软件测试网]._Hr] KYR
    ' FUNCTION RETURN:
    `b{8n)ms]Z W{138711'        0:        Success to find and output the corresponding webcheckbox object of title object51Testing软件测试网3O5V.Wa)PQ
    '        -1:        Fail to find the corresponding webcheckbox object of title object
    ,q8K$j4kB L8v"?I138711' FUNCTION ORIGINAL CREATOR:51Testing软件测试网1J Y.vG w][ Ub*~
    '        yabest
    5t:Rt@&ot138711' FUNCTION CREATION DATE:51Testing软件测试网2L:q!y2d?
    '        2007-08-30
    w\BR-ke138711' FUNCTION UPDATE HISTORY:
    :b4^X:z Sa0CQ8T/@138711'===============================================================51Testing软件测试网6iq k gV-H*L
    Function FindCheckBox(ByVal ParentObject, ByVal TitleObject, ByRef CheckBoxObject)51Testing软件测试网NU^,o ^+v/d

    $Zz Q4\(u*AS(z138711        Dim titleObjectY1, titleObjectY2, curChildObjectMidY51Testing软件测试网7B"?Z?m9Ew
            Dim checkBoxDesc, childObjects51Testing软件测试网'K i _ X `Ow!a{4pZ
            Dim childNum, childIndex, findIndex
    W-j#aXF!ak~e13871151Testing软件测试网A]5D.s/H
            'Get the title object's top/bottom y position
    o)S_C/R138711        titleObjectY1 = CInt(TitleObject.GetROProperty("abs_y"))51Testing软件测试网4IX[T]
            titleObjectY2 = CInt(TitleObject.GetROProperty("abs_y")) +  CInt(TitleObject.GetROProperty("height")) 51Testing软件测试网.n2i8q0?J4R:c1_[
    51Testing软件测试网@ Xy oB$[
            'get all webcheckbox objects
    *p%P#mef f1b_'[V138711        Set checkBoxDesc = Descrīption.Create()51Testing软件测试网 e'|;Se-Ei"J-K5s
            checkBoxDesc("micclass").Value = "WebCheckBox"51Testing软件测试网;u$w;pQf9MIR3[
            Set childObjects = ParentObject.ChildObjects(checkBoxDesc)
    5IP6v*z B13871151Testing软件测试网wv7@y1T;\(f
            'search the webcheckbox according y position. 51Testing软件测试网9L*}K0QW2Wv
            childNum = childObjects.Count51Testing软件测试网VM5q:UZ~u8_p:B
            findIndex = -1
    mwdvmav138711        For childIndex = 0 to childNum-151Testing软件测试网3DS,F9K:[ pO:h
                    Set curChildObject = childObjects(childIndex)51Testing软件测试网#D$O dM1C"Gt
                    curChildObjectMidY = CInt(curChildObject.GetROProperty("abs_y")) + CInt(curChildObject.GetROProperty("height"))/251Testing软件测试网 E'a3bx+r
                    'the webcheckbox should be:   (y+height/2) in [titleObjectY1, titleObjectY2] area
    R a3~)xdy UU3z138711                If curChildObjectMidY>=titleObjectY1 and  curChildObjectMidY<= titleObjectY2 Then51Testing软件测试网4H4s*IHB/X:G
                            findIndex = childIndex
    r6u*y`,Xc*Y+q4\138711                        Exit For
    b$g(s#GB-Br138711                End If
    8W[s"P~ y2? G138711        Next
    )E-}.gqW&x xb13871151Testing软件测试网 h*s*D-Q.}
            'if not found, return fail
    6?\Hu9J v,{138711        If findIndex = -1 Then
    vJR4b+m+i138711                FindCheckBox = -151Testing软件测试网hN'yB"ur
                    Exit Function51Testing软件测试网m%?2aOr3d!zg)w(aE+_u
            End If
    +mFL;_;?:V13871151Testing软件测试网1D6h.Mlc| ]E
            'if found, return success51Testing软件测试网,J3Et A'l)]
            Set CheckBoxObject = curChildObject51Testing软件测试网2V8K_*F8b:Z `
            FindCheckBox = 0
    kAD-kyE g meY$A138711        51Testing软件测试网u9X^,\6G0O
    End Function
     
     
    black.sam又给出了个答案,的一眼没看明白,似乎是描述性编程,先拷贝过来。
    dim obj_desc
    #\!n3HBQp b138711set obj_desc = Descrīption.Create
    6?X9X E g138711Obj_desc("html tag").value = "INPUT"
    1e$Z5B2K1WI%A;hGD138711Obj_desc("type").value = "checkbox"
    Oq1X r|gzt e138711dim allcheckbox,onecheckbox51Testing软件测试网q0RQ ~'X3i
    set allcheckbox = Browser("Browser").Page("Page").ChildObjects(obj_desc)
    "] Pe-emW a-xX)c138711for each onecheckbox in allcheckbox51Testing软件测试网.}R/\'h}b)d%m+s
      onecheckbox.set "ON"51Testing软件测试网u6~t Gici3J$|U
    next51Testing软件测试网-T j @I#a)Gcx

    k*}m @7l [E|138711black.sam在http://blog.csdn.net/black_sam/archive/2007/09/05/1772656.aspx里写了一篇关于descrīptive programming的
    4dL#hFp S138711解释一下我对black脚本的理解:51Testing软件测试网f7EcxWzC
    第一二行是定义了一个object:obj_desc即我们要用的check box(第一次看到Descrīption.Create理解可能有偏差);
    mX)` l#tbU G138711第三四行是为obj_desc的两个属性heml tag和type分别赋值;51Testing软件测试网-TEd/V k/{(Q
    第五六行定义变量allcheckbox为obj_desc的所有子对象集;51Testing软件测试网 i1| v7K-B
    第七八九行为一个for each-next循环,在allcheckbox定义之内的onecheckbox都会执行第八行set "ON"的命令,即在对应check box里打勾,不断循环、打勾,直到循环结束,所有目标项都被选择了。程序结束51Testing软件测试网 mXU\t
    51Testing软件测试网#e"|`)z/``7cd$D2{ a
    不知是不是程序没写完全,我没明白51Testing软件测试网-Cv#o} oN4]
    1.为什么没有对onecheckbox赋值?难道它只是充当一个指针的作用?(偶没编程经验)
    -H%_s i0x1387112.从哪个变量来控制/输入我要选出的对象?莫非是对html tag这个属性进行参数化?那循环时Obj_desc("html tag").value = "INPUT"只运行过一遍,如何保证所有预定目标项都被选择了?
     
    wlcking :
    要勾选多个就多用几次for each next,对onecheckbox参数话就行了,for each next就是在一个集合里查找值,查找到了就执行for each next下的语句51Testing软件测试网:yQ)],p)B6m \7fu
    看雪时节 :
    1:首先在OR里添加Table。
    M$|^ ^5gT-l-?M1387112:利用childItem(,“WebCheckBox”,0).set “On”51Testing软件测试网~]\i|R%S9rh
       其中还要用到webTable的RowCount、GetCellData方法
    51Testing软件测试网_"y-{\y8E
  • (转)QTP基础代码

    2008-12-19 15:50:35

    1 生产随机数列
    第一种方法
    randomize'更新反回的数据
    funcation rand(k,n)
    n="int((k-1)*rnd+1) rand=n
    end funcation
    第二种方法
    n="randomnumber.value(1,255)

    2 当运行到表中的某一行,自动导出表中的所有数据
    row=datatable.getcurrentrow
    if row="5" then
      datatable.export("d:\data.xml")
    end if

    3 参数化密码
    webedit("txtpass").setsecure"sdsdf...."
    如果参数化密码,可以直接在数据表中写入未加密的密码,它会自动识别,即不用把setsecure改为set

    4 如果弹出对话框就获取上面提示信息并与表中的信息对比,不统一证明弹出的提示出错,主要用来验证
    if browser("web_name").dialog("dialog_name").exist(1) then'如果不出现="false     

    error_message=browser("web_name").dialog("diaglog_name").static("用户密码错误!".getRoproperty("text")
        if error_message<>(datatable.value("error_info"))then 
             msgbox(error_message) 
         end if
         browser("web_name").dialog("diaglog_name").close 
    end if
    这里我总结了两点技巧:
      一是:对于dialog中,虽然提示信息对象名称是"用户密码错误",但如果信息对象名称是“该用户不存在”,不用更改会自动识别,我想主要是录制第一遍时,“用户密码错误”只是让运行时能找到这个控制,而不管它是什么内容,因为在对象仓库中,text不是决定该对象的属性
         二是:如果对于提示信息比较长的,可以用mid(error_message,n,m)取一部份特征提示信息进行验证,这样我想可以节省处理时间,又可以避免长度以及空格等字符的处理

    5 datatable.value("num")只在global形式下的一种省略形式;完整形式是:
    datatable.value("num",dtlocalsheet)
    -----向某一列的单元格赋值:
    datatable.value("column_name",dtlocalsheet)="nanjing"
    -----取得某一行具体值:
    datatable.setcurrentrow(n)
    msgbox(datatable.getsheet("global").getparameter("column_name").Rawvalue)
    或者kk=datatable.Rawvalue("column_name","action1")
    ----在run-time时,动态添加表格与数据
    kk=datatable.addsheet("sheet_name").addparameter("column_name","value").name;

    7 wintreeview一些操作
    选择一个条目:wintreeview.select(item)'根是0
    根的名称:wintreeview.getitem(0)

    8 数据库检查点模块:
    sub database_check
    set con="createobject(""adodb.connection")
    con.open "Descrīption="IBM_ODBC;DRIVER=SQL" Server;SERVER="IBM;UID=sa;""&_
                     "PWD="123456;APP=Quick" Test Pro;WSID="IBM;DATABASE=IBM_table""
    'access方式:con.open "DRIVER="{Microsoft" Access Driver (*.mdb)};DBQ="d:\test.mdb""
    'Orocle方式:con.open "DRIVER="{Oracle" in OraHome92};SERVER="CESHI;UID=CND_TEST;PWD=CND;DBQ=CESHI;DBA=W;APA=T;

    EXC=F;XSM=Default;FEN=T;QTO=T;FRC=10;FDL=10;LOB=T;RST=T;GDE=F;FRL=Lo;BA

    M=IfAllSuccessful;MTS=F;MDI=Me;CSR=F;FWC=F;PFC=10;TLO=O;""
    set record="createobject(""adodb.recordset")
    sql="select*from ibm_one_table"
    record.open sql,con
    DO
    if(record("ibm_table_column")="kai")then'//查找表格中有多少kai
    num=num+1;
    end if
    record.movenext
    loop until record.eof="true record.close
    set record="nothing con.close
    set con="nothing end sub

    9 换行符
    vbcr----chr(13)回车符// vblf----chr(10)换行符 
    vbcrlf----chr(13)+chr(10)结合//type(chr(13)就相当于按了一上键盘上的enter

    10  Run from step有两种方式:
    在Keyword View模式会从本步骤运行到所有action结束
    在expert view模式仅会将本action运行结束

    11 由于对象属性原因,无法识别对象
    -----对于对象属性是变化的,可以参数化/或者用正则表达式
    -----报匹配多个对象错误,可以spy查看对象,添加一个该对象另一个唯一标识属性
    -----有时可以删除对象的变化的属性来解决识别问题
    ------对于多个完全相同的对象,可以采用添加index,location,createtime等特殊属性来识别
      (index:按照程序源码,绘制对象的先后标识对象,所以与其它相同对象是相互依赖,当其它对象发生
      变化后,原先的所有对象index属性要发生变化,开始是0;如index:="0;         location:根据对象的位置进行确定,从上到下,从左到右;
      CreateTime:按照对象被浏览器打开的先后标识对象)
    ------另外换一种思维方式,采取等效的方法;比如用键盘代替鼠标或用操作系统本身特性去解决问题

    12  对系统文件的操作
    -------从系统的文件中获取信息及删除文件
      get_file_infor("c:\she.mpg")
       function get_file_infor(url)
        dim fso,f
        set fso="createobject(""scrīpting.filesystemobject")
        set f="fso.getfile(url)"
        f.name:f.size:f.type:f.datacreated'///获取文件信息
        fso.deletefile(url)'/////删除文件
       end function
    --------获取文件夹里所有文件信息
    get_folder_infor("c:\kai")
    function get_folder_infor(folder)
    dim fso,f,f1,n
    set fso="createobject(""scrīpting,filesystemobject")
    set f="fso.getfolder(folder) set fc="f.files for each f1 in fc
    select case f1.name
    case"kai.mpg","she.mpg","dd.mp3"'//检查文件夹里是否含有这些文件
    end select
    next
    end function

     

    13   等待某个对象出现方法
    y="......waitproperty(""visible",true,10000)

     

    14   防程序中断方法
    On error resume next
    On error goto handle

     

    15  数组的应用:
    name="array(1,2,""aa","bb")
    name(2)="aa"

     

    16  正则表达式应用模板
    进行日期YYYY-MM-DD的格式检查 :
    Function RegExpTest(patrn, strng)
      Dim regEx, Match, Matches      ' Create variable.
      Set regEx = New RegExp         ' Create a regular expression.
      regEx.Pattern = patrn         ' Set pattern.
      regEx.IgnoreCase = True         ' Set case insensitivity.
      regEx.Global = True         ' Set global applicability.
      Set Matches = regEx.Execute(strng)   ' Execute search.
      For Each Match in Matches      ' Iterate Matches collection.
        RetStr = RetStr & "Match found at position "
        RetStr = RetStr & Match.FirstIndex & ". Match Value is '"
        RetStr = RetStr & Match.Value & "'." & vbCRLF
      Next
      RegExpTest = RetStr
    End Function
    date_pattern="^((((19|20)(([02468][048])|([13579][26]))-02-29))|((20[0-9][0-9])|(19[0-9][0-9]))-((((0[1-9])|(1[0-2]))-((0[1-9])|(1\d)|(2[0-8])))|((((0[13578])|(1[02]))-31)|(((01,3-9])|(1[0-2]))-(29|30)))))$"
    result_message=RegExpTest(date_pattern, inputbox("请你输入要检查的时间:"))'用其它正则表达式更改此处
    Select case result_message
    Case ""
             msgbox("你输入的日期格式与标准不匹配")
    case else  MsgBox(result_message)
    end select

     

    17   返回一个字符串在另一字符串中的位置
    instr(string1,string2)

     

    18   有时回放出现找不到对象时,可能不是由于你的代码问题,而是由于你的操作系统等设置问题;
    举例说明1:
    比如:你录制一个选择磁盘中的文件动作
    会录制为:
    .winlistview("  ").drap 46,99
    .winlistview("  ").draponitem "she.mp3"
    下次录制的时候,如果你的系统文件改为不显示扩展名,下次执行的时候,QTP就找不到she.mp3,只能找到she;
    举例说明2:
    有时由于不同操作系统以及不同的ie,导致有些窗口不能识别,比如在2000下弹出的网页对话框的标题是:
    “web对话框",而在2003上是”网页对话框"

     

    19  "is+*"类型function
    isarray'是否是数组
    isconnected'判断QTP是否连接到TD
    isdate'是否是合法的日期类型
    isempty'判断是否初始化
    isNull'判断是否为空值
    isNumeric'判断是否是数字型
    isobject'判断是否一个功能对象
    isready'判断设备是否准备就绪
    isRootFolder'是否是根目录

     

    20 Action之间的参数传递
    例如:在Action1中,有如下代码:
    out_str="This is out_string"
    RunAction "Action2",oneIteration,out_str
    在Acton2中,在其step->Action Properties中的,input参数栏,加入out_str后,
    msgbox(parameter("out_str")),就能正确显示参数了 

     

    21 Wscrīpt.Shell的一些应用
    set WshShell ="CreateObject(""Wscrīpt.Shell")
    WshShell.SendKeys "{ENTER}"     '模拟键盘进行操作
    WshShell.AppActivate "Calculator"             '启动应用程序

     

    22 获取对象属性名称用法:
    GetRoProperty----从应用程序界面上获取对象属性(即,是脚本运行时,获取的对象动态属性值)例如:获取对象库中index属性值,似乎只能用GetToProperty,因为应用程序界面上对象没有该属性,只是QTP为识别该对象创立的描述属性;
    GetToproperty----从对象库中描述对象的属性,静态值
    GetToProperties----获取用于标识对象的属性集;对于这个集合,有count等属性方法

     

    23 FireEvent的使用可以对一个对象进行更复杂的操作
    如:FireEvent("onfocus")   '使一个控件获取焦点
         FireEvent("ondblclick")  '实现双击/也可以在事件设定中针对该对象事件响应  

     

    24 模板的应用
    -----新建一个文本,输入一些新建Action时常包含的信息,然后保存为ActionTemplate.MST文件,
     并复制到QTP/dat目录下;这样每次新建action都会包含固定的信息了;
    例如:
    '-------------------脚本说明---------------
    '产品版本:      __Build(  )
    '测试员:
    '编写日期:
    '测试功能:
    '脚本类型:
    '被测试对象初始状态:
    '进展程度:
    '基本思路:
    '主要功能函数:
    '历史修改:
    '没解决的问题:
    '--------------------脚本内容-------------

     

    25 在对象库中,两个对象有时不能通过更改属性或命名来达到两个对象完全一致的替换;
    在web-mod项目中,我在对象库里添加了一个自动含有index标识属性的对象,然后每次通过SetToproperty来改变
    index值,对对象进行数据驱动,使其操作另一个对象,但脚本始终操作原先index属性值的对象;后来,把该对象
    删除掉,重新添加一个不自动含有index标识属性的该类对象,然后,手工添加,index标识属性,后来脚本能正常工作了,可见两次的对象属性完全一致,但形成方式不一样,导致的结果往往也不一样;

     

    26 childobject的应用
    childobject可以返回界面上满足条件的对象集合,而且与对象库里是否有这些对象无关,这就可以简化对象库;
    返回的对象集合的count方法可以返回对象个数,这就可以通过下标对单个对象进行操作;在出现index标识对象时
    可以进行运用
    如:Set m_WinCheck="Descrīption.Create()       m_WinCheck("nativeclass").Value="Button"
          set All_WinCheck="Window(""").Dialog("").Childobject(m_WinCheck)
          n="All_WinCheck.Count()      for i="0" to n-1
          All_WinCheck(i).Set "ON" 
          next

  • (转)QTP常见问题解答

    2008-12-19 15:46:58

    QTP常见问题解答一
    1.      运行错误:不能识别对象(Cannot identify object)
    出现了这个错误时,就表示当前被测程序的窗口中没有符合条件的对象。
    出现这种错误,可能的原因有以下两种:
    >>> 对象此时在程序中没有显示或不存在。
    >>>在程序中存在该对象,但是它的描述在后来发生了改变,导致与对象仓库中存储的信息不匹配,从而QTP无法识别对象。
    果你正遇到“Cannot identify object”的问题,解决方法见1.1。
     
    1.1 如何去识别对象描述(Idenfirying Test Object Descrīption Problems)
        如果你能在被测程序中看到对象,但仍出现了“Cannot Identify Object”错误信息,这就表示仓库中对象的描述与程序中对象的描述一定存在着差异。
        解决对象描述问题的第一步是找到差异,最简单的方法是将仓库中对象的属性值与程序中对象的属性值进行比较。(仓库中对象的属性值可在Object Repository窗口中查看,程序中对象的属性值可用Object Spy功能查看。)
    比较仓库中对象的属性值与程序中对象的属性值的操作见1.3。
    在完成比较后,是否发现存在差异?
    如果是,请参考1.4;
    如果否,请参考1.5。
     
    1.2 处理对象丢失问题(Solving Missing Object Problems)
    在运行脚本时,QTP偿试进行某种操作,而该操作的对象在程序中却没有出现,出现这种情况的原因有以下几种:
    >>> 对象不再存在。对象已经被从程序中删除。
    解决方法:见1.2.1。
    >>> 对象还没有装载。
    解决方法:见1.2.2。
    >>>当前的程序页面(或窗口)不正确,不是对象所在的页面(或窗口)。
    解决方法:见1.2.3。
    >>>前一个步骤没有正确执行。
    解决方法:见1.2.3。
    1.2.1 解决对象不再存在的问题
    如果对象已经不再在被测程序中存在,则应在脚本中修改或删除相关步骤。
    1.2.2 解决对象装载超时的问题
    如果对象丢失的原因是因为没有足够的时间装载,偿试以下解决方案:
    a.对于Web对象,增加Browser Navigation Timeout(File>Setting>Web页签)时间。
    b.在包括该对象的步骤前使用Wait语句,让QTP在执行该步骤之前等待一段时间。
    1.2.3 检查前面步骤的执行情况
    如果是因为打开了错误的页面(或窗口)导致对象丢失问题,或因为前一步骤执行措误导致对象丢失问题,则请按以下方法检查原因:
    a. 如果怀疑在完成脚本后,被测程序又发生了改变,则检查对象的继承关系以及对象描述。参考1.1。
    b. 如果怀疑脚本错误,则检查脚本的每一个步骤。你可能是遗失了某个步骤,也可能是使用了不正确的方法或参数。
    QTP常见问题解答二
    1.3 测试对象的属性值与Run-time对象的属性值的比较(Comparing Test Object and Run-Time Object Property Values)
    根据以下的步骤比较测试对象与Run-time对象的属性值:
    1) 进入Obecjt Repository窗口(Resources>Object Repository),选择对象。
    2) 用笔记下对象的class以及它的各个属性及属性值。
    3) 打开被测程序,并打开包含被测对象的页面或窗口。
    4) 在QTP中选择菜单Tools>Object Spy或点击Object Spy按钮,打开Object Spy对话框。
    5) 选择“Test Object Properties”选项。
    6) 点击右上角的按钮(带有手图标的),这时QTP窗口以及Object Spy对话框都被最小化。
    7) 在程序页面(或窗口)中点击目标对象,恢复Object Spy对话框,并在对话框中显示对象及其父对象(以树的形式显示),并在Properties页签中显示当前对象的属性及属性值。
    8) 这时Object Spy对话框的Properties页签中显示Run-time对象的所有属性,在此查看对象的class,以及它的属性及属性值,并将它与第2步中记下的内容进行比较。
     
    1.4 解决对象描述存在的问题(Solving Object Descrīption Problems)
        如果发现仓库中对象的属性值与程序中对象的属性值存在不同,你应该判断这个不同是个别对象的问题,还是其它同类对象也存在相同的问题。
    是所有(或多个)同类对象都存在问题吗?
    如果是,则参考1.6
    如果否,则参考1.7
     
    1.5 关于父对象描述的识别问题(Identifying Parent Object Descrīption Problems)
    对象的识别还与它所继承的父对象有关。
        如果你能在被测程序中看到对象,而且程序中对象的属性值与仓库中对象的属性值也是一致的,但仍然遭遇到了“Cannot identify object”错误,则这个错误可能与它的父对象有关(如仓库中父对象的属性值与程序中父对象的属性值不一致),也可能是仓库中的对象与程序中对象的继承关系不相同导致的。
    要判断是继承关系中的哪个父对象出现了问题,请偿试下面的方法之一:
    >>>重新录制对象,比较新旧对象的父对象。
    欲了解如何完成比较,参考1.8。
    >>>对继承关系中的每个父对象,分别插入一个Exist语句,并运行该部分脚本。
    欲了解如果创建Exist语句,参考1.9。
    注:你也可以使用Object Repository窗口中的Highlight in Application功能,在被测程序中定位对象。
    一旦找到了存在问题的父对象,接下来偿试以下方法:
    >>>修复存在问题的父对象的描述。方法见1.4。
    >>>在专家视图的模式下,查找所有继承存在问题的实例并进行修正。
    举例:1.8.1。
     
    1.6 解决某类对象的识别问题(Soving Object Identification Problems for a Test Object Class)
        如果你发现某类对象的对象描述对于被测程序来说都不是很合理,或你预期到对象描述中的某属性值是经常变化的,你可以在Object Identification对话框中改变该类的识别属性的设置,或定义该类的Smart Identification设置并启用Smart Identification机制,这样QTP就可以唯一识别对象了。
     
    1.7 解决单个对象的描述问题(Solving Individual Test Object Descrīption Problems)
    选择下列方法之一来解决对象的描述问题:
    >>>如果被测程序中对象描述发生了改变,并且你也清楚改变的内容,并且该改变是永久性或长期性的,你可以直接手工修改仓库中对象描述中的相关属性值。
    >>>如果被测程序中的对象的属性值依赖于前面的步骤或其它对象,则将该属性值参数化,这样就可以使用其它步骤的输出值为属性值。
    >>>如果属性值的组成部分中,部分是固定的,部分是动态改变的,则可以将属性值设计为正则表达式。
    >>>如果属性值是遵循某种规则变化的,或者是不可预期的,则从对象描述中移除该属性,并向对象描述中添加一个或多个属性以便于QTP进行对象识别。
    >>>If you can only access the information on the property values during the run session, you can create and use functions that use programmatic descrīptions to identify the object using property values retrieved earlier in the run session.
    For more information on programmatic descrīptions, see Using Programmatic Descrīptions.
    >>>如果在录制过程中对象是唯一的,但现在程序中出现了两个或多个描述相同的对象,但是它们在页面(或窗口)中的位置不相同,则应在Object Properties或Object Repository窗口中,向对象描述中添加一个ordinal identifier(index或location)。
     
    1.8 重新录制对象,以判断父对象描述是否存在问题(Re-recording an Object to Identify Parent Object Descrīption Problems)
    根据下面的指引,来判断父对象的问题。
    通过重新录制对象,来判断它的父对象是否存在问题:
    1) 打开浏览器或程序,来到包含被测对象的页面或窗口。
    2) 在关键字视图模式,选择最后一个组件(component),或在专家视图模式,将光标放在最后一个脚本步骤的下面。
    3) 点击Record按钮,或选择Automation>Record。
    4) 点击(或操作)页面或窗口中的目标对象。
    5) 点击Stop按钮,或选择Automation>Stop,完成步骤添加。
    6) 右击新添加的步骤,并选择Object Properties右键菜单。
    7) 在Object Properties对话框中,点击Repository,打开Object Repository窗口,并选中了新对象。注意记下该对象的继承关系。
    8) 在Object Repository窗口中找到旧的对象(即存在问题的对象),将它的继承关系与新对象的继承关系进行比较。
    通过比较,可以检查到新旧对象是父对象的描述存在不同,还是它们的继承关系根本就不同。
    a. 如果是父对象的描述问题,则修改父对象的描述。参见1.4.
    b. 如果是对象的继承关系不正确(即具有不同的父对象)引起的问题,则在脚本中找到所有使用该继承关系的实例,将它们替换为正确的继承关系。
    举例:参见1.8.1。
     
    1.8.1 举例
        假设有一个带有Frame的网站,你录制了一个操作针对Image对象“Poster”的操作步骤。在Object Repository窗口,你可以Image对象的继承关系如下所示:
    MyCompany(Browser)
        MyCompanyPage)
            Main(Frame)
                 Poster(image)
        当你运行脚本时,网页看起来没有什么不同,但是识别Image对象时却出现了“Cannot identiry object”的错误提示。当你重新录制操作步骤,然后在Object Repository窗口中查看新的Image对象时,发现该对象的继承关系如下所示:
    MyCompany(Browser)
        MyCompanyPage)
             Poster(image)
        从中可以看出,Frame已经从Web Page中移除,所以尽管Image对象“Poster”的描述没有发生任何改变,但它的继承关系已经改变了。
        在Object Repository窗口,你可以看到新旧Image对象“Poster”是两个完全不同的对象:旧的位于已经被移除的Frame对象之下,而新的则直接位于Page“Mycompany”对象之下。
        修复这个问题,可以在脚本步骤中将旧的对象替换为新的对象。
        为了保持Object Repository窗口的整洁,你应删除那些已不再存在的对象(如本例中的Frame)。
     
    1.9 创建Exist语句,以判断父对象的描述是否存在问题
        QTP在录制发生在某个对象上的操作时,也会同时去了解对象以及它的继承关系。因此,如果在运行过程中,QTP不能识别继承关系中的任何一个父对象,都会导致目标对象的识别失败。
        使用带有Exist方法的Msgbox语句,可以方便的检查出是继承关系中的哪个父对象出现了问题。
        假设在运行下面脚本时,你遇到了“Cannot identify Object”错误信息(但是可以确定对象仓库中Link对象的描述与当前程序中对象的描述是完全一致的):
    Browser("Yahoo!").Page("Yahoo!").Link("Arts & Humanities").Click
    你可以在该语句前面插入以下语句:
    Msgbox Browser("Yahoo!").Exist
    Msgbox Browser("Yahoo!").Page("Yahoo!").Exist
    Msgbox Browser("Yahoo!").Page("Yahoo!").Link("Arts & Humanities").Exist
    然后你从头开始运行脚本,发现第1行语句运
        但是,当QTP运行到第2步时,就弹出信息框,内容为“False”,表示不能找到Page object。这就证明Page对象存在问题。
        确定了出现问题的父对象以后,修复该问题。参见1.4。
    QTP常见问题解答三
    2.      运行错误:对象不唯一(The object is not unique)
    在被测页面或窗口中的同一父对象下,找到多个与仓库中对象描述相符的Run-tim对象。
    请确定是只有个别对象存在此问题,还是此类对象的所有对象(或部分对象)存在此问题。
    此类对象的所有对象(或部分对象)都存在此问题吗?
    如果是,参考2.1;
    如果否,参考2.2。
     
    2.1 为某对象类设置能唯一识别对象的描述规则(Configuring Unique Test Object Descrīptions for a Test Object Class)
        如果你发现某类对象的对象描述都不足以唯一识别对象,你可以在Object Identification对话框中,改变该类的识别属性的设置,或定义该类的Smart Identification设置并启用Smart Identification机制,这样QTP就可以唯一识别对象了。
     
    2.2 设置通唯一识别对象的对象描述(Creating a Unique Test Object Descrīption for an Object)
    查看当前对象的描述,并偿试在程序中找到其它具有相同描述的对象并查看它们的描述。
    >>>如果你找到了可以将它们区别开来的一个或多个属性,则修改仓库中对象的相关属性(如向描述中添加属性等),以使QTP在运行时可以唯一识别它。
    >>>如果它们的识别属性完全相同,则在对象描述中为对象添加一个ordinal identifier(index或location)。
     
    3.      运行错误:找不到父对象(Parent not found)
    识别对象时,会先识别它的父对象是否正确。如果遇到“Parent not found”的错误信息,请偿试以下解决方法:
    >>>修复出现问题的父对象的描述。参见1.4。
    >>>在脚本中找到继承关系不正确的实例,并修改为正确的继承关系。例如1.8.1。
    QTP常见问题解答四
    4.      运行错误:无效的参数(Invalid arguments)
    一个或多个方法的参数是无效的。
    参数无效可能是参数类型错误,也可能是参数个数不正确。
    根据以下建议,找到方法的正确语法:
    >>>在Keyword模式,如果方法包括参数,则在Value栏会显示该方法的参数提示。
    >>>在Expert模式,如果方法包括参数,则当你插入方法然后按下Shift+Ctrl+Space键时,QTP会显示该方法的参数的提示信息。(注:只有在Editor Options对话框的General页签中打开了Statement completion功能时才可以看到参数的提示信息。)
     
    5.      运行错误:不能识别item(Cannot identify item)
    QTP不能识别方法参数中指定的列表或树对象的item时,请确认指定的item是否存在于对象之中。
    >>>如果item不存在,则删除相关脚本步骤,或修改item。
    >>>如果item存在,但被测程序中它的名字发生了改变,则修改item的名称,或在脚本中使用item的index而不是名字(如“#4”)。注意,不同的对象或方法,它们使用index的语法可能不同。
     
    6.      运行错误:对象的item不唯一(The object’s item is not unique)
    在列表或树对象中,可能有多个名字相同的item。
    在这种情况下,可以指定item使用index(例如“#4”)。
     
    7.      运行错误:运行失败(Test run failed)
    测试运行失败,还有可能是其它未知错误造成的。检查出现错误时的脚本步骤。
    如果错误出现在执行检查点或输出值时,请查阅关于检查点与输出值的帮助。
    如果错误出现在使用外部文件时,如数据库表、数据库、环境变量文件、或关联仓库文件等,则检查是否可以正常获取并使用文件,或这些文件的存储格式是否正确。
    如果错误出现在完成某个脚本动作时,请参考QuickTest Object Model Reference帮助,以确认方法或函数的使用是否正确。
    如果错误出现在执行一个标准的VBscrīpt语句时,参考Microsoft VBscrīpt Reference以获得帮助。

  • (转)QTP脚本例子汇总

    2008-12-19 15:40:57

    例一:(来自测试者家园)

    以下语句指示 QuickTest 选中 Itinerary 网页上的所有复选框:

    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

    例二:(来自51testing)

    目标如下:
    sL zx SH1387111.    脚本需要处理成功和失败的用户的登陆
    I+Y`jd^-{4` W1387112.   数据驱动

    设计开发脚本如下:


    4S Kpc.| o;o138711第一步录制脚本如下
    K-iCZ]-N V [138711Browser("智能变电巡检仪系统 4.0").Page("智能变电巡检仪系统 4.0").WebEdit("txtLoginName").Set "吕巍" 51Testing软件测试网1Y.v|dq*E
    Browser("智能变电巡检仪系统 4.0").Page("智能变电巡检仪系统 4.0").WebButton("登 录").set ""
    4V`^i0l!xL138711Browser("智能变电巡检仪系统 4.0").Page("Page").Syn
    X@t'w dD:Wpj {0v138711Browser("智能变电巡检仪系统 4.0").Close

    以上为录制的正确的用户名,下边录制错误的用户名51Testing软件测试网'T i \@?
    Browser("智能变电巡检仪系统 4.0").Page("智能变电巡检仪系统 4.0").WebEdit("txtLoginName").Set "xx"
    u9F_6O Wao'{*YJ138711Browser("智能变电巡检仪系统 4.0").Page("智能变电巡检仪系统 4.0").WebButton("登 录").set "" 51Testing软件测试网*P&U5Fc!i!M!I
    出现错误提示“该用户不存在”

    第二步 增强脚本

    现在需要设计的是一套脚本驱动所有的测试数据,这样可以驱动所有的用例数据,qtp中提供了datatable。51Testing软件测试网AT0\"~ LR hb
    但是有数据驱动也要做一个事情就是如何处理错误的用户名和正确的用户名,如何结合起来呢?51Testing软件测试网jaU(GV:\j3Z#R} n
    这里我把datatable看作存放测试用例的地方,里面放入测试数据,还放入测试的预期结果。这样我的设计已经出现雏形了。
    7k5L+pk3G_ ~138711我把datatable设计为三列

    username  password status51Testing软件测试网pE,h)QVu0[&q*GG-|
    吕x               
    sq f(QW2W138711xxx       xxxx     该用户不存在

    第三列放入最后执行的结果,我设计的是空为成功登陆,如果有信息就用实际运行的结果和这一列对比.好了万事俱备只欠东风了

    修改脚本如下:51Testing软件测试网&P1Ik6sR&W p"|m2?
    Dim iStatus

    Browser("智能变电巡检仪系统 4.0").Page("智能变电巡检仪系统 4.0").WebEdit("txtLoginName").Set DataTable("username", dtLocalSheet)
    /Kb3? T/B138711Browser("智能变电巡检仪系统 4.0").Page("智能变电巡检仪系统 4.0").WebButton("登 录").set DataTable("password", dtLocalSheet)
    h$p]%Q i R;uUFx138711iStatus = DataTable("status", dtLocalSheet)

    If   iStatus=""  Then51Testing软件测试网 E+cD e x
      Browser("智能变电巡检仪系统 4.0").Close
    7_8y#F^$m138711End If

    51Testing软件测试网mis` }CGyE
    If   iStatus="该用户不存在"    Then51Testing软件测试网R!Sfd.O;ha1w"[;k
         Reporter.ReportEvent micFail, "登陆", "登陆失败." 51Testing软件测试网-_*Ems"X`0V
    End If

    Browser("智能变电巡检仪系统 4.0").Close

    第三步,设置脚本运行过程

    打开 tests-〉settings51Testing软件测试网 O Iy%Xj^1|
    设置RUN TAB页面下 Datatable iterations中 Run On all rows

    这样就完成了整个脚本的设计工作,以上通过一个简单例子吧脚本的设计和软件的功能结合起来,达成脚本的设计效果。

    例三:(来自MSN 秀)

    [功能]
    +~S qa Lr3m R ^#?c138711    1.启动一个VB的windows application。设置好Excel文件和QTP的安装路径。51Testing软件测试网;]}n"{&jn1\X6aX
        2.启动脚本进行测试,测试代码是QTP自带的订票系统。

    [脚本的参数设定]
    oB[)y5c4I138711    脚本中有2个参数-EXCEL文件和QTP安装路径从VBS文件传入。在QTP中设定如下:51Testing软件测试网`eES$lin
        1.在KeyWord view界面。在Action1上点击右键,选Action properties,弹出 Action properties对话框。在其中添加2个入参。如下图所示:51Testing软件测试网yS/e DW2q4f5k!R-h$@


    eAm \A-~*}13871151Testing软件测试网 Fj l6z Y6^Xa${'t.c
    2.设置测试参数51Testing软件测试网,S%O/x3xf!x
        Test->Test Settings->Parameters.设置2个入参。如下图所示:
    q$i\_&fn138711

    3.将Action参数和Test参数关联起来
    ,[u@;ib138711     1.在KeyWord view界面。在Action1上点击右键,选择Action Call properties51Testing软件测试网O6H(`(j#`?i;Gk?

    Z^!_"K Hp%n7U13871151Testing软件测试网9@ m?Ce#}

    51Testing软件测试网'h}6{W'b@ b2H2}

    hp-Hfl l3o138711点Vaiue51Testing软件测试网~R/rY2fN

    在脚本中使用以下语句可以取得2个入参:51Testing软件测试网1PDc O]X9S t
        filename= Parameter("InAction1")51Testing软件测试网:a*z:F?;pPR!B
        QtpPath= Parameter("InAction2")51Testing软件测试网 C\Vv3b?%X
    [脚本部分]
    8a6h0}(^.m?F138711Dim conn,rst,filename,coboname51Testing软件测试网\B8U9W4IA _
    Dim user,passwd
    F `~-x6Q4S138711'filename="C:\DATA.xls"
    a V'~;X6R)j^v8]138711filename= Parameter("InAction1")51Testing软件测试网[ LK&?M"W9]
    QtpPath= Parameter("InAction2")51Testing软件测试网2|$qu r n
    'datatale.import(filename)
    6f!tp{t|138711Set conn= createobject("ADODB.Connection")51Testing软件测试网Ba%bW/Id+S
    'msgbox filename51Testing软件测试网`+P9d!F`
    conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source="&filename&";Extended Properties='Excel 8.0;hdr=yes'"51Testing软件测试网#_6zMw6Ed%h&S s"~c
    Set rst= createobject("ADODB.Recordset")

    '  Excelファイルのデータを読み込む51Testing软件测试网 s-OseG|M
    rst.Open "select  *   from [sheet1$] " ,conn,1,1

    ' table WHCT0717のデータをセットする
    @|#y'Ee1]-?O138711 While Not rst.EOF  51Testing软件测试网F U)n f;?g'F
       systemutil.run  QtpPath&"\samples\flight\app\flight4a.exe",""51Testing软件测试网,Zp$_[4].uM
        user = rst.fields("user")51Testing软件测试网3qK |6c_:V2Ju
     passwd = rst.fields("password")51Testing软件测试网qNs;J(D[[H
     Dialog("ログイン").WinEdit("代理店名:").Set  (user)51Testing软件测试网~ O(_:xE/^c
       ' Dialog("ログイン").WinEdit("代理店名:").Type  micTab51Testing软件测试网&F`H'Anp
     Dialog("ログイン").WinEdit("パスワード:").set(passwd)51Testing软件测试网 A#[6tn"`
     Dialog("ログイン").WinButton("OK").Click
    Hwc`bJ138711 reporter.filter=051Testing软件测试网 oyC%EJii i"d
     If ( Dialog("ログイン").Dialog("フライト予約").WinButton("OK").Exist(2) )  Then
    AO ja6s0VKt{138711    text = Dialog("ログイン").Dialog("フライト予約").GetVisibleText
    Q\$@ iHH(|3|:C\A138711 reporter.ReportEvent micFail ,"Load Error",text
    `3X5T6~5S})f$`138711  Dialog("ログイン").Dialog("フライト予約").WinButton("OK").Click
    1M N3yW?#v"|g,L138711  Dialog("ログイン").WinButton("キャンセル").Click
    ^S y/iyK/b$?.@138711 else
    ;a8I8[8~6j3C138711   Window("フライト予約").close51Testing软件测试网U6k4zQK'y gZg
     end if
    /sI \NB+aJ:]-R138711     rst.MoveNext
    G5l1D PA?&yN W138711   Wend
    +Y-r#WCs.`138711 rst.close51Testing软件测试网z v;A!c'Z;p9N'A
    51Testing软件测试网a3joL.Nj-G:i
       脚本部分最主要的是注意QTP对象的选择和使用。(Tools-->object Repository 对象的添加和删除)

    [VB application]51Testing软件测试网f&x |D4YV
         以下是Button1单击的触发事件
    j'n5u5HJ.ZV F;Y2W138711     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    c8d"x3M*l3Y138711        Dim qtApp
    [RQf7e(R zu+~138711        Dim qtTest 
    !_A3Q"t kZv|;n138711        Dim qtResultsOpt 51Testing软件测试网x A5Sl4r/Zcb
            Dim pDefColl, pDef, rtParams, rtParam1, rtParam251Testing软件测试网#h?Co^7c5k1i)F
            Dim QtpTestPath51Testing软件测试网NQ l;R4B;Scr
            qtApp = CreateObject("QuickTest.Application") 51Testing软件测试网O+C u+UsF3EGCL)u
            qtApp.Launch()
    ,nCP!|#@138711        qtApp.Visible = True '使得QTP的程序可见


    )R/VM+k W}v{@138711        ' 设置运行属性
    7q[w VYUi2oi138711        QtpTestPath = QtpPath.Text & "\Tests\Test3" '设置脚本路径51Testing软件测试网O%t1C W,i |-Q'P
            qtApp.Options.Run.RunMode = "Fast"
    \v?tC u138711        qtApp.Open(QtpTestPath, True) ' Open the test in read-only mode

            ' set run settings for the test
    +q k0Y h,Ig138711        qtTest = qtApp.Test51Testing软件测试网0R'Ic@^
            qtTest.Settings.Run.OnError = "NextStep" 51Testing软件测试网9OtRy*e
            qtResultsOpt = CreateObject("QuickTest.RunResultsOptions") 
    3w[ u8kqD138711        qtResultsOpt.ResultsLocation = "D:\program files\Mercury Interactive\QuickTest Professional\Tests\Test3" ' 设置放结果的地方

            pDefColl = qtApp.Test.ParameterDefinitions
    u j4I'lT4SU6d138711        Dim cnt = pDefColl.Count
    8dB6jXV h138711        Dim Indx = 1
    7C/Ur-D8k/N^O138711        While Indx <= cnt51Testing软件测试网Z+|p7xb'C&v} gN
                pDef = pDefColl.Item(Indx)
    kR"?]V6[138711            Indx = Indx + 151Testing软件测试网*N2P6|w%n$u"o
            End While
    ]0s(` oe+Y.S138711        rtParams = pDefColl.GetParameters()51Testing软件测试网'K6P;dR`[_
            rtParam1 = rtParams.Item("InParameter1")
    ;]r^_JyH @7u138711        rtParam1.Value = DataFileName.Text
    5t1I@].C#G1^"`138711        ' MsgBox(TextBox1.Text)
    p-`6\x r&| Y138711        rtParam2 = rtParams.Item("InParameter2")
    9p0n@n_"h138711        rtParam2.Value = QtpPath.Text

            qtTest.Run(, True, rtParams) ' Run the test 51Testing软件测试网/j6U#zB;E.pB
            'MsgBox(rtParams.Item("OutParameter1").Value)

            'qtTest.Close ' Close the test 51Testing软件测试网"^U.E x%Z%n
            qtResultsOpt = Nothing     ' Release the Run Results Options object 51Testing软件测试网FFea7i{F
            qtTest = Nothing     ' Release the Test object
    I$LNvp3pbU138711        qtApp = Nothing     ' Release the Application object 51Testing软件测试网s)rmw~%mG w7e
            qtTest.quit()

        End Sub
    p(E$?v#g5k)~|138711

  • (转)QTP中一个关于Action的实例

    2008-12-19 15:38:11

     本例还是以QTP安装后自带的Flight Reservation为例来录制脚本.首先我们把登录程序系统,然后新建定单,再打开定单,最后关闭系统.分别录制成5个action,设置一个主的action为main来分别先后调用login(登录),new order(新建定单),open order(打开定单),logout(退出).

    注明:设置拆分action,选择菜单功能split Action .选择independent of each other为并列的两个action.选择Nested为主次的两个action.

     

    全部录制完所有action后,在main action中代码如下:

    RunAction "login", oneIteration51Testing软件测试网rTM5I*wF6]n
    RunAction "new order", oneIteration
    "Jilz(EaJ138711RunAction "open order", oneIteration51Testing软件测试网i!u N1S7L9Cs8h
    RunAction "logout", oneIteration

    其中RunAction是一个调用action的函数,后面跟action名和要传递的参数.

    说明:

    RunAction ActionName, [Iteration , Parameters]51Testing软件测试网&O.h5O-o,^`Irz

    在这里我再引入action之间参数传递.在login action中选择菜单选项,在action properties中设置两input参数分别先后为username 和 passwd.

    这样我们就通过RunAction "login", oneIteration,"mercury","mercury"  把这两个变量分别传给username 和passwd.这边的变量先后关系分别依次对应了action properties里input参数的先后关系.

    这样我们就可以在login action中调用这两个变量了.

    Dialog("Login").WinEdit("Agent Name:").Set Parameter("username")51Testing软件测试网$m&f"M)_s Q? U~
    Dialog("Login").WinEdit("Password:").Set Parameter("passwd")
    SmZ*X1Xs138711Dialog("Login").WinButton("OK").Click
    a5p@ \]{)ha#k138711

    下面再来实现从一个action中传出一个变量给另一个action.

    那么我们在new order 中选择菜单选项,在action properties中设置一个output参数为orderno

    Window("Flight Reservation").WinEdit("Order No:").Output CheckPoint("Order No:")

    通过上面这句话把生成的定单号的值存放到这个ouput参数中

    RunAction "new order", oneIteration,order
    nF4h"]$NE:g138711
    RunAction "open order", oneIteration,order

    再靠main action中这个order变量来传递,这个变量正好对应着new order里的output参数.从new order中传出来,再把这个变量传给open order.当然在open order中还要同样设置input参数.和这个order变量对应起来.

    这样就可以在open order中使用这个变量了.

    Window("Flight Reservation").Dialog("Open Order").WinEdit("Edit").Set Parameter("orderno")

    当然其实两个action之间传递参数还可以更简单点.比如一个脚本中 datatable和环境变量都是全局的,在一个脚本中的任何action都能使用.所以可以借用这两个来传递.

    通过这个例子最主要讲的是两点,拆分action和action之间的参数传递.

25813/13|<<45678910111213
Open Toolbar