发布新日志

  • 检查该网站上有多少个链接,并取得link.

    2009-06-19 11:31:51

    这是代码!
    SystemUtil.Run "IEXPLORE.EXE","http://www.baidu.com","","open","3"
    Dim i,j,arry()
    i=0
    m=0
    Set a=Browser("百度一下,你就知道").Page("百度一下,你就知

    道").Object.links
    For each element in a
            ReDim preserve arry(i+1)
            arry(i)=element.href

    'msgbox arry(i)
    i=i+1
    m=m+1
    Next
    msgbox(m)

    实质:

    链接是Web应用系统的一个主要特征,它是在页面之间切换和指导用户去一些不知

    道地址的页面的主要手段。链接测试可分为三个方面。首先,测试所有链接是否

    按指示的那样确实链接到了该链接的页面;其次,测试所链接的页面是否存在;

    最后,保证Web应用系统上没有孤立的页面,所谓孤立页面是指没有链接指向该页

    面,只有知道正确的URL地址才能访问。

    在此代码中没有达到验证网页上link有效性的作用!

  • QTP获取当前路径总结

    2009-04-23 13:59:37

    QTP当前路径总结


    说明:本总结不涉及相对路径的应用


    以下为获取当前路径的三种方法,包括QTP和vbs的或二者都可用的。
          以下为本人实验过的。用的QTP版本为9.2版。

    1.
    environment("TestDir")
    使用environment("TestDir")能获取当前测试的绝对路径,不包括最后的“\”
    方法:
    Path = environment("TestDir")

    2.
    WshShell.CurrentDirectory
    (注:不包括地址最后的“/”)
    方法:
    Dim WshShell,path
    Set WshShell = WScript.CreateObject("WScript.Shell")
    Path = WshShell.CurrentDirectory
    以上为vbs中的用法,如果是在QTP中使用,则可以用以下方法(vbs也可以用以下方法):
    Dim WshShell,path
    Set WshShell = CreateObject("WScript.Shell") ‘就这一句少了“WScript”
    Path = WshShell.CurrentDirectory
    注意:此方法在QTP运行时获取的将是QTP安装目录下bin目录的路径,如果是写在vbs文件中,然后加载到QTP中,在QTP运行时也是获取QTP安装目录下bin目录的路径。但是如果是编辑一个测试脚本(脚本里包含此获取路径方法,或引用的vbs文件包含此获取路径方法),然后保存(不要关闭脚本),这时运行脚本,则此方法将获取测试脚本存放的当前路径。关闭脚本再打开运行,则还是会获取QTP安装目录下bin目录的路径。因此在调试时可能是正常的,但到运行时就出错了。
           而如果用environment("TestDir"),则获取的都是当前测试的存放路径,但是不能用在VBS文件中(除非此文件是加载到QTP中运行的,那就可以)。
    例:QTP安装目录下的bin路径:C:\program files\Mercury Interactive\QuickTest Professional\bin

    3.
    left(Wscript.ScriptFullName,len(Wscript.ScriptFullName)-len(Wscript.ScriptName))
    (注:包括地址最后的“/”)
    方法:
    Path = left(Wscript.ScriptFullName,len(Wscript.ScriptFullName)-len(Wscript.ScriptName))
    注意:此方法只能用在单独的vbs文件中,加载到QTP中的vbs文件如果含有此方法也会报错。因为QTP不支持WScript。

  • QTP数据表数据库操作(z)

    2008-12-19 14:55:56

    1、Datatable方法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

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

    2008-12-19 14:53:27

     

    摘要:产生期望的随机数来选取到动态的下拉菜单的值。
    关键字:随机数;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-19 14:51:31

    '几个重要的方:OpenTextFile,AtEndofLine,Split

    Dim Fileobj,FilePath,FileName,Arrayline

    FilePath="E:\cntesting.txt"       '操作文本的所在路径也可以为表达式

    '创建一个文本文件并写入数据 1塂!}`tg? 
    Set ōbjth = CreateObject ("scrīpting.FileSystemObject") ;9籔??@  
    Set AdFile = objth.OpenTextFile(FilePath,2,true)      '此方法打开指定的文件并返回TextStream对象 ,第一个参数为要打开文件字符串表达式,第二个参数有三个值1,2,8可选,第三个参数True为创建新文件 巬暌/DV;  
    AdFile.WriteLine "###############################" ?o絎5?  
    AdFile.WriteLine "此脚本为读写文本文件的脚本例子" 輐g?滝? 
    AdFile.Close

    Set AdFile =  objth.OpenTextFile(FilePath,1,false)    '此中的参数1为只读方式打开

     While not AdFile.AtEndofLine    '如果文件指针正好位于OpenTextFile返回的TextStream文件中的行尾符之前,则返回True,否则返回False,只读 *禂?娘O  
      Arrayline = Split(AdFile.ReadLine,",")'此方法将一个字符串分割为子字符串,然后将结果作为字符串数组返回 ?Y??渗a  
      msgbox Arrayline(i) ?B懭懋鰐? 
     Wend

  • 一些问题的解决方案:

    2008-12-19 14:49:20

    ---------------------------------------------

    ->“实际项目录制脚本时经常遇到这种情况,伴随着系统不断的版本升级更新,需要我们在许多不同情况下回放同样的脚本,这样带来大量脚本中IE跳转地址的变动,有更好的方法能更快速,准确的实现这个需求吗?”

     

    ->有的,一般情况下最好的方式是把IE跳转地址,在脚本中实现而不是在Record and run settings 中设置打开固定的IE请求地址。如下:InvokeApplication "C:\Program Files\Internet Explorer\IEXPLORE.EXE http://www.cntesting.net/"

    ---------------------------------------------

    ->”录制脚本中发现同一模块的有些功能,步骤基本类似,是否能优化一下代码而减小脚本 代码的缀余呢?

     

    ->是的若脚本中缀余代码过多,不仅看起来麻烦,维护起来也很不方便,所以我们应该在脚本中善于使用过程,函数,对功能模块步骤基本类似的可以写成过程或则函数来提供调用。

    ---------------------------------------------

    ->”能提供一些QTP常用的快捷键吗?这样我想工作的效率也会提高很多,用起来也方便

     

    ->几个重要又经常使用到的QTP快捷键应该记住: CTRL+Y专家视图编辑前进;CTRL+Z专家视图编辑后退; CTRL+G移动到指定行; F2重新命名Ative的名字; F9设定断点,F3录制,F5运行,F4停止。还有很多快捷键都是经常要用到的,要经常用了才能记牢,我在这就不一一写出来了。

    ---------------------------------------------

    ->”项目中,我们经常会遇到这样的需求,需要记录一套脚本的运行时间,如果手工一个个操作去记录下时间的话,一来不是很精确,二来确实手工的方法太麻烦,有中方法解决这个问题吗?

     

    ->”这个需求是经常遇到的,以前我做项目的时候临近上线要验收测试了,因为时间紧迫必须大概知道脚本的运行时间,当时比较傻一个脚本手工的拿着个表记录时间,后来研究了一下,还是有方法的:在运行脚本的下一行记录下开始时间: startTme = timer; 在结束脚本的上一行记录下结束时间: endTime = timer; 然后 加一句这样的代码 runtime= round(endTime – startTime),2) 。用四舍五入的方法算出这个时间差就是脚本的运行时间。

    ---------------------------------------------

    ->”QTP能录下键盘的操作吗?能把我移动窗口的动作录制下来吗?”

     

    ->”可以的,但是我用过的就Table,如果要实现键盘按键的操作需要自己编码了,要把一些微小的操作录制下来,那就得启用微小录制了。

    ---------------------------------------------

    ->”我需要使用不同Action Datatable 里面的值,实现起来复杂吗?

     

    ->不复杂: DataTable.GetSheet("Action1").GetParameter("cntesting").ValueByRow(1)

    ---------------------------------------------

    ->”项目中有这样的需求,需要我们通过修改系统时间来做一笔定单,但是我总不能手动去修改啊.”

     

    ->呵呵,都手动去了都不需要自动化了,修改系统时间实际项目中很多要用到,需要自己写个dat文件在本地,里面设置好所要修改的时间,然后在QTP中执行这个dat文件,可以实现这个需求。Dat文件里面只要有这几代码就可以: time%1, 然后在QTP, SystemUtil.Run "c:\settime.bat","所要修改的具体时间

    ---------------------------------------------

    ->”经常遇到这样的情况,因为要验证弹出的窗口里面的内容,所以在IE属性中设置了不阻止窗口,但问题出来了窗口有时候弹出有时候不弹真奇怪了,如果不弹出来脚本中又录制有则会报错,要怎么去判断窗口是否弹出呢?”

     

    ->有一个方法 Exit 。是这样用的  if Browser(…).Page(…)…().exit then ……

    ---------------------------------------------

    问:时间控件QTP能录制下来吗?

     

    :对于时间控件的录制问题与开发使用的技术有关,我可以建议你用种方法,但是不同技术开发出的控件可能录制情况也有所不同。试试总比不试的好: Browser("xxx").Page("xxx").WebEdit("StartDate").Object.value=DataTable("StarDate", dtLocalSheet)

    ---------------------------------------------

  • QTP对Excel文件的读写操作

    2008-12-19 14:18:03

    重要方法   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    '读出函数调用

  • 并列Action之间的参数传递

    2008-12-19 14:18:03


    并列Action之间的参数传递:(目的:将并列Action_one中的参数传递给 Action_Two)

     

     

    步骤一:首先建立2个并列Action(并列Action_one,并列Action_Two),然后如图右击并列Action_one->选择Action properties.

     

     

    步骤二:选择Parameters单元,output parameters name 一列填写参数名。

     

     

    步骤三:右击并列Action_Two->Action Properties,设置Action_Two参数值。

     

     

    步骤四:在输入参数:input parameters中输入传入参数名。

     

     

    步骤五:让2个并列Action之间相互调用,点击Action call properties

     

     

    步骤六:点选parameter单元格。选择input parameter 中的 Value 一列。

     

     

    步骤七:点选parameter 在下拉列表中选择Test/action parameterAction一行选择传入并列Action_oneparameter 一行 选择Action_one中的Out Parameter 输出参数名。

     

     

    这样我们就达到了2个并列Action的相互参数传递, 此例并列Action_Two中的参数Inparametertwo,是由并列Action_one中的参数outparamter传递而来。

  • 一位高人的QTP学习笔记

    2008-12-19 14:06:56

    转贴一个高人的QTP笔记供大家学习。
       
    文章比较长,一共三部分:
    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

  • 自动化测试框架设计指南

    2008-12-19 14:01:57

    Tarun Lalwani在《Guidelines for Automation Framework Design》一文中提出了自动化测试框架设计时应该考虑的20个方面:

    (1)选择合适的框架类型。
    (2)不要重复发明轮子。
    (3)可重用性。
    (4)支持对不同版本的程序的测试。
    (5)脚本的版本控制。
    (6)脚本的开发调试与发布环境应该分离。
    (7)外部可配置。
    (8)自适应性。
    (9)测试对象改变时,框架所需的修改应该最小化。
    (10)框架的执行。
    (11)状态监视。
    (12)报告。
    (13)修改框架时应该尽量不依赖自动化测试工具。
    (14)框架应该易于调试。
    (15)
    日志
    (16)易使用性。
    (17)灵活性。
    (18)性能。
    (19)开发框架配套的外部工具。
    (20)代码标准和规范。

  • 基于Web的自动化测试方法及应用

    2008-12-19 14:00:16

     随着Internet和Intranet/Extranet的快速增长,Web已经对商业、工业、教育、政府和娱乐及我们的工作生活产生了深远的影响。因为Web能提供支持所有类型内容连接的信息发布,容易为最终用户存取,更多传统的信息和数据库系统正在被移植到互联网上;电子商务正迅速增长,范围广泛的、复杂的分布式应用也正在Web环境中出现。基于Web的系统在变得越来越复杂的同时,Web应用软件的缺陷危机也更加严重、更加广泛。

      在Web工程过程中,基于Web系统的测试、确认和验收已成为一项重要而富有挑战性的工作。Web测试也毫无例外地必须进行自动化测试。以期能通过自动化测试工具按照测试工程师的预定计划进行自动化测试,来减轻手工测试的劳动量,从而达到提高软件质量的目的。

      两种基于Web的测试方法

      笔者长期以来一直从事Exchange Server 2007、E14(未来的Exchange Server 2009)的基于Web的帮助功能及UI测试,OWA(Outlook Web Access)的功能和UI测试。在实际工作中也深感各种应用Web化已经是大势所趋。

      Microsoft Exchange的Web功能和UI测试大部分是基于自动化测试,在此希望和大家一起讨论和分享一下Web自动化测试的方法和经验。

      基于Web的测试基本上采用两种思路和方法:一种可以称为“Browsers测试”(浏览器端测试)。这种测试通常是模拟浏览器端的一些操作,比如在TextBox输入一些文本,选择ComboBox中的某个选项。因为可以得到具体的操作界面,这种方法更多地应用到UI和Localization方面的测试。在进行OWA的46种语言的Localization方面测试时,我们就采用了这种方法,对各种操作产生出来的界面进行抓图,然后对这些screenshot进行分析,以发现一些UI和Localization方面的问题。

      另一种方法称为“Protocol测试”(协议测试)。这种方法是建立在HTTP协议级的测试,通过POST或Web Service向服务器发送请求,然后对服务器响应回来的数据进行解析、验证。对一些功能测试,会更多地采用这种方法。最简单的应用就是检查链接的有效性,向服务器发送URL请求,检查响应回来的数据,来判断链接是否指向正确的页面。

      在实际项目中,我们可以根据具体需求进行选择。以下是这两种方法优缺点的比较:

     测试方法  优点  缺点
     浏览器测试  能够测试客户真实的操作场景  慢
     协议测试  快,稳定 不能对UI和一些脚本进行测试 

      览器端测试的具体应用

      对于这种模拟浏览器端操作的测试,微软已经有了非常成熟的测试框架,其中应用比较广泛的是ECHO和KAF。ECHO是一个可以驱动Web UI的、面向对象的测试架构,它允许终端用户使用XML或受.Net托管的编程语言,如C#来编写自动化测试用例。而KAF可谓ECHO的后继者,目前基于ECHO的测试项目都在逐渐向KAF迁移。这是因为KAF不但包括ECHO的大部分功能,而且支持多种浏览器(目前支持IE和Firefox),对页面上的动态元素也有很好的支持,灵活性更强。当然这些测试架构都是微软内部使用的工具,是不允许对外发布的。但大部分的Web UI测试架构都是建立在如下的设计思路,按照这样的设计思路,我们完全可以构建封装适合自己项目的Web UI测试架构进行浏览器端的测试(见图1)。


      图1

      (1)UI Element

      Web页面是由一系列的对象元素组成的,比如按钮、文本框等。UI Element就代表了这些通用的网页接口元素。UI Element类一般都是super class(超类),这个类通常会有以下的类成员:

      string Name: UI Element元素的名称。作为这个元素的唯一标识。
      Driver UIDriver: 是对UI Element所使用的UI驱动实施的一个引用。针对不同的浏览器会选择不同的驱动方法。
      List<List<UIElementAttr>>AttributeLists: UI Element属性的集合,UI Driver将遍历所有的属性列表去定位匹配的Element。当某个元素在不同的状态可能会有不同的属性时,例如我们熟知的button的三态,我们就需要有多个属性列表。UIElementAttr通常是一个集合,一般包含有属性名称、属性值、是否准确匹配等。
      string ContainerName: UI Element所在的容器名称。对于Web页面,就是指元素所在的框架的名称。
      以上只是一些基本的类成员,可以根据实际情况对这个类进行补充。通常我们会创建一些UIElement子类内置到我们的测试架构中,这此子类主要是如下的一些常见的Web控件:

    TextBox
    Button
    RadioButton
    Link
    Label
    Image
    Checkbox
    SelectItem
    ComboBox
    DropDownMenu

      我们通常会将静态的UI Element存储到XML文档,这样做的好处是当UI Element元素发生变化时,只需要修改这个XML文档,而不必修改我们的测试代码。

      有时候可能在Test Cases运行期间,用来确定UI Element唯一性的属性会变化,这时候我们也需要用编码动态地去更新属性列表,来创建这个UI Element。

      (2)Browser Agent

      我们设计Web测试框架最主要的目的就是能够让测试代码在不同的浏览器,比如IE、Firefox中都能自动地、正常地运行。提供Browser Agent可以更灵活设置浏览器的类型,以及完成一些常规的浏览器功能,比如清除浏览器的缓存及载入页面等。

      (3)UI Driver Interface

      为了实现测试代码在不同浏览器都能够自动执行这个目的,可以抽象出一个UI的驱动层。在这一层里可以设计出能在各种浏览器里执行的、所有可能的UI动作,而且我们设计的Test Cases也只与这一层进行交互。这样可以将驱动的实现与Test Cases进行分离,将来Test Cases的修改不会影响到Driver Implement层代码的实现部分,而且UI Driver Implement层的改变也会不影响到测试代码。常见的一些方法如下:

    Click(…):
    Select(…):
    DragAndDrop(…)
    GetTitle(…):
    PressKey(…):

      (4)UI Driver Implement
      这是建立一个Web测试架构的基础,对于不同的浏览器可能会采用不同的驱动实现方法。

      协议级测试的具体应用

      图2

  • 用TestComplete实现一个关键字驱动测试框架(转载)

    2008-12-19 13:47:32

    最近在做使用TestComplete做一个自动化测试项目的时候,发现在TestComplete中,可以利用其中的FindChild方法来实现一个简单的关键字驱动的框架,方法如下:

    (1)在Excel编写测试关键字。
    在Excel文件中编写测试关键字,包括测试对象、测试操作、输入的参数等,如图所示:
     
    (2)编写测试脚本,读入Execl中的测试关键字。
    // 全局的变量数组,用于存储从Excel读入的测试关键字
    Var KeyWord_TestObject,KeyWord_Operation,KeyWord_Parameters;
    //.............................................................................
    // 目的:通过ADO查询Excel数据
    // 输入参数:
    //           ExcelFilePath :Excel文件的路径
    //           QueryString:查询语句
    // 返回结果:
    //           返回所有关键字数据,赋值给KeyWord_TestObject,KeyWord_Operation,KeyWord_Parameters这3个全局的变量数组
    // 注意事项:
    // 作者:陈能技
    // 日期:2008-6-3
    //.............................................................................
    Function ReadKeyWordFromExcel(ExcelFilePath,QueryString);
     Var ConStr,Connection,RS,ClassObjArray,LineIndex,ClassObject:OleVariatn;
    begin
     // 定义连接串
     ConStr := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%S;Extended Properties=Excel 8.0';
     ConStr := Utilities.Format(ConStr,[ExcelFilePath]);
     Connection := Sys.OleObject('ADODB.Connection');
     // 打开连接
     Connection.Open(ConStr);
     // 执行查询操作
     RS := Connection.Execute(QueryString);
     // 创建变量数组
     KeyWord_TestObject := CreateVariantArray(0,0);
     KeyWord_Operation := CreateVariantArray(0,0);
     KeyWord_Parameters := CreateVariantArray(0,0);
     LineIndex := 0;
     // 循环读入所有数据
     While Not RS.EOF do
     begin
        Inc(LineIndex);
        // 动态修改数组大小
        VarArrayRedim(KeyWord_TestObject,LineIndex-1);
        VarArrayRedim(KeyWord_Operation,LineIndex-1);
        VarArrayRedim(KeyWord_Parameters,LineIndex-1);  
        // 赋值
        KeyWord_TestObject[LineIndex-1] := RS['TestObject'].Value;
        KeyWord_Operation[LineIndex-1] := RS['Operation'].Value;
        KeyWord_Parameters[LineIndex-1] := RS['Parameters'].Value;   
        // 下一条数据
        RS.MoveNext;
     end;
     RS.Close;
     // 关闭连接
     Connection.Close;
    end;
    Procedure Test_ReadKeyWordFromExcel;
     Var I : OleVariant;
    begin
     ReadKeyWordFromExcel('D:\Code\MyTestSuite\Data\KeyWord.xls','Select * from [KeyWord$]');
     For I := 0 to VarArrayHighBound(KeyWord_TestObject,1) do
     begin
        Log.Message(VarToStr(KeyWord_TestObject[I])+ '   | '
                   + VarToStr(KeyWord_Operation[I])+' | '
                   + VarToStr(KeyWord_Parameters[I]));
     end; 
    end;
     
    (3)封装一个函数,用于根据Excel读入的测试关键字创建可用的测试对象。
    Uses CheckUIPerformance;
    //.............................................................................
    // 目的:返回当前进程中的指定测试对象
    // 输入参数:
    //           Process :进程对象
    //           TestObject:测试对象的描述
    // 返回结果:
    //           返回当前进程中的指定测试对象
    // 注意事项:
    // 作者:陈能技
    // 日期:2008-6-3
    //.............................................................................
    Function getObject(Process,TestObject);
    var
     PropArray, ValuesArray;
    begin
     PropArray := CreateVariantArray(0, 0);
     ValuesArray := CreateVariantArray(0, 0);
     PropArray[0] :='FullName';
     ValuesArray[0] := TestObject;
     // 调用 FindTestObject 函数,返回当前进程中的指定测试对象
     Result := FindTestObject(Process,PropArray,ValuesArray);
    end;
     
    这里调用了CheckUIPerformance脚本中编写的FindTestObject函数,该函数用于根据测试对象的描述信息查找指定进程中的测试对象,脚本如下:
    Function FindTestObject(Process,PropArray,ValueArray);
     var res;
    begin
     Result := False;
     // 查找指定的测试对象
     Process.Refresh();
     res := Process.FindChild(PropArray, ValueArray, 1000);
     // 返回测试对象
     if res.Exists then
     begin
        Result := res;
        Log.Message('找到测试对象: ' + res.FullName)
     end
     else
        Log.Message('未找到测试对象');
    end;
     
    (4)封装一个函数,用于根据Excel读入的测试关键字执行测试操作。
    //.............................................................................
    // 目的:执行测试操作
    // 输入参数:
    //           TestObject :测试对象
    //           Operation:测试操作的描述
    //           Parameters:测试操作对应的参数
    // 返回结果:无
    // 注意事项:
    // 作者:陈能技
    // 日期:2008-6-3
    //.............................................................................
    Function DoOperation(TestObject,Operation,Parameters);
    begin
     case Operation of
        'Keys' : TestObject.Keys(Parameters);
        'Click' : TestObject.Click;
        // 添加其它类型的测试操作的处理代码 ...
     else
        Log.Error('不支持该测试操作!');
     end; 
    end;
     
    注:这里仅仅添加了 Keys 和 Click 的测试操作。
     
    (5)关键字驱动的核心框架
    有了前面几个函数的基础,就可以写出下面一个简单的关键字驱动的核心框架:
    //.............................................................................
    // 目的:关键字驱动的核心框架
    // 输入参数:
    // 返回结果:
    // 注意事项:
    // 作者:陈能技
    // 日期:2008-6-3
    //.............................................................................
    Procedure Driver;
     Var TestObject,I;
    begin
     // 1、读入关键字
     ReadKeyWordFromExcel('D:\Code\MyTestSuite\Data\KeyWord.xls','Select * from [KeyWord$]');
     // 2、遍历关键字,创建测试对象、执行测试操作
     For I := 0 to VarArrayHighBound(KeyWord_TestObject,1) do
     begin
    //    Log.Message(VarToStr(KeyWord_TestObject[I])+ '   | '
    //               + VarToStr(KeyWord_Operation[I])+' | '
    //               + VarToStr(KeyWord_Parameters[I]));
        // 创建测试对象
        TestObject := getObject(Sys.Process('flight4a'),VarToStr(KeyWord_TestObject[I]));
        // 执行测试操作
        DoOperation(TestObject,VarToStr(KeyWord_Operation[I]),VarToStr(KeyWord_Parameters[I]));  
     end;
    end;
     
    经试验,这种方法是可以实现类似QTP的关键字驱动测试框架,但是仅仅是一个非常基础的关键字驱动测试框架,如果想把这个框架应用在实际项目中的话,还需要进一步地修改和完善,还有很多工作要做,包括:
    (1)关键字编辑器的编写。
    目前采用直接在Excel文件中填写测试关键字的方法,存在效率和可用性问题,需要创建一个类似QTP的更加好用的关键字视图编辑器。
    (2)添加更多的测试操作和方法。
    目前作为试验,仅仅添加了 Keys 和 Click 的测试操作,还有很多控件的很多测试方法需要封装,例如List控件的ClickItem、SelectItem等,另外,对测试对象的属性赋值操作、属性检查操作(类似于QTP的CheckPoint)等都需要进一步地编写框架代码来处理。
    (3)关键字代码与测试脚本之间的同步。
    仅仅依赖Excel的关键字数据来实现整个项目的自动化测试未免过于理想化了,QTP提供了很好的代码生成机制,关键字视图的数据与专家视图的测试脚本之间可以随时同步、切换,因此这个关键字驱动测试框架还缺少一个代码生成器,如何建立Excel数据与测试脚本之间的映射关系是下一步的主要工作之一。

数据统计

  • 访问量: 10428
  • 日志数: 17
  • 文件数: 1
  • 建立时间: 2008-12-11
  • 更新时间: 2009-06-19

RSS订阅

Open Toolbar