未来已来

发布新日志

  • LoadRunner和HTTP协议

    2010-08-20 10:44:01

     

    最近在做性能测试,在开发web脚本的过程中遇到错误: Action.c(15): Error -26631: HTTP Status-Code=400 (Bad Request) for  http://xxxxxx/onlinefront/s.do?tl=51&bk=null&optionId=244&p=110

    问了很多人没有人知道问题的原因,最后只能自己潜心研究,首先从http status-code400的错误开始分析, 这个错误是说请求无法被处理因为它含有缺失或无效的信息, 根据错误信息的描述应该是发送HTTP请求中语法格式不正确导致不被服务器接受,这很可能就是通过LoadRunner  发送HTTP请求是一个不完整。那么首先要确认的就是比较发出的请求和录制的时候请求看是否丢失了http信息来判断错误的原因。

         首先选上runtimesettingsextended log的三个选项后运行此脚本,用录制发送相类似请求的日志和选择exection loghttp send请求日志进行对比 。拷贝这些请求数据包到一个记事本中然后进行比较。在Recording Log(单协议)或Generation Log(多协议)中查找是否存在头数据包,我们发现在执行日志中头域失踪了。

         这样解决问题的方法就是web_add_header("xxxxx","yyyy")添加一个http头,在错误的请求前添加此函数然后回放。

      如果你发现所有的HTTP send请求都缺少头数据包,在脚本中的开头添加web_add_auto_header”XXXXX“”yyyy“;随着web_add_auto_header的添加,你不需要为每个HTTP send请求都添加web_add_header了。

    还有一个解决问题的方法是在Tools -> Recording Options -> Advanced tab中设置,点“headers”按钮,在列表中选择Record Headers in the List,然后选择“XXXXX”,因此它可确保在录制过程中录制自己。

  • QTP回放解决方案(学员翻译)

    2010-06-16 20:50:42

    2008103

    大家好,

      已经有一段时间没给大家回信了,对此我非常抱歉。由于公司的业务繁忙所以我一直没有给大家回信,当然我知道不应该拿这个当作借口。

      这次,我将给大家讲解一下有关QuickTest Professional的使用。

    多数时间,QTP可以自动录制你与应用系统交互的每一步,然而,尽管QTP功能强大,但是当应用界面对象不是标准的时候QTP也是无能为力的。

    这是因为对于应用界面不标准的类型,QTP没有关于它的先前的资料,所以当遇到这种问题的时候就不知道如何去解决。正如一个孩子当在一些新的事情上犯错误的时候就不知道怎么去解决。

     

    对于这类型的问题,我们有两种解决办法:

    告诉QTP这个新事物的所有相关信息并且解释处理的方法。意思就是说当QTP下次遇到这个新事物的时候,就会自动识别并恰当地使用这个新事物(知道该记录什么和如何去回放这些记录)。让QTP执行这个,你需求使用一个叫做可延长性的功能。然而,我们都知道创建可延长性是有一定难度的而且它会限制QTP添加项的使用。

    你创建一个回放的解决方案。意思是当你录制的时候QTP任然不知道你对这个应用的操作,所以不会恰当的生成脚本但是在录制的过程中QTP能够和应用交互。为了实现这个功能,你必须写自定义的函数并且详细的描述每一步的操作。这类型的解决方案往往使你的脚本更容易理解。下面我们会对这种解决方案进行详细的介绍。

    因此,首先,我们使用QTP录制一段脚本:

    Window(“Paint”).WinObject(“Colors”).Click 72,33

    Window(“Paint”).WinObject(“Tools”).Click 21,148

    Window(“Paint”).WinObject(“Afx:1000000:8″).Click 48,99

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drag 100,48

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drop 137,100

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drag 52,98

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drop 135,98

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drag 47,100

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drop 47,189

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drag 47,189

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drop 134,188

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drag 137,102

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drop 135,188

    Window(“Paint”).WinObject(“Colors”).Click 134,30

    Window(“Paint”).WinObject(“Tools”).Click 15,174

    Window(“Paint”).WinObject(“Tools”).Click 31,261

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drag 82,144

    Window(“Paint”).WinObject(“Afx:1000000:8″).Drop 102,187

    如果你录制了这段脚本,你将看到QTP画了一个院长的图画,但是我们看这段脚本根本没有一点标示是画这个图画。同时你也注意到这个图画中丢失了一个元素,我没有忘记这个元素但是QTP却没有录制它。

    现在,让我们看一下我们如何提高我们的脚本并且使我们的录制方案比QTP目前所能及的做的更好。

    首先行为第一,你想让你的脚本看起来像什么呢?我个人的意见是,像下面的这段脚本就是好的:

    SelectColor “red”

    SelectTool “line”

    DrawLine 100, 48, 137, 100

    DrawLine 52, 98, 135, 98

    SelectColor “blue”

    SelectTool “rectangle”

    DrawRectangle 82, 144, 102, 187

     

    如果你像我,仅仅读了上面的一段脚本,你理解QTP做了什么,画了一根红色的线,一个蓝色的矩形等等[但是,你任然不会知道最后这个图画是什么样子]。你相信吗,这就是向前的方式?是的,的却如此,让我们出发。

    首先,我们需要去了解QTP从应用中获悉什么。为了知道这个,我们使用间谍工具去监视QTP怎样识别你的对象。你将注意到所有的工具栏(工具和颜色)都作为一种对象被识别,同时QTP不能识别个别的按钮但是你能看到QTP识别了这种对象并作为WinObjects

    当你在应用中看到WinObjects的时候,你应该立刻意识到,这些是QTP不能识被的对象。事实如此,WinObjects是当QTP不了解这个对象时用来使用的一种类型。如果QTP了解对象的一些属性,QTP将把这些对象分类为一些其他的对象(WinEdit, WinButton, WinToolbar, 等等.)因此,对选项里的任一项,QTP有一种类型用来标示它不识别这个对象。WinObjectwindows的对象WebElementWeb的对象,JavaObjectJava对象,SwfObject.Net对象等等。

    因此,现在我们知道QTP只识别3个对象,这3个对象全是WinObjects:工具栏,颜色栏和画布(画图区域)。对于我们的回放,这些信息就已经足够了,因为我们总是通过使用点击工具栏里的按钮并使用相应的提示进行操作,只要这个按钮在工具栏里不移动就可以。

    现在我们做一个简单的例子:

    当我们选择了这个线条工具,QTP识别下面的状态:

    Window(“Paint”).WinObject(“Tools”).Click 21,148

    如果你试图努力,你可能得到一些和这些提示不同的值但是他们基本上一致,实际上,你可以点击任何地方只要他在工具栏的范围之内并且你可以选择即可。

     

    现在,我们写一些和以下相似的事情:

    SelectTool “Line”

    如果你现在就这样执行脚本,QTP将提示它不理解关于选择工具栏的任何信息。而且QTP将通过“配错类型”错误提示显示出来。如果你同意的话,告诉QTP怎样去做。

    我们需要创建一个和选择工具栏相同名字的程序,并且规定当执行程序时相应的做什么。

    Sub SelectTool(ToolName)

    If ToolName = “Line” Then

          Window(“Paint”).WinObject(“Tools”).Click21,148

        Else

          MsgBox “Invalid tool name.”

        End If

    End Sub

    SelectTool “Line”

    如果你再次执行这段脚本,你将注意到QTPP不会验证关键字是否正确,反而直接调用Line 工具。

    因此,现在你可以在你的函数里添加许多新的灵活的工具:

    Sub SelectTool(ToolName)

    Select Case ToolName

      Case “Line”

          Window(“Paint”).WinObject(”Tools”).Click16,142

      Case “Curve”

           Window(“Paint”).WinObject(”Tools”).Click 41,143

      Case “Rectangle”

           Window(“Paint”).WinObject(”Tools”).Click 16,165

      Case “Polygon”

           Window(“Paint”).WinObject(”Tools”).Click 41,166

       Case Else

        Reporter.ReportEvent micFail, “SelectTool”, “The tool ‘” & ToolName & “‘ does not exist.”

    End Select

    End Sub

    SelectTool “Line”

    SelectTool “Rectangle”

    SelectTool “Line”

    好了,现在你得到了图片并且你也知道如果新建SelectColor程序了。

    但是,让我们看的远一点,因为我们写的程序并不完美。当我们写函数或程序时,我们可以使用变量让它更灵活而且我们可以参数化工具名称实现。然而,一个函数或是程序可以完全独立于外部数据除了通过参数传递数据。并且在当前情况下,SelectTool是依靠Window(”Paint”).WinObject(”Tools”)。所以,为了完善我们的函数,我们从这种方式重写:

    Sub SelectTool(ToolObject, ToolName)

    Select Case ToolName

            Case “Line”

                ToolObject.Click 16,142

            Case “Curve”

                ToolObject.Click 41,143

            Case “Rectangle”

                ToolObject.Click 16,165

            Case “Polygon”

                ToolObject.Click 41,166

            Case Else

           Reporter.ReportEvent micFail, “SelectTool”, “The tool ‘” & ToolName & “‘ does not exist.”

        End Select

    End Sub

    SelectTool Window(“Paint”).WinObject(“Tools”), “Line”

    SelectTool Window(“Paint”).WinObject(“Tools”), “Rectangle”

    SelectTool Window(“Paint”).WinObject(“Tools”), “Line”

    现在,我们通过添加一个新的参数从工具对象中移除附属,增加句法的结构复杂性。但是QTP有一个特性就是容许我们给QTP对象注册一个函数或者程序。通过做这些,我们告诉QTP对象现在是一个新的函数:

    Sub SelectTool(ToolObject, ToolName)

    Select Case ToolName

            Case “Line”

                ToolObject.Click 16,142

            Case “Curve”

                       ToolObject.Click 41,143

             Case “Rectangle”

                ToolObject.Click 16,165

            Case “Polygon”

                ToolObject.Click 41,166

            Case Else

          Reporter.ReportEvent micFail, “SelectTool”, “The tool ‘” & ToolName & “‘ does not exist.”

    End Select

    End Sub

    RegisterUserFunc “WinObject”, “SelectTool”, “SelectTool”

    Window(“Paint”).WinObject(“Tools”).SelectTool “Line”

    Window(“Paint”).WinObject(“Tools”).SelectTool “Rectangle”

    Window(“Paint”).WinObject(“Tools”).SelectTool “Line”

    现在,我们知道在我们的工具栏里如何去选择一个项目,让我们看一下在画布里画图。之前,我们规定和下面的代码相似是理想的:

    SelectColor “red”

    SelectTool “line

    DrawLine 100, 48, 137, 100

    So, now we need to draw a line:

    Sub DrawLine(CanvasObject, StartX, StartY, EndX, EndY)

    CanvasObject.Drag StartX, StartY

    CanvasObject.Drop EndX, EndY

    End Sub

    RegisterUserFunc “WinObject”, “DrawLine”, “DrawLine”

    Window(“Paint”).WinObject(“Afx:1000000:8″).DrawLine 44, 34, 128, 34

    完整脚本如下:

    Dim dicTools

    Set dicTools = CreateObject(“Scripting.Dictionary”)

    dicTools.Add “line”, Array(16, 142)

    dicTools.Add “curve”, Array(41, 142)

    dicTools.Add “rectangle”, Array(16, 165)

    dicTools.Add “polygon”, Array(31, 165)

    Dim dicColors
    Set dicColors = CreateObject(“Scripting.Dictionary”)

    dicColors.Add “black”, Array(42, 14)

    dicColors.Add “white”, Array(42, 30)

    dicColors.Add “red”, Array(72, 33)

    dicColors.Add “yellow”, Array(89, 33)

    dicColors.Add “green”, Array(103, 33)

    dicColors.Add “blue”, Array(135, 33)

    Sub SelectTool(ByRef objTool, ByVal ToolName)

    ToolName = LCase(ToolName)

       If dicTools.Exists(ToolName) Then

      objTool.Click dicTools(ToolName)(0), dicTools(ToolName)(1)

          Reporter.ReportEvent micPass, “SelectTool”, “The tool ‘” & ToolName & “‘ has been selected.”

       Else

            Reporter.ReportEvent micFail, “SelectTool”, “The tool ‘” & ToolName & “‘ does not exist.”

       End If

    End Sub

    Sub SelectColor(ByRef objColor, ByVal ColorName)

    ColorName = LCase(ColorName)

        If dicColors.Exists(ColorName) Then

            objColor.Click dicColors(ColorName)(0), dicColors(ColorName)(1)

            Reporter.ReportEvent micPass, “SelectTool”, “The color ‘” & ColorName & “‘ has been selected.”

        Else

            Reporter.ReportEvent micFail, “SelectTool”, “The color ‘” & ColorName & “‘ does not exist.”

        End If

    End Sub

    Sub DrawLine(CanvasObject, StartX, StartY, EndX, EndY)

        CanvasObject.Drag StartX, StartY

    CanvasObject.Drop EndX, EndY

    End Sub

    Sub DrawRectangle(CanvasObject, StartX, StartY, EndX, EndY)

    CanvasObject.Drag StartX, Start

  • 如何获得一个ie已经存在的实例

    2009-08-02 17:12:23

     

       最近一个朋友在做自动化测试过程中想实现一个时时监控的功能,如只要前台有人打开网页,后台qtp就开始对页面上进行校验,这个功能很新颖第一次听同行有这样的思路。该工具的实现难点在于后台什么时候触发qtp执行自动化测试,这一点通过hook的技术可以实现,进入系统消息链,监控特定消息,然后触发qtp。hook的开发还需要一段时间,他暂时先不是同步进行校验,测试人员打开ie之后先手工出发校验。这里涉及到如何获得已经存在的ie的实例,也就是测试人员打开ie后,打开网页执行测试,同时点击执行qtp脚本,qtp开始在测试人员打开的那个页面上进行校验。这里主要用internet controls,ie application对象实现。

    Dim objSW 'As SHDocVw.ShellWindows
    Dim objIE 'As SHDocVw.InternetExplorer
    Dim objDoc 'As Object

    Set objSW = New SHDocVw.ShellWindows
        For Each objIE In objSW
           If InStr(1, UCase(objIE.FullName), "IEXPLORE.EXE") <> 0 Then
              If objIE.LocationURL = "目标链接地址" Then
                Set objIE = objSW.Item
                Exit For
              End If
           End If
        Next 'objIE
    '下面一行为控制代码,替换需要的操作代码
     objIE.Navigate "www.sohu.com"

    Set objSW = Nothing
    Set objIE = Nothing

    以上代码在vb中调试通过

  • 如何用QTP处理dll中带有枚举类型返回值的函数

    2009-05-16 23:15:31

      
      收到一封学员关于用qtp处理dll中带有枚举型返回值函数的问题,这里是给他的一个答复。

    老师:

      我用QTP 调用VC 编写的dll (extern c 编译)
    MXDSGC_API MXD_RTN_CODE_E SGC_InitWinsock(void);
    /*!
     * This function is used to close windows socket port.
     * \param 
     *         void
     * \return
     *         Return code by MXD_RTN_CODE_E enumeration.   
     */
    我在QTP中应该如何调用?
    extern.Declare micUInteger
    ,"SGC_InitWinsock","D:\Share\MA\SiggenControl\sgc.dll","",micVoid
    如果返回值是枚举型,在QTP中用什么返回呢?

     

     回答:关于qtp调用dll返回的是枚举型函数的问题,其实只要把返回值设置成MicInteger类型就可以,我写了一个例子请看下
      
      在vc中编写了一个带有枚举型返回值函数的dll
      lib.h中代码如下:
      enum color
    {red,yellow,blue};

    #ifndef LIB_H
    #define LIB_H
       extern "C" color __declspec(dllexport)getcolor();
    #endif
      lib.cpp中代码如下
      #include "lib.h"
    color getcolor()
    {
     color c_1;
             c_1=red;
     return c_1;
    }
    以上代码纯为了说明问题,vc6中编译通过

    qtp中调用代码
    Extern.Declare micInteger,"getcolor","D:\VC\dll\Debug\dll.dll","getcolor"
    Dim iColorResult
    iColorResult=Extern.getcolor()
    If iColorResult =0 Then
        msgbox "red"
    End If

    If iColorResult =1 Then
        msgbox "yellow"
    End If

    If  iColorResult =1 Then
     msgbox "blue"
    End If

    以上代码在qtp10中调式通过。

    这里关键是vbs是无类型的编程语言,所以不能和c语言中的类型进行匹配,如我们会在vb中声明同类型的变量更替它,vb中的调用代码如下:
    Private Declare Function getcolor Lib "D:\VC\dll\Debug\dll.dll" () As color

    Private Enum color
      red
      yellow
      blue
    End Enum

    Private Sub Command1_Click()
      Dim iColorResult  As color
      iColorResult = GetColor()
      MsgBox iColorResult
    End Sub

    可以在vb中声明替代枚举型变量,与c中的枚举类型相匹配。


     

  • Qtp 问题代码收集

    2008-12-25 22:09:31

     
    1.环境变量处理数组
    Dim MyArray(1)
    MyArray(0) = "10"
    MyArray(1) = "20"
    Environment.Value("Env") = MyArray
    MsgBox Environment.Value("Env")(0)    'Output = 10
     
    2.How to specify the tolerance for a bitmap checkpoint 
    The user would like to specify the acceptable number of failing pixels between the expected and actual bitmap. 
    ________________________________________
    Solution: Set the relevant value for the key in the registry
    1. Open the registry editor (Start -> Run -> regedit).
    2. Navigate to HKEY_CURRENT_USER\SOFTWARE\Mercury Interactive\QuickTest Professional\MicTest\BitmapVerification.
    3. Right-click on the ToleranceLevel value.
    4. Select "Modify" from the pop-up menu.
    5. Set the desired tolerance level. This value is the number of pixels that the checkpoint can allow to be different.
    6. Close the registry editor.
    You will need to restart QuickTest Professional for the changes to take effect.

    Example:
    If you set the tolerance level to be 10, then the checkpoint will pass as long as ten or less pixels are different between the expected and actual images
     
    3.db code function

    'Example of How to use functions.

    ''************************************************************************************
    ' Example use DSN created for database of Flight sample application.
    ''************************************************************************************
    SQL="SELECT * FROM ORDERS"
    connection_string="QT_Flight32"

    isConnected = db_connect ( curConnection ,connection_string )
    If isConnected = 0 then
        ' execute the basic SQL statement
        set myrs=db_execute_query( curConnection , SQL )
       
        ' report the query and the connection string
        Reporter.ReportEvent micInfo ,"Executed query and created recordset ","Connection_string is ==> " & connection_string & " SQL query is ===> " & SQL
        ' show the number of rows in the table using a record set
        msgBox " Quantity of rows in queried DB ( db_get_rows_count )==> " & db_get_rows_count( myrs )
        ' show the number of rows in the table using a new SQL statement
        msgBox " Quantity of rows in queried DB (db_get_rows_count_SQL ) ==> " & db_get_rows_count_SQL( curConnection , "SELECT COUNT(*) FROM ORDERS" )

        ' change a value of a field in an existing row
        rc = db_set_field_value (curConnection, "ORDERS" , "Agents_Name" , "test", "Agents_Name", "AGENT_TESTER")

        ' examples of how to retrieve values from the table
        msgBox "val row 0 col 0: " & db_get_field_value( myrs , 0 , 0 )
        msgBox "val row 0 col 1: " & db_get_field_value( myrs , 0 , 1 )
        msgBox "val row 1 col Name: " & db_get_field_value( myrs , 1 , "Agents_Name" )
        msgBox "val SQL row 1 col Name: " & db_get_field_value_SQL( curConnection , "ORDERS" , 1 , "Agents_Name" )

        db_disconnect curConnection
    End If

    ''****************************************************************************************


    ' Database Functions library
    '******************************************************************************************
    'db_connect
    ' ---------------
    ' The function creates a new connection session to a database.
    ' curSession - the session name (string)
    ' connection_string - a connection string
    ' for example the connection_string can be "DSN=SQLServer_Source;UID=SA;PWD=abc123"
    '******************************************************************************************
    Function db_connect( byRef curSession ,connection_string)
        dim connection
        on error Resume next
        ' Opening connection
        set connection = CreateObject("ADODB.Connection")
        If Err.Number <> 0 then
            db_connect= "Error # " & CStr(Err.Number) & " " & Err.Descrīption
            err.clear
            Exit Function
        End If
     
        connection.Open connection_string
        If Err.Number <> 0 then
            db_connect= "Error # " & CStr(Err.Number) & " " & Err.Descrīption
            err.clear
            Exit Function
        End If
        set curSession=connection
        db_connect=0
    End Function

    '********************************************************************************************
    ' db_disconnect
    ' ---------------------
    ' The function disconnects from the database and deletes the session.
    ' curSession - the session name (string)
    '********************************************************************************************
    Function db_disconnect( byRef curSession )
        curSession.close
        set curSession = Nothing
    End Function

    '*********************************************************************************************
    ' db_execute_query
    ' ---------------------------
    ' The function executes an SQL statement.
    ' Note that a db_connect for (arg1) must be called before this function
    ' curSession - the session name (string)
    ' SQL - an SQL statement
    '**********************************************************************************************
    Function db_execute_query ( byRef curSession , SQL)
        set rs = curSession.Execute( SQL )
        set db_execute_query = rs
    End Function

    ''***********************************************************************************************
    ' db_get_rows_count
    ' ----------------------------
    ' The function returns the number of rows in the record set
    ' curRS - variable , contain record set , that contain all values that retrieved from DB by query execution
    ''***********************************************************************************************
    Function db_get_rows_count( byRef curRS )
        dim rows
        rows = 0
        curRS.MoveFirst
        Do Until curRS.EOF
            rows = rows+1
            curRS.MoveNext
        Loop
        db_get_rows_count = rows
    End Function

    ''************************************************************************************************
    ' db_get_rows_count_SQL
    ' ------------------------------------
    ' The function returns the number of rows that are the result of a given SQL statement
    ' curSession - the session name (string)
    ' CountSQL - SQL statement
    ''************************************************************************************************
    Function db_get_rows_count_SQL( byRef curSession ,CountSQL )
        dim cur_rs
        set cur_rs = curSession.Execute( CountSQL )
        db_get_rows_count_SQL = cur_rs.fields(0).value
    End Function

    ''*************************************************************************************************
    ' db_get_field_value_SQL
    ' -----------------------------------
    ' curSession - variable denote current active connection
    ' tableName - name of the table , where value should be retrieved
    ' rowIndex - row number
    ' colName - the column name.
    '*************************************************************************************************
    Function db_get_field_value_SQL( curSession , tableName , rowIndex , colName )
        dim rs
        SQL = " select " & colName & " from " & tableName
        set rs = curSession.Execute( SQL )

        rs.move rowIndex
        db_get_field_value_SQL = rs.fields(colName).value
    End Function

    '*************************************************************************************************
    ' db_get_field_value
    ' --------------------------
    ' The function returns the value of a single item of an executed query.
    ' Note that a db_execute_query for (arg1) must called before this function

    ' curRecordSet - variable , contain record set , that contain all values that retrieved from DB by query execution
    ' rowIndex - the row index number (zero based)
    ' colIndex - the column index number (zero based) or the column name.
    ' returned values
    ' -1 - requested field index more than exists in record set
    '*************************************************************************************************
    Function db_get_field_value( curRecordSet , rowIndex , colIndex )
        dim curRow

        curRecordSet.MoveFirst
        count_fields = curRecordSet.fields.count-1
        If ( TypeName(colIndex)<> "String" ) and ( count_fields < colIndex ) then
            db_get_field_value = -1 'requested field index more than exists in recordset
        Else
            curRecordSet.Move rowIndex
            db_get_field_value = curRecordSet.fields(colIndex).Value
        End If
    End Function

    '*************************************************************************************************
    ' db_set_field_value
    ' ---------------------------
    ' The function changes the value of a field according to a search criteria.
    ' We search for a certain row according to a column name and the desired vale, then we change a value in that row according
    ' to a desired columns

    ' curConnection - the session name (string)
    ' tableName - name of the table , where value should be retrieved
    ' colFind - the column we search the criteria in
    ' colFindValue - the value we search in the column
    ' colChange - the column were we want to change the value
    ' colChangeValue - the new value

    ' returned values
    ' -1 - requested field index that doesn't exists in the recordset
    '*************************************************************************************************
    Function db_set_field_value(curConnection, tableName , colFind , colFindValue, colChange, colChangeValue)
        dim curRow
        dim updateSQL
        dim checkSQL

        checkSQL = "select * from Details"
        set myrs1 = db_execute_query( curConnection , SQL )
        myrs1.MoveFirst
        count_fields = myrs1.fields.count
        If ( TypeName(colFind)<> "String" ) or ( TypeName(colChange)<> "String" ) then
            db_set_field_value = -1 'requested field index that doesn't exists in the record set
        Else
            updateSQL = "UPDATE " & tableName & " SET " & colChange & "='" & colChangeValue & "' WHERE " & colFind & "='" & colFindValue & "'"
            set myrs1 = db_execute_query( curConnection , updateSQL )
            db_set_field_value = 1 'operation suceeded
        End If
    End Function

    '*************************************************************************************************
    ' db_add_row
    ' -----------------
    ' The function adds a new row to the desired table

    ' curConnection - variable , contains a recordset , that contains all the values to be retrieved from DB by query execution
    ' tableName - name of the table , where value should be retrieved from
    ' values - array that contains values to be entered in a new row to the table.

    ' Note: the function must receive values for all the columns in the table!
    ' returned values
    ' -1 - the number of values to be entered to the table doesn't fit the number of columns
    ' 1 - execution of the query succeed and the data was entered to the table
    '*************************************************************************************************
    Function db_add_row(curConnection, tableName , byRef values)
        dim i
        dim updateSQL
        dim myrs1

        updateSQL = "INSERT INTO " & tableName & " VALUES ("
        arrLen = UBound (values) - LBound (values) + 1

        set myrs1=db_execute_query( curConnection , SQL )
        myrs1.MoveFirst
        count_fields = myrs1.fields.count
        ' check if numbers of values fit the numbers of columns
        If arrLen <> count_fields then
            db_add_row = -1
        Else
            For i = 0 to arrLen-1
                updateSQL = updateSQL & values (i)
                If i <> arrLen-1 then
                    updateSQL = updateSQL & ","
                End If
            Next
            updateSQL = updateSQL & ")"
            set myrs1 = db_execute_query( curConnection , updateSQL )
            db_add_row = 1
         End If
    End Function

    '*************************************************************************************************
    ' represent_values_of_RecordSet
    ' ---------------------------------------------
    ' the function reports all the values on fields in a record set
    ' curRS - variable , contains the recordset , that contains all the values that were retrieved from the DB by the query execution
    '*************************************************************************************************
    Function represent_values_of_RecordSet( myrs)
        dim curRowString
        myrs.MoveFirst
        reporter.ReportEvent 4,"Fields quantity" , myrs.fields.count
        count_fields = myrs.fields.count-1
        curRow=0
        Do Until myrs.EOF
            curRowString= ""
            curRow = curRow+1
            For ii=0 to count_fields
                curRowString = curRowString& "Field " &"==> " & myrs.fields(ii).Name &" : Value ==>" & myrs.fields(ii).Value & vbCrLf
            Next
            myrs.MoveNext
            reporter.ReportEvent 4,"Current row"& curRow , curRowString
        Loop
    End Function

  • QTP FrameWork 子文件夹

    2008-12-02 14:36:48

    例:
    1.scrīpt files (.mts)
    2.OR files (.mtr-> per action , .tsr-> shared)
    3.Library files( .vbs)
    4.Recovery files (.qrs)
    5.Test Data files .xls
    6.Output/Result files (.xml)
    7.Functions (.txt)
    8. Documents (.xls or xlsx)
     
    例:
    1.SoftWare
    2.Config
    3.Log
    4.Report
    5.Test Data
    6.lib
    7.Documents
  • hp winrunner 百问 三

    2008-10-16 22:29:04

    winRunner api 调用,例子中实现如何获得功能执行时间

    load_dll ("C:\\WINNT\\SYSTEM32\\kernel32.dll");
    extern int GetTickCount();
    <code code code>
    start=GetTickCount();
    <transaction to be timed code goes here>
    end=GetTickCount();
    # Note posting to a file
    post_tick_count_time_lapse(start,end,"Transaction Title","C:\\temp.txt");

    #-----------------------------------------------------------------------------------------------------------------
    # FUNCTION CODE BELOW
    public function post_tick_count_time_lapse (in starttime, in endtime, in transtitle, in filename)
    {
    # Declare variables
    auto timelapse;
    # Validate parameters
    if (nargs() != 3 && nargs() != 4)
    {
    tl_step ("get_tick_count_time_lapse", FAIL, "Only 3 or 4 parameters are allowed.");
    return(E_ILLEGAL_NUM_OF_PARAMS);
    }
    # Determine how long the transaction took and round
    timelapse = int((endtime - starttime) + .5)/1000;
    # Post timelapse
    if (nargs() == 3) # Was no ouput file specified
    report_msg (transtitle & " : " & timelapse & " seconds"); # Send output to the test results
    else   # There was an ouput file specified
    {
    print (transtitle & " : " & timelapse & " seconds |" & get_time()) >> filename; # Append output to specified file
    # Note "|" is a file delimiter above
    close(filename);
    }
    return(E_OK);


  • hp-WinRunner 百问 二

    2008-10-05 16:26:15

      

        WinRunner使用TSL脚本,主要是类c的语法,wr调用com对象难度比较大,这里利用另类办法调用底层com对象,主要利用wr中file的操作以及dos_system的调用方法,实现,通过这种方法可以加强wr的脚本扩展能力的缺陷。例子如下:

    public function send_outlook_mail(in to, in cc, in bcc, in subject, in body, in attach)
    {
    auto i, scrīpt;

    scrīpt = getvar("exp") & "\\send_outlook_mail.vbs";

    file_open(scrīpt,FO_MODE_WRITE);
    file_printf(scrīpt,"Dim objOutlook\r\n");
    file_printf(scrīpt,"Dim objOutlookMsg\r\n");
    file_printf(scrīpt,"Set ōbjOutlook = CreateObject(\"Outlook.Application\")\r\n");
    file_printf(scrīpt,"Set ōbjOutlookMsg = objOutlook.CreateItem(olMailItem)\r\n");
    file_printf(scrīpt,"objOutlookMsg.To = \"%s\"\r\n", to);
    file_printf(scrīpt,"objOutlookMsg.CC = \"%s\"\r\n", cc);
    file_printf(scrīpt,"objOutlookMsg.BCC = \"%s\"\r\n", bcc);
    file_printf(scrīpt,"objOutlookMsg.Subject = \"%s\"\r\n", subject);
    file_printf(scrīpt,"objOutlookMsg.Body = \"%s\"\r\n", body);
    file_printf(scrīpt,"objOutlookMsg.attachments.add \"%s\"\r\n", attach);
    file_printf(scrīpt,"objOutlookMsg.Send\r\n");
    file_close(scrīpt);
    dos_system("wscrīpt \"" & scrīpt & "\"");
    #dos_system("del \"" & scrīpt & "\"");
    return(E_OK);
    }

    Example:

    send_outlook_mail("pcl@51testing.com.com","","","Daily reports","Winrunner scrīpt to check the status of Daily reports is Completed.Check the results attached.Thanks.",file);

     

  • hp - WinRunner 百问 一

    2008-09-21 14:03:34

    How to Close all Browsers that were opened before WinRunner?

    1.The close_browsers function will close browsers that were opened
    before WinRunner
    function close_browsers()
    {
       auto count, count2;
       count = 0;
       while (win_exists("{class: window,MSW_class:browser_main_window,location:" & count & "}")==0)
          count++;
       for (count2 = 0; count2 < count; count2++)
          win_close("{class: window,MSW_class:browser_main_window,location:"0"}"); 
       # close IE-spawned browser windows
       count = 0;
       while (win_exists("{class: window,MSW_class: IEFrame,location:" &
    count & "}")==0)
          count++;
       for (count2 = 0; count2 < count; count2++)
          win_close("{class: window,MSW_class: IEFrame,location:"0"}");

       # close browsers open before WinRunner

       set_class_map("mic_unknown_class", "window");
       set_record_attr("mic_unknown_class", "class", "MSW_class",
    "location");
       set_record_method("mic_unknown_class", RM_RECORD); 
       count = 0;
       while (win_exists("{class: window,MSW_class:
    mic_unknown_class,location: " & count & "}")==0)
          count++;
       for (count2 = 0; count2 < count; count2++)
          win_close("{class: window,MSW_class: mic_unknown_class,location:" & count & "}");
    }

    2. This version of the function may execute a little faster when using
    Netscape:

    public function close_all_browsers()
    {
        auto desc = "{class: window,MSW_class:
    browser_main_window,NSTitle: \"Browser Main
    Window\",location:",x,y,done;
        auto desc2 = "{class: window,label: \"!.*Microsoft Internet
    Explorer\",MSW_class: IEFrame,location:";
        auto val = 50; # this line acutally sets the number of browser
    windows to close
        x = val;
        done=0;
        while(x >= 0)
        {
            y = desc&x--&"}";
            if(E_OK == win_exists(y))
            {
                win_activate(y);
                win_close(y);
            }
        }
        x = val;
        while(x>=0)
        {
            y = desc2&x--&"}";
            if(E_OK == win_exists(y))
            {
               win_activate(y);
                win_close(y);
            }
        }
        return E_OK;
    }

    3. You can use the undocumented _web_browser_close function to close
    all browsers that were opened after WinRunner. Using empty quotes ""
    will close all browsers opened after WinRunner. To close a specific
    browser, pass the logical name of the browser to the function.

    _web_browser_close("");

    EXAMPLE:
    # Close all open browser windows:
    _web_browser_close("");

    Here is a function which uses _web_browser_close to close the browsers
    opened after WinRunner and will also close the browsers opened before
    WinRunner.

    public function close_all_browsers2()
    {

        # close browser opened after WinRunner
        _web_browser_close("");

        # close browsers open before WinRunner
        set_class_map("mic_unknown_class", "window");
        set_record_attr("mic_unknown_class", "class", "MSW_class",
    "location");
        set_record_method("mic_unknown_class", RM_RECORD);

        while (win_exists("{class: window, MSW_class: mic_unknown_class,
    location: 0}") == E_OK)
        {
           win_activate("{class: window, MSW_class: mic_unknown_class,
    location: 0}");
           win_close("{class: window, MSW_class: mic_unknown_class,
    location: 0}");
        }

    }

    4. If the functions above have problems closing browsers opened before
    WinRunner, you can try using the following code in one of the
    functions. This code checks the items in the Shell Tray (the toolbar
    at the bottom that lists the running applications) and selects the
    ones that correspond with the browsers. This should bring the browser
    to the foreground, at which point the type function can be used to
    press Alt-F4 in order to close the window. This should work on Windows
    95, 98, NT 4.0, and 2000. This will not work on Windows XP in its
    current form, due to the way that Windows XP represents the items in
    the Shell Tray as a toolbar, rather than a tab control. Similar
    functionality should work, however, for Windows XP using toolbar
    functions, instead of tab functions.

    set_window("Shell_TrayWnd", 3);
    tab_get_info("tab", "count", count);
    for(i = count-1; i > 0; --i)
    {
        tab_get_item("tab", i, item);
        if(match(item, ".*Microsoft Internet Explorer") > 0 || match(item,
    ".*Netscape") > 0)
        {
           tab_select_item("tab", "#" & i);
           wait(1);
           type("<kAlt_L-kF4>");
           wait(1);
        }

    }

  • Winrunner_Robot_数据驱动脚本代码

    2008-09-17 13:04:56

    WinRunner
    读取文件没有循环:
    # Flight Reservation
    win_activate ("Flight Reservation");
    set_window ("Flight Reservation", 5);
    file_open("C:\\Win_execirses\\Dat2.txt",FO_MODE_READ);
    file_getline("C:\\Win_execirses\\Dat2.txt",line);
    split(line,array,";");

    obj_type ("MSMaskWndClass",array[1]);
    list_select_item ("Fly From:",array[2]);  # Item Number 0;
    list_select_item ("Fly To:", array[3]);  # Item Number 0;
    obj_mouse_click ("FLIGHT", 32, 45, LEFT);

    # Flights Table
    set_window ("Flights Table", 2);
    button_press ("OK");

    # Flight Reservation
    set_window ("Flight Reservation", 8);
    edit_set ("Name:", array[4]);
    button_set ("First", ON);
    button_press ("Insert Order");
    set_window ("Flight Reservation", 8);
    obj_mouse_click ("Button", 7, 13, LEFT);

    #obj_mouse_click ("Button_4", 12, 11, LEFT);
    file_close("C:\\Win_execirses\\Dat2.txt");


    优化上面脚本,带有循环驱动:
    # Flight Reservation
    win_activate ("Flight Reservation");
    set_window ("Flight Reservation", 5);
    file_open("C:\\Win_execirses\\Dat2.txt",FO_MODE_READ);
    while(file_getline("C:\\Win_execirses\\dat2.txt",line)==0)
    {
    # file_getline("C:\\Win_execirses\\Dat2.txt",line);
    split(line,array,";");


    obj_type ("MSMaskWndClass",array[1]);
    list_select_item ("Fly From:",array[2]);  # Item Number 0;
    list_select_item ("Fly To:", array[3]);  # Item Number 0;
    obj_mouse_click ("FLIGHT", 32, 45, LEFT);
    # Flights Table
    set_window ("Flights Table", 2);
    button_press ("OK");
    # Flight Reservation
    set_window ("Flight Reservation", 8);
    edit_set ("Name:", array[4]);
    button_set ("First", ON);
    edit_set ("Tickets:", array[5]);
    button_press ("Insert Order");
    set_window ("Flight Reservation", 8);
    # Flight Reservation
    set_window ("Flight Reservation", 4);
    obj_mouse_click ("Button", 18, 10, LEFT);
    # obj_mouse_click ("Button_4", 12, 11, LEFT);
    }
    file_close("C:\\Win_execirses\\Dat2.txt");


    Rational Robot脚本:
    数据驱动脚本-数据池技术:
    '$include "SQAutil.sbh"
    Sub Main
        Dim dp_Result As Integer
        dim dp_id as long
        'dim dp_result as string
        dim dp_Date as string
        dim dp_Flyfrom as string
        dim dp_Flyto as string
        dim dp_Name as string
        
        
        dp_id = SQAdatapoolopen("datapooltest1",FALSE, SQA_DP_SEQUENTIAL,FALSE)
        
        dp_result = SQAdatapoolfetch (dp_id)    
        Window SetContext, "Caption=Flight Reservation", ""
        dp_result = SQAdatapoolvalue (dp_id,1,dp_Date)
        InputKeys dp_Date
        ComboBox Click, "ObjectIndex=1", "Coords=120,13"
        dp_Result=SQADatapoolvalue(dp_id,2,dp_Flyfrom)
        ComboListBox Click, "ObjectIndex=1", "Text="&dp_Flyfrom
        ComboBox Click, "ObjectIndex=2", "Coords=117,8"
        dp_result=SQADatapoolvalue(dp_id,3,dp_Flyto)    
        ComboListBox Click, "ObjectIndex=2", "Text="&dp_Flyto
        PushButton Click, "Text=FLIGHT" 
        Window SetContext, "Caption=Flights Table", ""
        'ListBox Click, "ObjectIndex=1", "Text=16877   LAX   08:00 AM   LON   08:45 AM   SR     $162.30;Coords=272,23"
        PushButton Click, "Text=OK"
        
        Window SetContext, "Caption=Flight Reservation", ""
        dp_result = SQAdatapoolvalue (dp_id,4,dp_Name)
        InputKeys dp_Name
        PushButton Click, "Text=Insert Order"
        PushButton Click, "ObjectIndex=9"
      
        dp_result=SQADatapoolClose (dp_id)

    End Sub


    数据驱动脚本-数据池技术 优化版本:

    '$include "SQAutil.sbh"
    Sub Main
        Dim dp_Result As Integer
        dim dp_id as long
        'dim dp_result as string
        dim dp_Date as string
        dim dp_Flyfrom as string
        dim dp_Flyto as string
        dim dp_Name as string
        dim i as integer  
        
        dp_id = SQAdatapoolopen("datapooltest1",FALSE, SQA_DP_SEQUENTIAL,FALSE)    
        for i = 1 to 3
        dp_result = SQAdatapoolfetch (dp_id)    
        Window SetContext, "Caption=Flight Reservation", ""
        dp_result = SQAdatapoolvalue (dp_id,1,dp_Date)
        InputKeys dp_Date
        ComboBox Click, "ObjectIndex=1", "Coords=120,13"
        dp_Result=SQADatapoolvalue(dp_id,2,dp_Flyfrom)
        ComboListBox Click, "ObjectIndex=1", "Text="&dp_Flyfrom
        ComboBox Click, "ObjectIndex=2", "Coords=117,8"
        dp_result=SQADatapoolvalue(dp_id,3,dp_Flyto)
        
        ComboListBox Click, "ObjectIndex=2", "Text="&dp_Flyto
        PushButton Click, "Text=FLIGHT"
        
        Window SetContext, "Caption=Flights Table", ""
        'ListBox Click, "ObjectIndex=1", "Text=16877   LAX   08:00 AM   LON   08:45 AM   SR     $162.30;Coords=272,23"
        PushButton Click, "Text=OK"
        Window SetContext, "Caption=Flight Reservation", ""
        dp_result = SQAdatapoolvalue (dp_id,4,dp_Name)
        InputKeys dp_Name
        PushButton Click, "Text=Insert Order"
        PushButton Click, "ObjectIndex=9"
        next i
        dp_result=SQADatapoolClose (dp_id)

    End Sub


    数据驱动 - 文件技术:
    Sub Main
    Dim date1 as string
    Dim flyfrom as string
    Dim flyto as string
    Dim name1 as string
    Dim file as string

    file="C:\Rational_files\datafile1.txt"
    open file for input access read as #1
    while not eof(1)
    Input #1, date1,flyfrom,flyto,name1 
        Window SetContext, "Caption=Flight Reservation", ""
        InputKeys date1
        ComboBox Click, "ObjectIndex=1", "Coords=108,15"
        ComboListBox Click, "ObjectIndex=1", "Text="&flyfrom
        ComboBox Click, "ObjectIndex=2", "Coords=118,11"
        ComboListBox Click, "ObjectIndex=2", "Text="&flyto
        PushButton Click, "Text=FLIGHT"
        Window SetContext, "Caption=Flights Table", ""
        PushButton Click, "Text=OK"    
        Window SetContext, "Caption=Flight Reservation", ""
        InputKeys name1
        PushButton Click, "Text=Insert Order"
        PushButton Click, "ObjectIndex=9"
        wend
        close #1
    End Sub

  • HP 测试工具的支持环境

    2008-09-14 19:17:04

       到今天,hp性能测试工具LoadRunner已经支持多达60种协议,qtp提供25种插件环境,并且其他厂商提供了扩展插件2种,另外hp合作伙伴在测试管理工具qc基础上集成了13种插件,hp测试软件功能越来越强大同时软件包也变得越来越大

    HP LoadRunner Protocols:
    Action Message Format(AMF O)
    c#.Net Template(Visual Studio add-in)
    C++.net Template(Visual Studio add-in)
    Citrix_ICA
    COM/DCOM
    CORBA-Java(tm)
    C vuser
    DB2 CLI
    Domain Name Resolution(DNR)
    Enterprise Java Protocol
    HP WinRunner Software
    HP QuickTestProfessional Software
    i-mode
    internet messaging(imap)
    jacada
    java Vuser
    Javascrīpt Vuser
    Lightweight Director Access Protocol(LDAP)
    MediaPlayer(mms)
    MQSeries-Client
    MQSeries-Server
    MS Exchange(MAPI)
    MS Sequel Server Informix
    Multimedia Messaging Service(MMS)
    ODBC
    Oracle(2-tier)
    Oracle NCA
    Oracle Web Application 11.i(c&s for Oracle)
    Palm
    PeopleSoft Tuxedo
    Peoplesoft Enterprise(c&s for PeopleSoft)
    Post office Protocol(POP3)
    RealPlayer
    Rmi-java
    SAPGUI
    SAPGUI/SAP-WEB Dual Protocol
    SAP-WEB
    Siebel-DB2 CLI
    Siebel-Oracle
    Siebel-MySql
    Siebel-web
    Simple Mail Protocol(smtp)
    Sybase CTLib
    Sybase DBLib
    Terminal Emulation(RTE)
    Tuxedo 6/7
    vb vuser
    vb scrīpt vuser
    vbnet vuser
    vbnet Template(visual studio add-in)
    VoiceXML
    WAP
    Web(http/html)
    web click and scrīpt
    web services
    windows sockets

    HP LoadRunner partner protocols:
    Cognos(Genilogix)
    JDBC(J2EE911)
    SIP(Utopia)

    HP QuickTest Professional add-ins
    Legacy 3270,5250 enulators,vt100
    activex
    citrix
    delphi8.net winforms
    htc/viewlink
    internet explorer
    java swt
    jdedwards web client
    jdk,javafoundation classes,awt
    mozilla firefox 2.0
    netscape
    oracle 11i
    peoplesoft 8.x
    sap
    siebel 7.x/8.x
    stingray
    visual basic
    visualage smalltalk
    vmware desktop support
    web forms
    web services
    windows2000,windows2003,windowsxp ,windos vista
    winforms
    wpf from.net3.0

    HP QuickTest Professional partner add-ins
    Flex(adobe)
    TestAdvantage(infragistics)

    HP Quality Center partner integrations
    AccuBridge(accurev)
    CollabNet Conector(CollabNet)
    NetProcess(Intellicorp)
    Integrity Suite(MKS)
    Personal Navigator(OnDemand Software)
    SCM System(Perforce)
    TestSmart(Sapphire infotech)
    TeamTrack(Serena)
    PVCS Version Manager(Serena)
    Profesy(Sofea)
    Solstice Integra Suite(Solstice Software)
    QAInspect(SPI Dynamics)
    Virual QA/Test Lab Management System(Surgient)

     

  • 自动化测试代码赏析

    2008-09-11 11:43:37

    如果你有兴趣,请把代码分析的结果写下来,因为看别人的代码,是提高自己自身能力的最快途径之一,当下公司招聘很多都需要测试人员懂工具,有的公司在面试过程中还拿出代码让测试人员来读,分析代码的结果是什么。古人说 "熟读唐诗三百首,不会做诗也会吟",希望你也成为一个自动化测试开发高手:

    代码 一:

    txtSearch = "T"
    Set edtxt = CreateObject("Wscrīpt.Shell")
    Browser(" ").Page(" ").WebEdit(" ").Click
    edtxt.SendKeys(txtSearch)
    Set edtxt = Nothing

    rowCount = Browser(" ").Page(" ").WebTable(" ").GetROProperty("rows")
    For j = 1  to rowCount
          strTxt =  Browser(" ").Page(" ").WebTable(" ").GetCellData(j,1)
          strColor = Browser(" ").Page(" ").WebTable(" ").Object.rows(j-1).cells(1).currentStyle.backgroundColor

           If strColor = "#fffde8" Then
                reporter.ReportEvent micDone, "Text Highlighted", "The text  """&strTxt&""" is highlighted."
            strPos = left(strTxt,1)
                If (Trim(txtSearch) = Trim(strPos)) Then
                          reporter.ReportEvent micPass, "Highlighted", "First Letter of highlighted text  """&strTxt&""" starts with """&strPos&"""."
                Else
                       reporter.ReportEvent micFail, "Highlighted", "Text  """&strTxt&""" doesn't start  with letter """&strPos&"""."
                End If
           End If
    Next

    代码 二:

    Set ōbjDesc = Descrīption.Create()
    objDesc("micclass").Value = "WebEdit"

    Set ōbjWE = Browser().Page().ChildObjects(objDesc)
    objWECount = objWE.Count

    For i = 0 to objWECount-1
         Set ōbjCP = objWE(i).Object
         ChkPointWE = objCP.IsContentEditable
         Print objWE(i).GetROProperty("name")
         Print ChkPointWE
    Next

    代码 三:自动化测试框架代码,本框架基于SAFFRON(mercury)框架为基础实现的针对mercury自带的网上售票系统的关键字数据驱动其中SAFFRON(mercury)部分:

    框架核心代码:

    '************************************************************
    ' S.A.F.F.R.O.N. Prototype 1.1'
    ' Simple Automation Framework For Remarkably Obvious Notes
    ' Copyright © 2006 Mercury Interactive Corporation
    '
    ' Notes:
    '
    ' Requires QuickTest Professional 9.1
    '
    ' Author       : Adam Gensler
    ' Created      : July 12, 2006
    ' Last Updated : September 11, 2006
    '
    ' This prototype framework is provided AS IS, and is meant
    ' to be used for instructional purposes.
    '
    ' This framework is a prototype, and is not supported
    ' by Mercury Interactive.
    '
    '************************************************************
    initialized = false
    thirdlevel = ""
    level = ""
    desc = ""
    object = ""
    objectDescrīption = ""

    levelsubdescrīptiondelimiter = ","
    leveldescdelimiter = "|"
    objectdelimiter = "|"
    leveldelimiter = "|"
    objectsDescrīptiondelimiter = "|"

    webLevels = "Browser|Page|Frame"
    webLevelsDesc = "micclass:=Browser|micclass:=Page|micclass:=Frame|"
    objects = "Link|WebButton|WebList|WebEdit"
    objectsDescrīption = "micclass:=Link|micclass:=WebButton|micclass:=WebList|micclass:=WebEdit"

    ' Generates a generic descrīption based up on the "level" viarable
    ' levelstr - will be one of the values that is in the level array
    ' returns - string representative of the object hierarchy
    Public Function GenerateDescrīption (levelstr)
     l = IndexOf(level, levelstr)
     If l >=0 Then
      fdesc = level(0) & "(" & Quote(desc(0)) & ")."
      If l >= 1 Then
       fdesc = fdesc + level(1) & "(" & Quote(desc(1)) & ")."
       If 2 >= l Then
        If thirdlevel <> "" Then
         fdesc = fdesc + level(2) & "(" & Quote(desc(2)) & "," & Quote("name:=" & thirdlevel) & ")."
        End If
       End If
      End If
     End If
       GenerateDescrīption = fdesc
    End Function

    ' Generates an object descrīption based upon the object, and objectDescrīption arrays
    ' obj - name of the object in the object array
    ' prop - additional property to help uniquely identify the object
    ' returns - a string representative of the object descrīption
    Public Function GenerateObjectDescrīption (obj, prop)
     i = IndexOf(object, obj)
     ndesc = ""
       If i <> -1 Then
      ndesc = obj & "(" & Quote(objectDescrīption(i)) & "," & Quote(prop) & ")."
     End If
     GenerateobjectDescrīption = ndesc
    End Function

    ' given an array, returns the index of the value to search for
    ' ary - an array
    ' str - value to search for in an array
    ' returns - index in array
    Public Function IndexOf (ary, str)
     val = -1
     For i = 0 to UBound(ary)
      If ary(i) = str Then
       val = i
      End If
     Next
     IndexOf = val
    End Function

    ' configures framework to work within the context of a specific frame
    ' val - the Name of the frame to work within -- use Object Spy if you don't
    '       already know the frame name
    Public Function WorkInFrame (val)
     Report micPass, "Enter Frame", "Entered scope of frame " & Quote(val)
     thirdlevel = val
    End Function

    ' configures the framework to work outside the context of a specific frame
    Public Function StopWorkingInFrame
     Report micPass, "Exit Frame", "Exited scope of frame " & Quote(thirdlevel)
     thirdlevel = ""
    End Function

    ' generates a string with embedded/surrounding quotes
    Public Function Quote (txt)
     Quote = chr(34) & txt & chr(34)
    End Function

    ' navigate to a site if the browser is already opened, otherwise run initialization
    Public Function BrowseTo (url)
     thirdlevel = ""
     Report micPass, "Navigate to URL", "Navigating to URL: " & Quote(url)
     If initialized Then
      Execute GenerateDescrīption("Browser") & "Navigate " & Quote(url)
     Else
      Launch "website", url
     End If
     Reporter.Filter = rfDisableAll
    End Function

    ' waits for the web page to finish loading
    Public Function AutoSync
        Execute GenerateDescrīption("Browser") & "Sync"
    End Function

    ' close all opened browsers
    Public Function CloseBrowsers
     If Browser("micclass:=Browser").Exist (0) Then
      Browser("micclass:=Browser").Close
     End If
     While Browser("micclass:=Browser", "index:=1").Exist (0)
      Browser("index:=1").Close
     Wend
     If Browser("micclass:=Browser").Exist (0) Then
      Browser("micclass:=Browser").Close
     End If
    End Function

    ' prepares the framework for usage, and configures all internal framework
    ' variables and structures
    ' apptype - used to launch different types of applications based
    '           upon different technologies -- currently there is only web
    ' val     - string that represents what to launch
    ' returns - always returns true
    Public Function Launch (apptype, val)
     If "website" = apptype Then
      thirdlevel = ""
      Report micPass, "Initialize", "Initializing Framework"
      level = split(webLevels, leveldelimiter, -1, 1)
      desc = split(webLevelsDesc, leveldescdelimiter, -1, 1)
      object = split(objects, objectdelimiter, -1, 1)
      objectDescrīption = split(objectsDescrīption, objectsDescrīptiondelimiter, -1, 1)
      CloseBrowsers
      Set IE = CreateObject("InternetExplorer.Application")
      IE.visible = true
      IE.Navigate val
      While IE.Busy
       wait 1
      Wend
     End If
     initialized = true
     Launch = true
    End Function

    ' Verify the Existence of an object
    ' objtype - values should be limited to values in the object array
    ' text    - multi-purpose argument that indicates what to verify
    '         - for a link, or button, it's the text of the control
    '         - for a list, it's the name of the control
    '         - for a frame, it's the name of the frame
    Public Function Verify (objtype, text)
       rval = false
     localDesc = ""
     estr = ""
     If thirdlevel <> "" Then
      localDesc = GenerateDescrīption(level(2))
     Else
      localDesc = GenerateDescrīption(level(1))
     End If

       AutoSync()

     Select Case objtype
     Case "Page"
      Execute "rval = " & GenerateDescrīption(level(1)) & "Exist (0)"
      If rval Then
       Execute "title = " & GenerateDescrīption(level(1)) & "GetROProperty(" & Quote("title") & ")"
       If title = text Then
        rval = true
       Else
        rval = false
       End If
      End If
     Case "CurrentFrame"
      If thirdlevel <> "" Then
       estr = "rval = " & localDesc
      End If
     Case "Link"
      estr =  "rval = " & localDesc & GenerateObjectDescrīption("Link", "innertext:=" & text)
     Case "WebButton"
      estr = "rval = " & localDesc & GenerateObjectDescrīption("WebButton", "value:=" & text)
     Case "WebList"
      estr = "rval = " & localDesc & GenerateObjectDescrīption("WebList", "name:=" & text)
     Case "WebEdit"
      estr = "rval = " & localDesc & GenerateObjectDescrīption("WebEdit", "name:=" & text)
     End Select

     If estr <> "" Then
      Execute estr + "Exist (0)"
     End If

     If rval Then
      Report micPass, objtype & " Verification", "The " & objtype & " " & Quote(text) & " was verified to exist"
     Else
      Report micFail, objtype & "  Verification", "The " & objtype & " " & Quote(text) & " was not found"
     End If

     If "True" = rval Then
      rval = True
     Else
      rval = False
     End If

       Verify = rval
    End Function

    ' Activates an object based upon its object type
    ' objtype - the type of object should be limited to values in the object array
    ' text    - identifying text for the control - for a link, it's the text of the link
    Public Function Activate (objtype, text)
     localDesc = ""
     If thirdlevel <> "" Then
      localDesc = GenerateDescrīption(level(2))
     Else
      localDesc = GenerateDescrīption(level(1))
     End If

     AutoSync() 

     Select Case objtype
     Case  "Link"
      Execute localDesc & GenerateObjectDescrīption("Link","innertext:=" & text) & "Click"
      Report micPass, "Link Activation", "The Link " & Quote(text) & " was clicked."
     Case "WebButton"
      Execute localDesc & GenerateObjectDescrīption("WebButton", "value:=" & text) & "Click"
      Report micPass, "WebButton Activation", "The WebButton " & Quote(text) & " was clicked."
     End Select
    End Function

    ' Selects a specific value from a listbox, or combobox
    ' objname - name of the control -- use Object Spy if you don't know the name property
    ' text    - the item in the combobox to select
    Public Function SelectFromList (objname, text)
     localDesc = ""
     rv = ""
     rval = false
     If thirdlevel <> "" Then
      localDesc = GenerateDescrīption(level(2))
     Else
      localDesc = GenerateDescrīption(level(1))
     End If

     AutoSync() 

     localDesc = localdesc & GenerateObjectDescrīption("WebList", "name:=" & objname)

     Execute "cnt = " & localDesc & "GetROProperty(" & Quote("items count") & ")"
     For i = 1 to cnt
      Execute "rv = " & localDesc & "GetItem (" & i & ")"
      If rv = text Then
       rval = true
      End If
     Next

     If rval Then
      Execute localDesc & "Select " & Quote(text)
     End If
     If rval Then
      Report micPass, "WebList Selection", "The WebList item " & Quote(text) & " was selected."
     Else
      Report micFail, "WebList Selection", "The WebList item " & Quote(text) & " was NOT found."
     End If

     SelectFromList = rval
    End Function

    ' Enters text into an edit field
    ' objname - name of the control -- use Object Spy if you don't know what it is
    ' text    - the text to enter into the control
    Public Function EnterTextIn (objname, text)
     localDesc = ""
     rval = true
     If thirdlevel <> "" Then
      localDesc = GenerateDescrīption(level(2))
     Else
      localDesc = GenerateDescrīption(level(1))
     End If

     AutoSync()

     localDesc = localdesc & GenerateObjectDescrīption("WebEdit", "name:=" & objname)
     Execute localDesc & "Set (" & Quote(text) & ")"
     Report micPass, "Enter Text", "Text: " & Quote(text) & " was entered into " & Quote(objname)
     EnterTextIn = rval 
    End Function

    ' Obtains text from a control
    ' objtype - is the type of control the get the text from
    ' objname - is the name of the control -- use Object Spy if you don't know the name
    ' returns - the text of the control
    Public Function GetTextFrom (objtype, objname)
     text = ""
     localDesc = ""
     If thirdlevel <> "" Then
      localDesc = GenerateDescrīption(level(2))
     Else
      localDesc = GenerateDescrīption(level(1))
     End If

     AutoSync()

     Select Case objtype
      Case "WebEdit"
       Execute "text = " & localDesc & GenerateObjectDescrīption("WebEdit", "name:=" & objname) & "GetROProperty (" & Quote("value") & ")"
      Case "WebList"
       Execute "text = " & localDesc & GenerateObjectDescrīption("WebList", "name:=" & objname) & "GetROProperty (" & Quote("value") & ")"
     End Select
     Report micPass, "Capture Text", "Text: " & Quote(text) & " was captured from the control " & Quote(objname)
     GetTextFrom = text
    End Function

    ' Wrapper for the Reporter.Report Event method
    ' - could be used to create custom reports more easily
    ' See Reporter.ReportEvent documentation for usage
    Public Function Report (status, objtype, text)
     Reporter.Filter = rtEnableAll
     Reporter.ReportEvent status, objtype, text
     Reporter.Filter = rfDisableAll
    End Function

    基于此框架的qtp网上售票的系统的框架代码例子想要的人请加: pcl2004_19@hotmail.com

  • 解决RationalRobot获取htmlTableCell数据的技术

    2008-09-09 12:53:45

        昨天有位朋友通过msn加我,想解决RationalRobot如何获得HtmlTable中的Cell的数据问题,他在网上通过寻找以前的(2004-2005)年的帖子找到我,希望能解决这个问题,在论坛上大家给出的答案都是要扩展robot开发dll或者是解析网页,但是具体如何做没有给出代码,其实这个问题这么做就复杂了,robot我觉得是一个很不错的工具,2004年我写了很多关于robot心得的文章,记得第一篇在网络上发表的文章robot识别datagrid控件对象就是为了帮一个广州朋友解决问题得出的心得.
       问题是这样如何用rational robot获得htmltablecell的内容,这个robot本身确实做的不是很好,获得cell的数据需要根据索引来进行定位,我们先看如何获得htmltable的内容,我写了一个html页面文件代码如下:
    <HTML>
    <HEAD><TITLE>test</TITLE></HEAD>
    <BODY>
    <TABLE id=testaa>
       <TR>
          <TD>Jones</TD>
       </TR>
       <TR>
          <TD>Smith</TD>
       </TR>
       <TR>
        <TD>Harry</TD>
       </TR>
    </TABLE>
    </BODY>
    </HTML>
    保存为html文件后用ie打开,然后编写robot自动化测试代码如下:
    Sub Main
       Dim Value as variant
        Window SetContext, "Caption=test - Microsoft Internet Explorer",""
        Browser NewPage,"",""
        SQAGetProperty "Type=HTMLTable;HTMLId= testaa","InnerText",value
        SQAConsoleWrite "Value : "& value
    End Sub
    获得数据为 jones Smith Harry
    如何用robot获得其中cell中的单独数据呢,其实robot把html中的cell识别成htmltablecell对象,而获得其中的内容需要根据index来定位,我这个测试页面只有一个table,那么它的第一个cell的index就是1,第二个cell的index就是2
    所以修改自动化测试脚本代码看如何获得第一个 第二个 第三个cell的数据,修改代码如下:
    Sub Main
        Dim Result As Integer
        Dim iCellCount as Integer
        Dim Value as variant
        for iCellCount=1 to 3 
            Window SetContext, "Caption=test - Microsoft Internet Explorer",""
            Browser NewPage,"",""
            SQAGetProperty "Type=HTMLTableCell;index="+ iCellCount,"outerText",value
            SQAConsoleWrite Cstr(i iCellCount)+"Value : "& value
         next iCellCount 
    End Sub

    如果网页中有3个table,每个table横三行竖三列
    table 1
    ---------------------------
      1  |     2      |      3 
    ---------------------------
      4  |     5      |      6 
    ---------------------------
    table 2
    ---------------------------
      1  |     2      |      3 
    ---------------------------
      4  |     5      |      6 
    ---------------------------
    table 3
    ---------------------------
      1  |     2      |      3 
    ---------------------------
      4  |     5      |      6 
    ---------------------------
    如果要获得第二个table中的第一个cell中的内容,那么index就是7

    以上为利用robot自身解决获得cell表格内容的方法,当然还有其他网友提供的解析页面文件的方法,利用dom技术。

  • Qtp 9.5 温柔破解试验 一步破解成功

    2008-09-08 11:10:39

        
           周末在家休息,打开qtp想调试一些写的代码,但是发现qtp9.5过期,本人很懒实在厌烦重新安装系统,到网上看资料发现都是先破解qtp8.2或者9.2然后卸载8.2或者9.2版本然后在安装9.5版本,那有没有办法直接破解呢?
          思考:8.2到9.2的破解方式是把mgn-mqt82.exe文件拷贝到C:\Program Files\Mercury Interactive和qtp同级目录,然后执行该破解文件,但是到了9.5版本安装路径变成C:\Program Files\HP了,我想肯定是是否是文件夹路径改变后导致破解不成功,所以先在系统中创建了C:\Program Files\Mercury Interactive文件夹,然后把mgn-mqt82.exe拷贝到文件夹下,执行该破解文件,意想不到的事情发生,系统错误mgn-mqt82报错,不管三七二十执行QTP 9.5,发现破解没有完成。
               既然不行换个思路,以前我用mgn-mqt82.exe破解8.2的时候,经常发现破解不成功的问题,就到C:\Program Files\Common Files\Mercury Interactive\License Manager文件夹下去修改LSERVRC文件,删除里面的生成代码,再次执行mgn-mqt82.exe,反复几次就可以达到破解8.2的目的。
              既然这样我就到C:\Program Files\Common Files\Mercury Interactive\文件夹下,发现没License Manager文件夹,也没有生成LSERVRC文件,那我就手工创建该文件夹,做好该工作之后,然后再C:\Program Files\Mercury Interactive文件夹,执行mgn-mqt82.exe,执行成功,没有报错,既然没有报错,那就继续我把C:\Program Files\Common Files\Mercury Interactive\License Manager\LSERVRC中产生的生成的字符串拷贝出来,然后拷贝到qtp的license向导中,破解成功。
         呵呵,功夫不负有心人,试验成功
        
         破解步骤:
         1.安装qtp
         2.拷贝mgn-mqt82.exe到C:\Program Files\Mercury Interactive(创建)文件夹下
         3.创建C:\Program Files\Common Files\Mercury Interactive\License Manager文件夹
         4.执行mgn-mqt82.exe
         5.打开qtp9.5,然后安装license,copy文件C:\Program Files\Common Files\Mercury Interactive\License Manager\LSERVRC中#之前的字符串
          如:
       3QVWCPPOS5NGGFM6KPX64EQFSH6INFRJIVMC5WZ4XIIFIXX86UCPIP4M686DZKV9NANA9BUP# "QuickTestPro" version "6.0", no expiration date, exclusive
    JZ7F79F6YQQFVUWNG2V7AW22K537DOELQYNX6VSCNCZ9J8M2QW9OXO5DSEQKUZA46X5BO# "FT-Unified" version "1.0", no expiration date, exclusive
        就拷贝#号前的3QVWCPPOS5NGGFM6KPX64EQFSH6INFRJIVMC5WZ4XIIFIXX86UCPIP4M686DZKV9NANA9BUP 然后paste到license向导中的license输入的地方,就可以了
         恭喜成功了
  • 一个工作任务的解决方法

    2008-09-07 23:21:58

     有个网友接到工作任务产生测试数据,具体任务如下:
    “我们老大给了个这个的任务给我:
      质量:重复率<0.1%,相似率<10%
      数据根据该字段的类型和长度生成, 涵盖各种情况,包括边界值,异常值....字符串要包含所有字符集,规定的所有长度,时间跨度取前后3年以上,枚举字段要随机取完所有值....
      特殊要求:
      固定在一个字段里放测试标识,如在作者字段的前两个字符为"测试",便于识别和删除...”
      他的解决问题思路是通过lr把现有数据库中的数据导入到参数文件中,然后发送给服务器(不知道他为什么从数据库中读取数据,然后再发送),导入到file中遇到问题是 lr报错 “check file format”。经过交流之后我们把他的问题简单化,其实就是一个目标产生数据,但是中间遇到的是两个问题,一个是数据来源问题  一个是数据如何发送问题

     1.数据来源,如果是要网页文件信息,从他的方法来看,是利用lr读取数据库,那么我们来看看结合lr如何做呢?首先是利用vc写一个dll,从服务器上读取字段内容,然后在lr中读取该代码,2007年的时候当时帮大连的一个朋友写过一个dll代码,就是读取oracle数据库字段内容的,然后再lr中使用。根据以上思路写了个vc中伪代码(伪代码就是没有经过调试,或者没有实现完全的代码)如下:
       _ConnectionPtr pConnection;
    _RecordsetPtr pRecordSet;
    ICfxDataAdoPtr pCfxDataAdo;

    pRecordSet.CreateInstance(__uuidof(Recordset));
    pConnection.CreateInstance(__uuidof(Connection));

     // Read from database
     pConnection->ConnectionString ="Provider=Microsoft.Jet.OLEDB.4.0;Persist Security Info=False;Data Source=";
     pConnection->Open("","","",-1);
     pRecordSet = pConnection->Execute("SELECT * FROM xxx",NULL,-1);
     //获得pRecordSet字段数据
       
      pRecordSet->Close();
      pConnection->Close();
     
        以上代码可以封装成函数放入dll后,在lr中调用dll,lr中的代码伪代码如下,

       
        rc=lr_load_dll("xxx.dll");
     if( rc != 0 ){
      lr_error_message("lr_load_dll of advapi32.dll failed. Aborted for rc=%d",rc);
      lr_abort();
     }else{
               strcpy(data,dll中调用返回的函数数据);
               web_submit_form 发送出去要发送的数据包

     }

           我们在换一个思路,如果就是为了得到html这样的数据,那么我们是否可以自己写代码得到网站上任何的Html代码作为自己的数据,用vbs写了段代码:
       Set XML = CreateObject("Microsoft.XMLHTTP")
       XML.Open "GET", "http://www.51testing.com", False
       XML.Send
       vResponse = XML.responseText
       MsgBox vResponse
       以上代码调试通过
     
       2.如何发送数据包
         方法可以是利用lr发送,可以是直接发送请求,我们看如何直接发送请求,代码如下:
         Dim xmlhttp
        Set xmlhttp = New MSXML2.ServerXMLHTTP
        xmlhttp.Open "POST", "http://xxxxxxx", False
        xmlhttp.setRequestHeader "Content-Type", "xxxxx"
        xmlhttp.send DataToSend
       
        Set xmlhttp = Nothing

    DataToSend
    =====================================================
    <HTML>

      <HEAD>
        <title>demo</title>
      </HEAD>

      <BODY>
         xxxxxx
      </BODY>
    </HTML>
     
       思路如上,解决问题中具体用到的技术大家可以找相应资料深入研究下。   
     

     

  • WinRunner 曾经的记忆

    2008-09-01 17:47:49

        昨天在做Qtp培训发给学员资料的时候无意中找到以前的资料,记得刚参加工作的时候自动化测试就知道Rational robot,感觉工具特别好,也激起了很大的热情和兴趣,对Robot做了很多研究,当时还写了很多关于robot的文章,也曾经憧憬着做中国第一个自动化测试项目,后来加入51testing由于工作需要接触了wr,qtp,silktest等功能自动化测试工具,随着时间的推移wr robot逐渐淡出大家的视线。其实每一个工具都有自己的特点在里面,好比一个人一样有自己的风格,在不同的项目用不同的工具,只有结合起来才能发挥最大的威力,下面是一些代码例子,算是做个纪念:

    1.WinRunner如何加载Dll,例子代码如下:

    rc1 = reload ( "win32api", 1, 1 );
    if ( rc1 != 0 )
     { tl_step ( "Error Message", FAIL, "[reload(\"win32api\")] - FAILED!"); }
    else
     { tl_step ( "Status Message", PASS, "[reload(\"win32api\")] - OK"); }

    public function phone_num_gen (out phone)
    {
     auto x, areacode, prefix, sufix;

     x = int ( rand(GetTickCount())*1000000000000 );
     areacode = substr(x, 1 ,3);
     prefix = substr(x, 4, 3);
     sufix = substr(x, 7, 4);
     phone = "(" & areacode & ") " & prefix & "-" & sufix;
     return ( E_OK );
    }

    for (i = 1; i < 10; i++)
    {
     phone_num_gen(num);
     printf(num);
    }

    rc1 = unload ( "win32api" );
    if ( rc1 != 0 )
     { tl_step ( "Error Message", FAIL, "[unload(\"win32api\")] - FAILED!"); }
    else
     { tl_step ( "Status Message", PASS, "[unload(\"win32api\")] - OK"); }

    2.在winrunner中如何统计代码行,提供一种解决思路

    public function cloc ( in fileX, inout lines_code, inout lines_blank_or_comment, inout total_LOC  )
    {
     auto line;

     # Initialize variables ...
     lines_code = 0;

     file_open ( fileX, FO_MODE_READ );

     while ( file_getline( fileX, line ) == 0 )
     {
      # Blank or Coment lines ...
      if ( match( line, "[^#]" ) == 1 )
      {
       lines_blank_or_comment++;
      }
      else
      {
       lines_code++;
      }
     }

     total_LOC = lines_code + lines_blank_or_comment;

     file_close ( fileX );
    }


    rc1 = cloc( "C:\\Junk1\\scrīpt", LOC, BlankOrComment, TLOC );

    printf ( "Total Number of lines of code: %s\r\n", LOC );
    printf ( "Total Comment or blank lines in code: %s\r\n", BlankOrComment );
    printf ( "Total lines in file: %s\r\n", TLOC );

    3.winrunner错误处理函数

     

    function CreateErrorMessageArray ( inout ErrorMsgArray[] )
    {
     # Location of WinRunner scrīpt which defines the error message codes
     auto ErrorMsgFile = getenv ( "M_ROOT" )  & "\\lib\\wr_gen\\scrīpt";
     auto rc = E_OK;  # Return code for this function
     auto character;  # Store a character
     auto line;   # Store a line from file
     auto tmpline;  # Store a line with no tab or spaces
     auto counter;  # Used to strip tab and spaces out of the line
     static tmpArray[]; # Store split (  )  results

     # Delete everything in the ErrorMsgArray
     for  ( counter in ErrorMsgArray )
      delete ErrorMsgArray[counter];

     rc = file_open ( ErrorMsgFile,FO_MODE_READ );
     if  ( rc != E_OK )
      return  ( rc );

     #Parse the file looking for "public const E_"
     while ( file_getline ( ErrorMsgFile,line ) == 0 )
     {
      if  ( index(line, "public const E_") > 0 )
      {
       # Get rid of spaces and tab characters
       tmpline = "";
       for  ( counter = 1; counter <= length(line); counter++ )
       {
        character = substr ( line, counter, 1 );
        if  ( (character != " ") && (character != "\t") )
         tmpline = tmpline & character;
       }
       split  ( tmpline, tmpArray, "=" );

       # The substr ( tmpArray[2],1, length ( tmpArray[2] ) -1 ) gets rid of the trailing semicolon  ( ; )
       # The substr ( tmpArray[1], 12 ) is the error code minus the public const
       if  ( ErrorMsgArray[substr(tmpArray[2], 1, length(tmpArray[2] - 1 )  ) ] )
       {
         ErrorMsgArray[substr(tmpArray[2], 1, length(tmpArray[2] - 1) ) ] =
         ErrorMsgArray[substr(tmpArray[2], 1, length(tmpArray[2] - 1) ) ]&", "&
         substr(tmpArray[1], 12 );
       }
       else
       {
        ErrorMsgArray[substr(tmpArray[2], 1, length(tmpArray[2]) - 1) ] =
        substr(tmpArray[1], 12);
       }
      }
     }
     file_close ( ErrorMsgFile );
     return  ( E_OK );
    }

    function GetErrorMessage ( inout ErrorMsgArray[], in ErrorCode )
    {
     return ( ErrorMsgArray[ErrorCode] );
    }

     

  • AOM对象创建不成功

    2008-08-31 00:32:01

       

          今天用VB写创建AOM对象,代码执行如下的时候就报错:

          Set Qtp_App=CreateObject("QuickTest.Application")'报错 ActiveX控件不能创建

          单独打开qtp没有问题,就是以上代码会出现问题,最后找了下论坛中的是否有人遇到同样的问题,也没有最后给解决办法,最后自动动手丰衣足食,分析结果是直接注册QTObjectModel.dll也不能解决以上问题,分析应该是有相关dll对象耦合在一起了,所以重新注册相应的dll就可以解决了,大胆推断后,然后就是小心求证,最后问题解决

          解决方法尝试如下:重新执行C:\Program Files\Mercury Interactive\QuickTest Professional\bin\QuickTestProfessional.bat,也就是重新注册qtp dll,执行完毕后执行代码,没有报错

  • 自动化测试框架中如何远程启动进程的技术

    2008-08-22 22:46:07

        

           在自动化测试框架中经常设计分布式执行用例,调用不同计算机机上的qtp来执行,如何远程调用qtp有以下几个方法:

           1.利用qc启动相应机器上qtp执行自动化测试用例

              打开QC 打开test lab--> in the execution flow-->设置

           2.利用wmi对象远程启动远程进程

             脚本代码例子:

             strComputer = "."
             strCommand = "QPro.exe"


             Const INTERVAL = "n"
             Const MINUTES = 1

             Set ōbjWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
             Set ōbjScheduledJob = objWMIService.Get("Win32_ScheduledJob")
             Set ōbjSWbemDateTime = CreateObject("Wbemscrīpting.SWbemDateTime")

             objSWbemDateTime.SetVarDate(DateAdd(INTERVAL, MINUTES, Now()))
             errReturn = objScheduledJob.Create(strCommand, objSWbemDateTime.Value, False, 0, 0, True, intJobID)


             If errReturn = 0 Then
                Wscrīpt.Echo "notepad.exe was started with a process ID: " & intJobID
             Else
                Wscrīpt.Echo "notepad.exe could not be started due to error: "&errReturn
             End If
      

           3.利用lr controller远程启动qtp自动化测试脚本

            打开controller,然后加载qtp脚本,设置load generator

     

          

  • 老婆测试工具培训记 - QTP 函数实现 - 1

    2008-08-20 13:13:18

    Write a program to delete Line in file?

    思路:封装scrīpting.filesystemobject对象,利用readline方法

    Function DeleteLine(strFile, strKey, LineNumber, CheckCase)

    'Use strFile = "c:\file.txt"  (Full path to text file)
    'Use strKey = "John Doe"      (Lines containing this text string to be deleted)
    'Use strKey = ""              (To not use keyword search)
    'Use LineNumber = "1"         (Enter specific line number to delete)
    'Use LineNumber = "0"         (To ignore line numbers)
    'Use CheckCase = "1"          (For case sensitive search )
    'Use CheckCase = "0"          (To ignore upper/lower case characters)

       Const ForReading=1:Const ForWriting=2
       Dim objFSO,objFile,Count,strLine,strLineCase,strNewFile
       Set ōbjFSO=CreateObject("scrīpting.FileSystemObject")
       Set ōbjFile=objFSO.OpenTextFile(strFile,ForReading)
       Do Until objFile.AtEndOfStream
          strLine=objFile.Readline
          If CheckCase=0 then strLineCase=ucase(strLine):strKey=ucase(strKey)
          If LineNumber=objFile.Line-1 or LineNumber=0 then
             If instr(strLine,strKey) or instr(strLineCase,strkey) or strKey="" then
                strNewFile=strNewFile
             Else
                strNewFile=strNewFile&strLine&vbcrlf
             End If
          Else
             strNewFile=strNewFile&strLine&vbcrlf
          End If
       Loop
       objFile.Close
       Set ōbjFSO=CreateObject("scrīpting.FileSystemObject")
       Set ōbjFile=objFSO.OpenTextFile(strFile,ForWriting)
       objFile.Write strNewFile
       objFile.Close

    End Function

     

     

  • vbs创建对象的知识点

    2008-08-20 11:18:58

      一般vb中创建对象有两种形式:

      (1)

      dim   a   as   object_x  
      这样只是定义对象A的一个标识,并没有开辟内存空间来创建这个对象.  
      dim   a   as   new   object_x  
     

      这样定义就开辟了内存空间,即在定义对象时就构建了这个对象.其它等于:  
     

      (2)

      dim   a   as   object_x  
      set   a= new   object_x  

      或者  
      dim   a   as   object_x  
      set   a= CreateObject("objectname”)

     
      CreateObject支持更多的对象定义.比如用VB6写的DLL不是标准格式的DLL,一般用CreateObject来完成对象的创建,而且在VBscrīpt(qtp)等VB的子集中也只支持用CreateObject.

491/3123>
Open Toolbar