发布新日志

  • QTP自动化测试工程师需要掌握的DOM(转)

    2011-05-13 17:06:59

    在使用QTP测试WEB页面时,经常需要利用测试对象中的Object属性来访问和操作DOM,因此,QTP自动化测试工程师非常有必要掌握一些常用的DOM知识。 下面就列举了一些常用的DOM属性、方法和集合:

      常用DOM 属性

      ●  className.同一样式规则的元素用相同的类名。可以通过className快速过滤出一组类似的元素。

      ●  document.用于指向包含当前元素的文档对象。

      ●  id.当前元素的标识。如果文档中包含多个相同id的元素,则返回一个数组。

      ●  innerHTML.用于指向当前元素的开始标记和结束标记之间的所有文本和HTML标签。

      ●  innerText.用于指向当前元素的开始标记和结束标记之间的所有文本和HTML标签。

      ●  offsetHeight, offsetWidth.元素的高度和宽度。

      ●  offsetLeft, offsetTop.当前元素相同对于父亲元素的左边位置和顶部位置。

      ●  outerHTML.当前元素的开始标记和结束标记之间的所有文本和HTML标签。

      ●  outerText.当前元素的开始标记和结束标记之间的所有文本,但不包括HTML标签。

      ●  parentElement.当前元素的父亲元素。

      ●  sourceIndex.元素在document.all集合中的索引(index)。

      ●  style.元素的样式表单属性。

      ●  tagName.当前元素的标签名。

      ●  title.在IE中,代表元素的tool tip文本。

      常用DOM 方法

      ●  click().模拟用户对当前元素的鼠标点击。

      ●  contains(element).用于判断当前元素是否包含指定的元素。

      ●  getAttribute(attributeName, caseSensitive).返回当前元素所包含的某个属性,参数attributeName为属性名、caseSensitive表示是否大小写敏感。

      ●  setAttribute(attributeName, value, caseSenstive). 设置当前元素的属性。

      常用DOM 集合

      ●  All[].当前元素中包含的所有HTML元素的数组。

      ●  children[].当前元素包含的孩子元素。

  • QTP & DOM (转)

    2011-05-13 17:04:48

    要想用QTP做好WEB自动化测试,需要熟悉DOM 。

    通过 DOM ( Document Object Model ,文档对象模型),可以操纵页面的每个 HTML 元素。

     

    常用 DOM 属性和方法
    Every HTML element in a Web page is a scriptable object in the object model, with its own set of properties, methods, and events. To enable access to these objects, Internet Explorer creates a top-level document object for each HTML document it displays. When you use the .Object property on a Web page object in your test or component, you actually get a reference to this DOM object. This document object represents the entire page. From this document object, you can access the rest of the object hierarchy by using properties and collections.

    Following are the most useful document properties and methods available through the Web .Object property: (通过.Object 可以访问以下属性、集合和方法)

    Properties 属性
    ·   activeElement Property - Retrieves the object that has the focus when the parent document has focus.

    ·   cookie Property - Sets or retrieves the string value of a cookie.

    ·   documentElement Property - Retrieves a reference to the root node of the document.

    ·   readyState Property - Retrieves a value that indicates the current state of the object.

    ·   URL Property - Sets or retrieves the URL for the current document.

    ·   URLUnencoded Property - Retrieves the URL for the document, stripped of any character encoding.

    Collections 集合
    ·   all - Returns a reference to the collection of elements contained by the object.

    ·   frames - Retrieves a collection of all window objects defined by the given document or defined by the document associated with the given window.

    ·   images - Retrieves a collection, in source order, of img objects in the document.

    ·   links - Retrieves a collection of all objects that specify the HREF property and all area objects in the document.

    Methods 方法
    ·   getElementById Method - Returns a reference to the first object with the specified value of the ID attribute.

    ·   getElementsByName Method - Retrieves a collection of objects based on the value of the NAME attribute.

    ·   getElementsByTagName Method - Retrieves a collection of objects based on the specified element name.

    Note that some of these properties are also provided by QuickTest Test Objects. For example, it is possible to access the cookies set by a Web page both through the cookie property in the DOM, and through the GetCookies method provided by the Browser Test Object.

     

    activeElement
    Retrieves the object that has the focus when the parent document has focus.
    You can get the source index of the active element (object that has focus) on the page by doing the following:

    CurrentSourceInd = Browser("Browser"). Page("Page").Object.activeElement.sourceIndex

    Now you can query the source index of any object on the page by doing the following:

    SrcIdx = Browser("Browser").Page("Page").WebEdit("q").GetROProperty("source_index")

    You can then compare the two values to see if the WebEdit is the active element on the page that has focus. If the source index of the WebEdit is the same as the source index of the activeElement , then the WebEdit is the object that has focus.

     

    activeElement 代表当前获得焦点的对象

     

    例子:

    ' 当前获得焦点的页面元素的 sourceIndex

    CurrentSourceInd = Browser("Web Tours").Page("Web Tours").Object.activeElement.sourceIndex

    Print CurrentSourceInd

     

    ' 获取 username 输入框的 sourceIndex 属性

    SrcIdx = Browser("Web Tours").Page("Web Tours").Frame("navbar").WebEdit("username").GetROProperty("source_index")

    Print SrcIdx

     

    If CurrentSourceInd<>SrcIdx Then

           Reporter.ReportEvent micFail," 默认焦点错误 "," 默认焦点未置于 UserName 输入框上! "

    End If

     

    ' 把焦点置于 username 输入框上

    Browser("Web Tours").Page("Web Tours").Frame("navbar").WebEdit("username").Object.focus

    SrcIdx = Browser("Web Tours").Page("Web Tours").Frame("navbar").WebEdit("username").GetROProperty("source_index")

    Print SrcIdx

     

    cookie
    A cookie is a small piece of information stored by the browser that applies to a Web page. Each cookie can store up to 20 name=value; pairs called crumbs, and the cookie is always returned as a string of all the cookies that apply to the page. This means that you must parse the string returned to find the values of individual cookies.

    The following is an example which retrieves the value of the cookie for a specified Web page.

    strCookie = Browser("Browser").Page("Page").Object.cookie

    Note: You can also use the Browser Test Object's GetCookies method to retrieve cookies for a specific URL. For example:

    msgbox Browser("Yahoo").GetCookies("http://finance.yahoo.com")

     

    使用 Object.cookie 来获取指定页面上的 Cookie

    例子:

    strCookie = Browser("Web Tours").Page("Web Tours").Object.cookie

    Print strCookie

     

    ' 也可这样获取 Cookie

    Print Browser("Web Tours").GetCookies("http://127.0.0.1:1080/WebTours/")

     

     

    documentElement
    The documentElement property is a reference to the root node of the document. It is read-only, and has no default value. The root node of a typical HTML document is the html object.

    documentElement 属性指向DOM 的根节点,通常就是HTML 节点对象

    This example uses the documentElement property to retrieve the innerHTML property of the entire document.

    msgbox Browser("Browser").Page("Page").Object.documentElement.innerHTML

     

    可以通过 Object.documentElement 访问 innerHTML 属性取得整个文档的 HTML 文本

    例子:

    Print Browser("Web Tours").Page("Web Tours").Object.documentElement.innerHTML

     

    取到页面的 HTML 文本如下:

    <HEAD><TITLE>Web Tours</TITLE></HEAD><FRAMESET border=1 frameSpacing=4 borderColor=#e0e7f1 rows=65,* frameBorder=0><FRAME. name=header marginWidth=2 marginHeight=2 src="header.html" noResize scrolling=no><FRAME. name=body marginWidth=2 marginHeight=2 src="welcome.pl?signOff=true" noResize></FRAMESET>

     

     

    readyState
    The readyState property is a string value a string value that indicates the current state of the object.

    用readyState 属性来标识指定对象当前的状态,这个属性对于所有DOM 元素都适用。

    Note that the readyState property is applicable to any DOM element. Both examples below are equally valid, and both will display the readyState of the object to which they belong

    msgbox Browser("Browser").Page("Page").Object.readyState

    and

    msgbox Browser("Browser").Page("Page").Link("Link").Object.readyState

    An object's state is initially set to uninitialized, and then to loading. When data loading is complete, the state of the link object passes through the loaded and interactive states to reach the complete state.

     

    对象状态的一般变化过程:

    uninitialized -> loading -> loaded -> interactive -> complete

     

     

    URL
    The URL property sets or retrieves the URL for the current document. This property is valid for Page and Frame. objects.

    The following example displays the URL for the Web page that is currently open in the browser:

    msgbox Browser("Browser").Page("Page").Object.URL

     

    URL 属性对于 Page 和 Frame. 对象都适用

     

    例子:

    Print  Browser("Web Tours").Page("Web Tours").Object.URL

    Print  Browser("Web Tours").Page("Web Tours").Frame("body").Object.URL

    Print  Browser("Web Tours").Page("Web Tours").Frame("header").Object.URL

    Print  Browser("Web Tours").Page("Web Tours").Frame("info").Object.URL

    Print  Browser("Web Tours").Page("Web Tours").Frame("navbar").Object.URL

     

    输出页面对象以及各个 Frame. 对象的 URL 属性:

    http://127.0.0.1:1080/WebTours/

    http://127.0.0.1:1080/WebTours/welcome.pl?signOff=true

    http://127.0.0.1:1080/WebTours/header.html

    http://127.0.0.1:1080/WebTours/home.html

    http://127.0.0.1:1080/WebTours/nav.pl?in=home

     

     

    URLUnencoded
    The only difference between the URL property and the URLUnencoded property is that the URLUnencoded property strips the URL of any character codings (such as %20 for spaces, and so forth.)

    For more information about URL character encoding issues, see RFC-1738 on Uniform. Resource Locators (URL) .

     

    URL 与 URLUnencoded 的区别在于 URLUnencoded 属性去掉了 URL 中的格式编码,例如代表空格的 %20

     

    all, frames, images, 和 links 集合
    Return a reference to the collection of elements contained by the object.

    The all collection contains all the elements in the specified object. 指定对象中的所有元素。

    The frames property contains objects of type window (frame).

    Frame. 类型的对象中的所有元素。

    The images property contains objects of type of img (image).

    Image 类型的对象中的所有元素。

    The links collections contains objects of types HREF and area.

    HREF 、area 类型的对象中的所有元素。

    length property - Sets or retrieves the number of objects in a collection.
    item method - Retrieves an object from the all collection or various other collections.
    namedItem method - Retrieves an object or a collection from the specified collection.
    There are additional methods available for accessing some of the collections. For example, the images collection provides the tags method, which can be used to retrieve a collection of objects with a specified tag name. For more information, see http://msdn.microsoft.com/en-us/library/ms535862(VS.85).aspx .

    The following example loops through all the INPUT tags, and displays a message indicating the number of tags checked:

    Set inputs = Browser("Browser").Page("Page").Object.all.tags("INPUT")
    'Loop over all inputs in this collection and get the 'checked' value:
           For Each inputBtn In inputs
                  If inputBtn.checked Then
                         checkedCount = checkedCount + 1
                  End If
           Next

    MsgBox checkedCount & " checkboxes are checked."

    The following example displays a message indicating the number of frames in the specified Web page:

    msgbox Browser("Yahoo").Page("Yahoo!").Object.frames.length

     

     

    从 all 、 frames 、 images 、 links 等集合中可以方便地获取到同一类型的所有对象。

     

    例子:

     

    ' 取得 Frame. 的个数

    Print  Browser("Web Tours").Page("Web Tours").Object.frames.length

     

    Browser("Web Tours").Page("Web Tours").Frame("navbar").WebEdit("username").Set "jojo"

    Browser("Web Tours").Page("Web Tours").Frame("navbar").WebEdit("password").SetSecure "4b4735162198024e11994f954660"

    Browser("Web Tours").Page("Web Tours").Frame("navbar").Image("Login").Click 55,14

    Browser("Web Tours").Page("Web Tours").Frame("navbar").Image("Itinerary Button").Click

     

    Browser("Web Tours").Page("Web Tours").Frame("info").WebCheckBox("1").Set "ON"

    Browser("Web Tours").Page("Web Tours").Frame("info").WebCheckBox("2").Set "ON"

     

    ' 取得标签为 INPUT 的所有对象

    Set inputs = Browser("Web Tours").Page("Web Tours").Frame("info").Object.all.tags("INPUT")

    For Each inputBtn In inputs

           If inputBtn.checked Then

                  checkedCount = checkedCount + 1

        End If

    Next

    Print checkedCount & " checkboxes are checked."

     

     

    getElementById
    The getElementById method returns a reference to the first object with the specified value of the ID attribute.
    The following example sets the value of obj to the first element in the page that has an ID of "mark":

    Set bj = Browser("Browser").Page("Yahoo!").Object.getElementByID("mark")

     

    通过对象的 ID 来查找对象

     

    例子:

    Set bj = Browser("Google").Page("Google").Object.getElementById("tb")

    msgbox obj.innerText

     

    getElementsByName 和 getElementsByTagName
    The getElementsByName and getElementsByTagName methods can be used just like getElementById except that they return a collection of objects (as opposed to getElementById , which returns only the first matching object it finds.)

    For example, the following script. line will display a message indicating the number of images on the page - image objects have an "IMG" tag.

    msgbox Browser("Yahoo").Page("Yahoo!").Object.getElementsByTagName "IMG").length

    getElementById 只查找并返回第一个匹配的对象,而 getElementsByName 和 getElementsByTagName 则返回一个包含匹配对象的集合。

     

    例:

    set imags = Browser("Google").Page("Google").Object.getElementsByTagName("IMG")

    For i=0 to imags.length -1

           Print imags(i).src

    Next

     

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/testing_is_believing/archive/2010/01/08/5161739.aspx

  • QTP提供的两种对象接口(转)

    2011-05-13 16:07:32

     QTP为用户提供了两种操作对象的接口,一种就是对象的封装接口,另一种是对象的自身接口。
    对象的自身接口是对象控件本身的接口,只要做过软件开发,使用过控件的人应该很清楚。
    对象的封装接口是QTP为对象封装的另一层接口,它是QTP通过调用对象的自身接口来实现的。

    两种接口的脚本书写格式的差别在于:
      自身接口需要在对象名后面加object再加属性名或方法名,
      封装接口就不用在对象名后面加object。

    具体格式如下:
      对实际对象的操作:
          对象.object.自身属性
          对象.object.自身方法()
          对象.GetROProperty("封装属性")
          对象.封装方法()

      对仓库对象的操作:
          对象.GetTOProperty("封装属性")
          对象.GetTOProperties()      ’获取所有封装属性的值
          对象.SetTOProperty("封装属性", "封装属性值")

    比如操作JavaEdit对象,通过QTP封装的封装接口,脚本如下:
      设置JavaEdit的内容:
         JavaDialog("Add NE").JavaEdit("NE Name").Set "NE1"
      读取JavaEdit的内容:
         msgbox JavaDialog("Add NE").JavaEdit("NE Name").GetROProperty("value")

    如果通过JavaEdit的自身接口,脚本如下:
      设置JavaEdit的内容:
         JavaDialog("Add NE").JavaEdit("NE Name").object.setText("NE1")
      读取JavaEdit的内容:
         Msgbox JavaDialog("Add NE").JavaEdit("NE Name").object.getText()

    QTP执行JavaEdit().Set语句时,是通过执行JavaEdit().object.setText()来实现的。
    QTP执行JavaEdit().GetROProperty("value"),是通过执行JavaEdit().object.getText()来实现的。
    JavaEdit对象的封装接口Set()和GetROProperty("value"),是QTP封装JavaEdit对象的自身接口setText()和getText()而得来的。

    对象的封装接口是QTP使用的缺省接口,我们录制出来的脚本都是使用封装接口,大家用的也都是封装接口。
    但是封装接口不如自身接口丰富,因为QTP只是封装了部分常用的自身接口嘛。
    所以我们在需要时,可以绕过封装接口,直接调用对象的自身接口。
    不过有些自身接口不够稳定,在实践中偶尔会出现问题,但是概率很少。
    封装接口有相应功能的话,就尽量用封装接口吧!

    理解了封装接口和自身接口的原理,我们就可以更加灵活的操作对象了。

    但是我们怎么知道对象都有哪些封装接口和自身接口呢?
    其实很简单,用对象查看器(Object Spy)查看对象,在查看窗口里有列出这些接口,包括属性和方法。
    窗口中间有选择栏让你选择Native Properties和Identification Properties或者Native Operations 和Test Object Operations (QTP10.0是这样)
    当选择Native Properties和Native Operations,它显示的就是对象的自身接口(自身的属性和方法)
    当选择Identification Properties和Test Object Operations时,它显示的就是对象的封装接口(封装的属性和方法)

  • 编写图片空间QTP脚本时的一点经验(转)

    2011-05-13 15:09:54

    我录制QTP脚本的思路是让能跑起来的都跑起来,不能跑起来的暂时不管,同时先采取固化脚本的思路写脚本(详细),完成后再加入参数化,让脚本灵活起来!呵呵!

      以下是我编写图片空间时的一点经验!

      经验1:用FireEvent方法处理TOP菜单中弹出的子菜单

      Browser(”淘宝网-店铺管理平台“).Page(”淘宝网-店铺管理平台“).Link(”素材管理(1)”).Click

      Browser(”淘宝网-店铺管理平台“).Page(”淘宝网-店铺管理平台“).Link(”图片空间“).Click

      我在编辑用鼠标点击TOP菜单时,发现脚本在运行时,不稳定,有时能捕捉到子菜单,有时又不能捕捉到子菜单,后加上FireEvent方法:

      browser(”淘宝网-店铺管理平台“).Page(”淘宝网-店铺管理平台“).Link(”素材管理(1)”).FireEvent “onmouseup”

      Browser(”淘宝网-店铺管理平台“).Page(”淘宝网-店铺管理平台“).Link(”图片空间“).Click

      这时每次运行脚本时,都能捕捉到子菜单了。

      经验2:通过对象唯一性确认页面访问对象

      需要校验图片分类下图片的数量,思路是将页面显示的数目与数据库中查询的数据进行对比,但此时不能直接读取有图片数量的对象,因为此对象不具有“唯一性”,它属于动态生成的对象。改变校验思路是先取得页面中具有“唯一性”对象图片分类DESC对象(系统中图片分类是具有唯一性),然后通过DOM对象取得图片数量的INFO对象。

      set my_obj=browser(”图片空间“).Page(”图片空间“).Link(”宝贝图片“).Object

      set my_b_info=my_obj.parentnode.nextSibling

      然后取得有图片分类下图片数据:

      tx=my_b_info.outertext

      ‘msgbox “a” + tx + “b”  用来校验是否有空格

      text=left(tx,len(tx)-4)

      ‘text=text+0

      ‘msgbox IsNumeric(text)

    经验3:通过CURRENTSYTLE判别LINK对象可用性

      提供两种思路:

      第一种方式:

    V=strcomp(browser(”图片空间“).Page(”图片空间“).Link(”name:=下移“,”index:=5″).GetROProperty(”class”), “move-down J_TagMoveDown no-move-down”,1)

    If  v=0 Then

       reporter.ReportEvent micPass,”pass”,”提示成功“

    else

             reporter.ReportEvent micFail,”fail”,”提示失败“

    End If

      第二种方式:

    set my_obj =browser(”图片空间“).Page(”图片空间“).Link(”name:=下移“,”index:=5″).object

    x= my_obj.currentstyle.getattribute(”cursor”)

    y=”not-allowed”

    v=strcomp(x,y,1)

    If  v=0 Then

       reporter.ReportEvent micPass,”pass”,”提示成功“

    else

             reporter.ReportEvent micFail,”fail”,”提示失败“

    End If

      经验4:通过DESCRIPTION访问对象库中同一对象运行时动态对象中静态提示文本

      在页面中经常出现的DIALOG对象,在同一页面中可能会出现很多不同的DIALOG,但是读取对象时只有一个对象,但是其中静态文本,却是动态生成的,不同的操作对应不同的提示,此时通过:Static(”text:=图片标题不能超过50字符“).Exist语句判断系统是否成功操作!

      Set MyDescription = Description.Create()

      MyDescription(”text”).Value = “此分类为系统分类,不可删除。"

      在这里的VALUE我们可以根据不同的对话框设置不同的静态文本:

    If browser(”图片空间“).Dialog(”Windows Internet Explorer”).Static(MyDescription).Exist then

        reporter.ReportEvent micPass,”pass”,”删除系统分类时提示成功“

             browser(”图片空间“).Dialog(”Windows Internet Explorer”).WinButton(”确定“).Click

    else

             reporter.ReportEvent micFail,”fail”,”删除系统分类时提示失败“

    End If

    Set MyDescription = Nothing

      也可以采取这种方式:

    If browser(”图片空间“).Dialog(”Windows Internet Explorer”).Static(”text:=图片标题不能超过50字符“).Exist Then

             reporter.ReportEvent micPass,”pass”,”图片标题不能超过50字符提示成功“

             browser(”图片空间“).Dialog(”Windows Internet Explorer”).WinButton(”确定“).Click

    else

             reporter.ReportEvent micFail,”fail”,”图片标题不能超过50字符提示失败“

    End If

  • QTP调用外部.vbs函数的方法比较(转)

    2011-05-09 17:30:11

    方式1:Executefile

      方式2:加到QTP的Resorece

      方式3:ExecuteGlobal方法

      在比较之前先简明叙述一下使用方法,以给初学者由浅入深的理解

      比如我们有一个函数Wally.vbs放在了C:盘下,其中有如下函数(获取本机的IP地址):

    FunctionGetIPAddr()
    SetobjWMI=GetObject("winmgmts://./root/cimv2")
    SetcolIP=objWMI.ExecQuery("Select*fromWin32_NetworkAdapterConfigurationwhereIPEnabled=TRUE")
    ForEachIPIncolIP
    temp=IP.IPAddress(0)
    ExitFor
    Next
    GetIPAddr=temp
    EndFunction


      方式1的使用方法:

      直接在QTP中打:

      Executefile"c:\wally.vbs"

      随后就可以引用wally.vbs中的任意函数了,如msgboxGetIPAddr()

      方式2的使用方法:

      点击QTP菜单的File->Settings->Resources,之后添加wally.vbs到QTP的resource中

      随后就可以引用wally.vbs中的任意函数了,如msgboxGetIPAddr()

      方式3的使用方式:

      ExecuteGlobal是VBS的函数而非QTP特有的函数,ExecuteGlobal的功能可以引入其它vbs文件的函数,就和C++的include,Java的import一样。使用范例:

    dimfso:setfso=createobject("scripting.filesystemobject")
    executeglobalfso.opentextfile("c:\wally.vbs",1).readall
    setfso=nothing

      大家可以看到其实它是把wally.vbs全部读入内存中

      随后就可以引用wally.vbs中的任意函数了,如msgboxGetIPAddr()

    下面是一些我使用中的心得:

      方式1:Executefile的好处:

      QTP可以使用这个函数方便了自己写语句来引入函数,灵活性非常高

      方式1:Executefile的缺点和解决方案:

      1.会使得QTP的语句执行的黄色指针工作异常,狂跳

      2.Debug很头疼。我以前的上周有一段经历,一个很小的Bug,调试的时候Stepinto不进正确的函数体,竟然跳到了一行空行。后来这个小Bug竟然足足花了我3整天的时间。这个应该是QTP的Bug,希望它后续的版本可以改进

      3.会莫名其妙的执行一些本不应该有的操作,大大降低QTP执行时间效率,之间屏幕在闪,但是不知道在执行些什么。我曾经遇到过这样的情况:任其自然执行,屏幕狂闪,执行了半小时;我单步执行,只花了5分钟执行完毕。可见这会使得原本就受质疑的QTP的Performance更受谴责

      解决方案:

      以上三点我找不出解决方案,属于Hp的严重Bug还是需要HP来完善

      方式2:加到QTP的Resorece的好处:

      毕竟是QTP自带的引用外部VBS函数的,非常稳定

      方式2:加到QTP的Resorece的缺点和解决方案:

      灵活程度大打折扣,经常的情况是使用同一个测试框架对于不同的项目需要引入不同的VBS文件,非常不灵活

      解决方案:

      不过这也是有方法可以解决的:在外部调用AOM的函数中添加:

    Setobj=CreateObject("QuickTest.Application")
    SetqtLibraries=obj.Test.Settings.Resources.Libraries'Getthelibrariescollectionobject
    IfqtLibraries.Find("C:\wally.vbs")=-1Then
    qtLibraries.Add"C:\wally.vbs",1
    EndIf


      这样子就可以通过外部文件调用QTP对象模型来加载指定的VBS,也可以非常灵活。

      方式3:ExecuteGlobal方法的优势:

      1.自己写代码,非常灵活

      2.外部函数由于从内存中读取,避免了I/O,执行速度加快,而且通过这个方法调用其它文件函数非常稳定

      方式3:ExecuteGlobal方法的缺点:

      1.一下子把可能需要用到的VBS文件全部读入内存,势必会增加内存开销

      2.Debug时候Stepinto不到指定的函数,调试不方便

      解决方案:

      对于1的解决方案的答案是没有解决方案,因为采取了ExecuteGlobal方法后内存开销增大是不可避免的。但是这点内存对于运行QTP来说并不是个不可承受的内存,微不足道

      对于2的解决方案其实可以在需要调试的时候手工加入到QTP专家视图窗口,调试完毕后再采用ExecuteFile调用

      事实上如果要我排个序的话我的优先顺序是:

      方式2:加到QTP的Resorece>>方式3:ExecuteGlobal>>方法方式1:Executefile

  • QTP全局和局部的错误处理模式(转)

    2011-03-25 10:35:00

    局和局部的错误处理模式

    上一篇 / 下一篇  2011-03-17 13:55:55 / 个人分类:QuickTestProfessional

    以下内容转载自http://makar.javaeye.com/blog/280272

    QTP提供全局错误处理模式,有Popup  message box,Process next action iteration,Stop run,Process next step这四种。

    QTP也提On Error Resumt Next/On Error goto 0的局部错误处理模式。可以在局部范围内实现Process next step的效果,忽略错误继续执行后续步骤。这个局部错误处理模式,象局部变量优先于全局变量并且只在本函数内有效一样,优先级高于全局错误处理模式,同时只在本函数局部范围(Action本身也可以看成是个函数)内生效。它不会影响外层函数的错误处理模式,但会改变局部范围内调用的子孙函数,将子孙函数的错误处理模式改为Stop Run!

    四种全局错误处理模式的区别在于: 

    1、Process next step 
      这种模式忽略错误继续往下执行,可以通过Err.Number来判断是否发生了错误。
      因为Case函数的每个步骤都是密切相关的,不可能忽略错误继续往下执行下一步骤
      也不可能在每个步骤每个语句后面都加错误检查,这样错误处理代码太多了
      在很多个步骤后再检查也是不严谨的,会错上加错,并因此失去第一个错误的信息
      所以,这种模式不可取
      
    2、Stop run 
      这种模式发生错误后,就抛出异常(可用Err对象得到异常里的错误信息),中止本函数,并一层一层的返回到上一层函数,最后到达Action函数后(Action本身也可以看成是个函数),就停止整个Test的执行。
      在一层一层的返回上层函数的过程中,如果某个中间函数有On Error Resumt Next/On Error goto 0,就会把错误拦截下来,这个中间函数会继续往下执行,不会中止函数并返回上一层函数。
      
    3、Popup  message box 
      这种模式在发生错误时,弹出对话框让用户选择Stop、Retry、Skip、Debug。
      主控Test要全自动执行,不能要求人工干预,所以这种模式不可取
      
    4、Process next action iteration 
      这种模式跟Stop run类似,但是它只是退出本次Action循环,还会继续下一个Action循环。
      主控Test没有继续下一个Action循环的需求,所以这种模式不可取。

    经过上述分析,我们可以得到结果,我们的主控Test,全局错误处理模式使用Stop run模式,同时在主控函数里使用On Error Resumt Next/On Error goto 0的局部错误处理模式来调用Case函数。这样使得Case函数和其子函数里发生错误时,会停止执行,并层层返回到主控函数这里,并由主控函数来拦截错误,记录错误。然后主控函数就可以正常的继续执行下一个Case函数了,不用担心会导致整个Test停止执行。

    主控函数调用Case函数的详细过程如下:

    Err.Clear
    On Error Resume Next
    call CaseFunctionName
    If Err.Number <> 0 Then
      WriteLog Err.Number  '错误码
      WriteLog Err.Description  '错误描述
      WriteLog Err.Source  '错误来源对象,不过好像没啥用
    End
    Err.Clear
    On Error goto 0

  • QTP自动化感悟

    2010-07-03 10:07:04

       最近换了一家公司,开始专职做QTP自动化工作,公司做的事医疗软件行业的项目,用的是PowerBuilder开发的CS架构程序,在选择测试工具方面,当时考虑使用QTP或者Robot,后来考虑到易用性及如何更方便的在技术质量管理部进行推广等因素的考虑,决定使用QTP,总所周知,在QTP9.5之前是没有PB插件的,最后使用QTP10进行测试脚本的编写。
       刚开始学习QTP的人,都习惯于如果解决技术上面的问题,想想自己刚开始学习的时候也是如此,总能为学会读取Excel、连接数据库而感到高兴,认为自己只要学会解决技术方面的问题就算是学好QTP。慢慢地,QTP做久了之后,想法开始改变了,想的多的问题变成脚本的粒度、脚本的复用性、脚本的结构这些问题了。技术上问题也许自己并不能解决,呵呵,但是总有人能解决的,google、help这些里面都是学习的地方。也学每个学习QTP得人都会经历这个过程吧。
       话说回来,在我做C/S方面的自动化测试之前,是做B/S web方面的,说实在的觉得web方面可能技术上有更高要求,不过大同小异,只是对不同程序所用的插件不同,识别出的对象不同而已,思想还是一样的。
       因为医疗方面的业务流程是比较复杂的,目前都是按照业务流程上面的功能模块进行QTP脚本的分割的,因为每个功能模块在其他业务流程中也有被使用的可能性,按照单个功能模块提供了脚本的复用性,例如:
  • 解析QTP资源文件(转)

    2010-01-28 20:26:30

    ------------------------------------
    ' 从XML格式的资源文件中获取对象
    '------------------------------------
    Public Function GetResource(Byval XmlFile,byval ResourceFile)
     Dim XmlObj,i,j,curRow
     Dim ObjRoot,Children
     Dim childCnt,Parent
     Dim Layer,CurLayerIndex()
     Dim sourceID,ParentID,sourceClass,sourceName
     
     Dim ExcelApp,Exlsheet,ExcelWorkBook
     Set ExcelApp = CreateObject("Excel.Application")
     ExcelApp.Visible = True
     ExcelApp.DisplayAlerts = False
     Set ExcelWorkBook = ExcelApp.Workbooks.Open(ResourceFile)
     Set Exlsheet = ExcelApp.Sheets("对象库")
     Exlsheet.Activate
     
     Set XmlObj = XMLUtil.CreateXMLFromFile(XmlFile)
     
      '---当前行
     curRow = 1
     '----子对象个数
     childCnt = 1
     
     '---------获取根对象
     Set bjRoot = XmlObj.GetRootElement().ChildElements().ItemByName("qtpRep:Objects")
     set  Children = ObjRoot.ChildElementsByPath( "./qtpRep:Object" )
     
     For i = 1 to Children.count()
      ' 第一层对象
      Layer =  0
      ReDim Preserve CurLayerIndex(Layer)
      CurLayerIndex(Layer )  = i
      j = 1
      Set Child = Children.item(i) 
      curRow = curRow + 1
      Parent = curRow - 1
      Set Children = Child.ChildElementsByPath( "./qtpRep:ChildObjects/qtpRep:Object" )
     
      sourceID =  curRow - 1
      Call GetAttrib(Child,sourceClass,sourceName)
      ParentID = 0
      Exlsheet.cells(curRow,1) = sourceID
      Exlsheet.cells(curRow,2) = sourceName
      Exlsheet.cells(curRow,3) = ParentID
      Exlsheet.cells(curRow,4) = sourceClass
      Exlsheet.cells(curRow,5) = "(" + chr(34) + sourceName + chr(34) + ")"
     
      If Children.count() >0  Then
       Layer = Layer + 1
       ReDim Preserve CurLayerIndex(Layer)
      End If
     
      While Children.count() > 0
        If  Children.count() >= j  Then
         CurLayerIndex(Layer )  = j
         Set Child = Children.item(j)
        
         curRow = curRow + 1
         sourceID =  curRow-1
         Call GetAttrib(Child,sourceClass,sourceName)
         ParentID = Parent
         Exlsheet.cells(curRow,1) = sourceID
         Exlsheet.cells(curRow,2) = sourceName
         Exlsheet.cells(curRow,3) = ParentID
         Exlsheet.cells(curRow,4) = sourceClass
         Exlsheet.cells(curRow,5) = "(" + chr(34) + sourceName + chr(34) + ")"
        
         childCnt = Child.ChildElementsByPath( "./qtpRep:ChildObjects/qtpRep:Object" ).count()
     
         If  childCnt > 0 Then
          Layer = Layer + 1
          ReDim Preserve CurLayerIndex(Layer)
          Set Children = Child.ChildElementsByPath( "./qtpRep:ChildObjects/qtpRep:Object" )
          Parent = curRow - 1
          j = 1
          CurLayerIndex(Layer )  = j
         Else
          j = j + 1
         End If
        Else
         temprow = CurRow
         parent = CInt(Exlsheet.cells(parent + 1,3))
        
         Layer = Layer - 1
         Set Child = Child.Parent.Parent
         Set Children = Child.Parent.Parent.ChildElementsByPath( "./qtpRep:ChildObjects/qtpRep:Object" )
                  
          j = CurLayerIndex(Layer) + 1
        End If
      Wend
      Set Children = Child.Parent.ChildElementsByPath( "./qtpRep:Object" )
     Next
     ExcelWorkBook.save
     ExcelApp.Quit
     Set ExcelApp = Nothing
    End Function


    '--------------------------------------
    ' 获取资源对象的描述
    '--------------------------------------
    Public Function GetAttrib(byval Obj,byref attrClass,byref attrName)
     Dim attrIdx
     GetAttrib = ""
     Set CurPara = Obj
     Set attribs = CurPara.Attributes()
     Set attr = attribs.Item(1)
     attrClass = attr.Value()
     GetAttrib = GetAttrib + attr.name() + "=" + chr(34) + attrClass + chr(34) + " "
     Set attr = attribs.Item(2)
     attrName = attr.Value()
     GetAttrib = GetAttrib + attr.name() + "=" + chr(34) + attrName + chr(34)

    End Function

  • QTP中类的基本使用方法(转)

    2010-01-28 20:24:02

    对于共同开发的自动化测试项目,实例方便的调用是很重要的。QTP采用的是vbscript脚本,所以也支持类,但是应为vbs并不支持类的继承,所以只能算作一种“拟类”。采用类对脚本进行封装,有很多好处,对于测试执行人员,可以通过项目情况对封装的类进行调用,而并不必关心类实现的细节。

    此处对QTP类的使用进行一些总结。

    '类名称

    Class TestCase

          Private DataFile

          

          ' ----用例预置条件

          Private Function CasePrepare()

                 

          End Function

          

          ' ----测试数据输入

          Public Function CaseData(byval RowNum)

                 

          End Function

          

          ' ----测试执行

          Public Function CaseRun()

                 

          End Function

          

          ' ----测试结果检查

          Public Function CaseCheck()

                 

          End Function

          

          '获取测试用例号

          Public Property Get CaseID()

                 CaseID = "TestCase_0001"

          End Property

          

          '获取测试用例名称

          Public Property Get CaseName()

                 CaseName = "用户登录"

          End Property

          

          '----构造函数----

          Private Sub Class_Initialize() 

                 DataFile = "C:\autotest\data.xls"

                 

                 Call CasePrepare()

       End Sub

          

          '----解构函数----

          Private Sub Class_Terminate()

                 

          End Sub

     

    End Class

     

    其中Class_initialize为构造函数,类初始化时调用,此处预设了数据文件,并在此处调用了用例预置函数。

    Class_Terminate为解构函数,一般用于释放类执行过程种占用的内存等

    Property Get用于获取类的属性,此处获取该测试用例类的ID,和名称属性

     

    模拟测试用例,类中包含了测试用例的几个部分:

    CasePrepare测试预置条件,如测试用户登录,此处可以判断登录界面是否已经显示

    Casedata:测试数据准备,如测试用户登录,此处可以载入登录用户、登录密码等数据

    CaseRun:测试执行,如测试用户登录,此处可以执行输入验证码,点击登录按钮等操作

    CaseCheck:执行结果检查,如测试用户登录,此处可以对登录结果进行检查,如页面是否正确跳转,如用户、密码不对,是否正确显示提示信息等。

     

    具体在QTP中的使用如下:

    Dim CaseLogin

    Set CaseLogin = New TestCase

    CaseLogin.CaseData 2载入数据文件中的第2行数据作为测试输入

    CaseLogin.CaseRun

    If CaseLogin.CaseCheck Then

     Case_LogInfo “测试用例”CaseLogin. CaseID & “测试通过!”,MicPass

    Else

    Case_LogError “测试用例”CaseLogin. CaseID & “测试失败!”,MicFail

    End If

  • QTP中时间的处理(转)

    2010-01-28 20:23:22

    自动化测试中,经常遇到页面需要输入时间,而这个时间很多时候是当前时间之后某个范围之类才有效。我们采用数据驱动时如果采用绝对时间,则数据复用性就很差了,数据需要经常修改。所以采用相对时间

     

    下面的函数用于获取相对时间

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

    '获取以当前时间为参照的偏移时间

    'increTime: 偏移时间量,可使用负数 格式:day:hour:min:sec  如 1:3:8:23

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

    Public Function GetTime(byval increTime)

           Dim y,m,d,h,n,s,timeArray

          

           timeArray = split(increTime,":",-1,1)

           d= timeArray(0)

           h= timeArray(1)

           n= timeArray(2)

           s= timeArray(3)

          

           GetTime = dateadd("d",d,now)

           GetTime = dateadd("h",h,GetTime)

           GetTime = dateadd("n",n,GetTime)

           GetTime = dateadd("s",s,GetTime)

          

           ' change to GE Time type

           Dim dateArr,timeArr

           timeArray = split(GetTime," ",-1,1)

           dateArr = split(timeArray(0),"-",-1,1)

           y = dateArr(0)

           m = ExpandByZero("L", dateArr(1),2)

           d = ExpandByZero("L", dateArr(2),2)

          

           timeArr = split(timeArray(1),":",-1,1)

           h = ExpandByZero("L", timeArr(0),2)

           n = ExpandByZero("L", timeArr(1),2)

           s = ExpandByZero("L", timeArr(2),2)

          

           GetTime = y  & "-" & m & "-" & d & " " & h & ":" & n & ":" & s

     

    End Function

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

    '以0扩展当前字符串

    'way: 扩展方式 L-左扩,R-右扩

    'OrigStr: 原字符串

    'HopeLen: 扩展后字符长度

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

    Public Function ExpandByZero(byval way,byval OrigStr,byval HopeLen)

       Dim i,ZeroStr

       ZeroStr = ""

       For i =1 to HopeLen - len(OrigStr)

                  ZeroStr = ZeroStr & "0"

       Next

       If way = "L" Then

                  ExpandByZero = ZeroStr & OrigStr

           elseif way = "R" Then

                  ExpandByZero = OrigStr & ZeroStr

           else

                  Exit Function

       End If

    End Function

  • QTP中页面的基本异常检查(转)

    2010-01-28 20:22:19

    页面异常输入测试系统测试的一个重要方面,但是因为比较繁杂,人工测试时往往难以完全覆盖,此时采用自动化测试,就有相当的优势了。

    如下图就是一个典型的信息录入页面

    其中就包括很多异常输入测试点:

    名称不能包含特殊字符,固定的电话格式,固定的手机格式,银行账号(必须全为数字),付费号码长度限制,手机号码格式、长度限制,Email格式限制等

     

    其实异常策略是有通用性的,现总结如下:

    1. exp@@SpecialChar(e_chr)    包含特殊字符,e_chr为指定的特殊字符

    2. exp@@StringLenMax(e_len)  字符串超过最大长度,e_len为最大长度值

    3. exp@@StringLenMin(e_len)  字符串不足最小长度,e_len为最小长度值

    4. exp@@String               字符串包含数字(要求全字符)

    5. exp@@Num                字符串包含字符(要求全数字)

    6. exp@@NumMax(e_max)   输入超过指定最大值,e_max,最大值

    6. exp@@NumMin(e_min)   输入不足指定最大值,e_mmin,最小值

    7. exp@@NumLenMax(e_len)   数值长度超限,e_len,长度最大值

    8. exp@@NumLenMin(e_len)   数值长度不足,e_len,长度最小值

    9. exp@@StringPre(e_pre)      字符串不为指定前缀,e_pre,前缀值

    10. exp@@NumPre(e_pre)      数值不使用指定前缀,e_pre,前缀值

    11. exp@@Email              数值不为标准Email格式

    12. exp@@Need              必输入项,提供空字符串

     

     

    具体实现上,在准备数据文件时,提供两种数据:

    1.     每个字段的默认输入值,即正确值。也是自动化程序执行时默认输入的数据

    2.     异常值,针对每个字段,提供该字段可能需要的异常策略,对所有异常进行遍历。

    第一行为默认值,第二行为字段对应的异常策略

     

    分三个函数来处理

    1.     执行函数

     

    Public Sub excep_OpUser()

                 routingname = "企业用户输入-异常测试"

                载入数据表数据的第2

    GE_SetCurRow OppDataFile,"企业用户",2

                 Dim objStr,oScript,i

                 set bjStr = CreateObject("Scripting.Dictionary")

                 set Script. = CreateObject("Scripting.Dictionary")

                 

                 根据数据表字段设置每个字段的QTP执行语句

                 for i = 1 to DataTable.GetSheet("UserData").GetParameterCount

                        if DataTable.GetSheet("UserData").GetParameter(i)="企业名称" Then _

                                objStr.add DataTable.value(i,"UserData"),".WebEdit("opername").set "

                        。。。。

                 Next

                 

                 调用异常数据生成函数,返回值保存在dictionary对象oScript

                 Gen_excepData(objStr,oScript)

                 

    依次对含异常策略的字段进行异常测试

                 For i = 0 to oScript.Count-1

                        Call OpUserSet(1,oScript(i))

                 Next

                 

                 set bjStr = Nothing

                 set Script. = Nothing

          End Sub

     

    2.     异常数据生成函数

     

    Public Function Gen_excepData(byval dObj,byRef oScript)

          异常值,正确值,异常类型,异常参数

    Dim errorValue,CorrectValue,expType,expPara

          Dim objName,scriptstr

          Dim i,j,expItem

          expItem = 0   记录异常数

          Randomize

          

          for i = 1 to DataTable.GetSheet("UserData").GetParameterCount

                 第一行数据为默认正确数值

                 CorrectValue = DataTable.GetSheet("UserData").GetParameter(i).ValueByRow(1)

                 datatable.SetCurrentRow 2

                 

                 if Instr(Datatable.value(i,"UserData"),"exp@@")>0 Then

                        objName = dObj.Item(Datatable.value(i,"UserData"))

                        同一字段多种异常策略的处理

                        arr1 = split (Datatable.value(i,"UserData"),"|",-1,1)

                        For j = 0 to Ubound(arr1)

                              获取异常类型和异常参数

    If RegExpTest("exp@@.{1,}\(.{1,}\)",arr1(j)) Then

                                      exptype = Mid(arr1(j),6,InStr(arr1(j),"(")-6)

                                      expPara = Mid(arr1(j),InStr(arr1(j),"(")+1,InStr(arr1(j),")")-InStr(arr1(j),"(")-1)

                               Else

                                      expType = replace(arr1(j),"exp@@","")

                               End If                  

                               不同策略对应的数据生成

                               select Case expType

                               Case "SpecialChar"

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"%")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"'")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"/")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),":")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"*")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"&")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"?")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"""")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"<")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),">")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                      oScript.add "excepData" & expItem,scriptstr

                                      errorValue = Replace(CorrectValue,Right(CorrectValue,1),"|")

                                      scriptstr = objName + chr (34) + errorValue + chr(34)

                                      expItem = expItem + 1

                                 

  • QTP DotNetFactory使用解析

    2009-12-01 14:57:41

    QuickTest Professional 9.x 增加了一项新功能DotNetFactory,它能让你创建.NET对象实例,它封装了CreateInstance方法。如果你想使用一个.NET对象作为QuickTest中一个方法的一个参数,你必须使用CreateInstance方法首先为该.NET对象创建一个COM接口:

    Set var_CreateInstance = DotNetFactory.CreateInstance (TypeName [,Assembly] [,args])

    Argument

    Type

    Description

    TypeName
    String
    The full name of the object type, for example, System.Windows.Forms.Form.
    Assembly
    Any
    Optional. If the assembly is preloaded in the registry, you do not need to enter it. Otherwise, you should enter the full path name, for example, System.Windows.Forms. If you want to create an instance of a type in the GAC (Global Assembly Cache), you can enter the short name, for example, Forms.
    Note: If you do not pass this argument, QuickTest assumes that the assembly is resident in memory. If QuickTest does not find the assembly, an error message is displayed during the run session.
    args
    Any
    Optional. The required arguments, if any, for the specified TypeName and/or Assembly.
    支持DotNetFactory这项功能的DLL位于: %programfiles%\HP\QuickTest Professional\bin\DotNetFactory.dll
     
     
    例子:
    1. Set objBtn1 = DotNetFactory.CreateInstance(”System.Windows.Forms.Button”, “System.Windows.Forms”)
    2. Set myList = DotnetFactory.CreateInstance("System.Collections.ArrayList")
    3. Set File = DotNetFactory.CreateInstance("System.IO.File")
    4. Set p1 = DotNetFactory.CreateInstance(”System.Drawing.Point”,”System.Drawing”,x,y)
    5. Set objReader1 = DotNetFactory.CreateInstance(”System.Xml.XmlTextReader”, “System.Xml”,”C:\Documents and Settings\kmohankumar\Desktop\11.xml”)
     
    附录:
    [Description("Enables you to create an instance of a .NET object, and access its methods and properties."), Guid("15494157-E302-4a17-95C7-24C545CA8F53"), ClassInterface(ClassInterfaceType.None), ProgId("Mercury.DotNetFactory.1"), ComVisible(true)]
    public class DotNetFactory : IObjFactory, IReflect, IObjFactoryServices
    {
     // Fields
     private ArrayList _ArgList;
    
     // Methods
     static DotNetFactory()
        {
         Trace.WriteLine("ObjectFactory");
         RegistryKey currentUser = Registry.CurrentUser;
         RegistryKey key2 = currentUser.OpenSubKey(@"Software\Mercury Interactive\QuickTest Professional\MicTest\ReservedObjects\DotNetFactory");//见下图
    string str = (string) key2.GetValue("PreloadAssemblies", null);
         if (str != null)
         {
             string[] strArray = str.Split(new char[] { ';' });
             DotNetFactory factory = new DotNetFactory();
             currentUser.Close();
             key2.Close();
             foreach (string str2 in strArray)
             {
                 try
                 {
                     Trace.WriteLine(str2);
                     factory.LoadAssembly(str2);
                     Trace.WriteLine("Loaded");
                 }
                 catch
                 {
                     Trace.WriteLine("Failed");
                 }
             }
         }
        }
    
     public DotNetFactory();
        {
            this._ArgList = new ArrayList();
        }
    
     private void AddArg(object arg)
        {
             if (arg is DispWrapper)
             {
                 arg = ((DispWrapper) arg)._object;
             }
             this._ArgList.Add(arg);
        }
    
     private void ClearArgs();
     
     public object CreateInstance(string TypeName, object assembly, params object[] CtorArgs)
        {
             object obj3;
             ConstructorInfo[] constructors;
             this._ArgList.Clear();
             if (CtorArgs != null)
             {
                 foreach (object obj2 in CtorArgs)
                 {
                     this.AddArg(obj2);
                 }
             }
             if ((assembly is string) && (((string) assembly).Length > 0))
             {
                 this.LoadAssembly(assembly as string);
             }
             Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();//获取当前应用程序域加载的所有程序集
             Type conversionType = null;
             foreach (Assembly assembly2 in assemblies)
             {
                 conversionType = assembly2.GetType(TypeName);//如果CreateInstance仅有一个参数无须带任何可选参数,帮助里说程序集已在内存中,如例2和例3             
                 if (conversionType != null)
                 {
                     break;
                 }
             }
             if (conversionType == null)
             {
                 throw new Exception("Type '" + TypeName + "' not found in any loaded assembly");
             }
             if (this._ArgList.Count == 0)
             {
                 constructors = conversionType.GetConstructors();//值来自于如果CreateInstance仅有一个参数
                 if ((constructors == null) || (constructors.Length == 0))
                 {
                     if (conversionType.IsValueType)
                     {
                         string str = "0";
                         try
                         {
                             obj3 = Convert.ChangeType(str, conversionType);
                         }
                         catch (InvalidCastException)
                         {
                             obj3 = new DispWrapper(conversionType);
                         }
                     }
                     else
                     {
                         obj3 = new DispWrapper(conversionType);
                     }
                 }
                 else
                 {
                     obj3 = conversionType.Assembly.CreateInstance(TypeName);
                 }
             }
             else
             {
                 object[] args = new object[this._ArgList.Count];
                 for (int i = 0; i < this._ArgList.Count; i++)
                 {
                     args[i] = this._ArgList[i];
                 }
                 this.ClearArgs();
                 constructors = conversionType.GetConstructors();//值来自于如果CreateInstance仅有一个参数
                 if ((constructors == null) || (constructors.Length == 0))
                 {
                     obj3 = new DispWrapper(conversionType);
                 }
                 else
                 {
                     obj3 = conversionType.Assembly.CreateInstance(TypeName, false, BindingFlags.CreateInstance, null, args, null, null);//此步能接受例4和例5的输入
                 }
                 if (obj3 == null)
                 {
                     throw new Exception("Cannot create instance of " + TypeName);
                 }
             }
             if (!(obj3 is string) && !(obj3 is DispWrapper))
             {
                 obj3 = new DispWrapper(obj3);
             }
             return obj3;
        }
     
     public void LoadAssembly(string partialName)
        {
         string str = partialName.ToLower();
         if (str.IndexOf(".dll") > 0)
         {
             this.LoadAssemblyByPath(partialName);
         }
         else if (str.IndexOf(".exe") > 0)
         {
             this.LoadAssemblyByPath(partialName);
         }
         else if (Assembly.LoadWithPartialName(partialName) == null)
         {
             throw new FileNotFoundException("Cannot load Assembly " + partialName);
         }
        }
    
     private void LoadAssemblyByPath(string path)
        {
         Assembly.LoadFrom(path);
        }
    
        FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr);
        FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr);
        MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr);
        MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr);
        MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr);
        MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers);
        MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr);
        PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr);
        PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr);
        PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers);
        object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters); public object Unwrap(object wrapper);
    // Properties
     protected virtual Type MyType { get; }
     Type IReflect.UnderlyingSystemType { get; }
    }
      
     
    [ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch)]
    internal class DispWrapper : IReflect
    {
     // Fields
     internal Exception _exception;
     internal object _object;
     private Type _ObjectType;
    
     // Methods
     internal DispWrapper(object obj)
     {
         this._object = obj;
         this._ObjectType = obj.GetType();
     }
    
     internal DispWrapper(Type t)
     {
         this._object = null;
         this._ObjectType = t;
     }
     public FieldInfo GetField(string name, BindingFlags bindingAttr);
     public FieldInfo[] GetFields(BindingFlags bindingAttr);
     public MemberInfo[] GetMember(string name, BindingFlags bindingAttr);
     public MemberInfo[] GetMembers(BindingFlags bindingAttr);
     public MethodInfo GetMethod(string name, BindingFlags bindingAttr);
     public MethodInfo[] GetMethods(BindingFlags bindingAttr);
     public PropertyInfo[] GetProperties(BindingFlags bindingAttr);  public PropertyInfo GetProperty(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers);
     public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters); MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers); PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr);
     
     // Properties
     public Type UnderlyingSystemType { get; }
    }
    
  • VBScript中的正则表达式语法详解(转)

    2009-11-26 21:25:41

    RegExp属性
    Global
    IgnoreCase
    Pattern

    RegExp方法
    Execute
    Replace
    Test

    RegExp对象
    Match
    Match属性
        FirstIndex
        Length
        Value

    RegExp集合
    Matches
    SubMatches

      我在学习正则表达式的时候根本不知何谓正则表达式、对他的理解也非常模糊,以至于接触了很长时间才懂得,虽然vbs手册中有很详细地解释。

      正则表达式我个人将其理解为用来搜索文本然后然后对搜索结果作处理的一些列动作。

      先来看一段大家所熟知的ubb代码


    function ubb(str)
    Dim rex,match,matches   ' 建立变量。
    Set rex= New RegExp   ' 建立规范表达式。
    rex.IgnoreCase = True   ' 设置是否区分字母的大小写。
    rex.Global = True   ' 设置全程性质。
    rex.Pattern = [url=(.)](.)[url]   ' 设置模式。官方是这样解释的,我认为我们应该换一种叫法:搜索方法,这样我们才便于理解。
    ubb = rex.replace(str,a href="http://www.blog.com.cn/$1"$2a) '将我们搜索到的内容替换
    '我们在设定搜索的时候用到了两个括号,也就是说我们将只需要用到这两个括号中的内容,这两个括号中的内容在替换的时候将会用$1(第一个括号中的内容)和$2(第二个括号中的内容)来代替。
    end function
    '用法
    dim text
    text=[url=httpwww.aaa.com]link[url]
    document.write ubb(text) '输出文本并调用正则表达式
    '如果在asp中使用请将document替换为response

     

      上面是一个简单的正则演示,在这个演示中我们只用了一行内容,用方法replace在替换文字的时候只处理一行中的第一个ubb代码头和最后的一个ubb代码的尾,如下:
    [url=httpwww.aaa.com]link[url] [url=httpwww.aaa.com]link[url]
    将会被替换为a href=httpwww.aaa.com]link[url] [url=httpwww.aaa.coma,这个结果可不是我们要的,
    也就是说我们必须在大量替换搜索内容前将要搜索的全部的文本或者字符串作处理。处理的结果就是要保证每一行只能存在一个相应的代码。这点非常重要,在我学习的时候一直搞不明白为什么?后来才知道是这个原因。

      在上面的一个示例中我们用到了正则表达使得所有属性以及replace的方法,下来我们来看一下有关于方法Execute,对象Match及所有属性,集合Matches 的一个官方的示例

    Function RegExpTest(patrn, strng)
    Dim regEx, Match, Matches   ' 建立变量。
    Set regEx = New RegExp   ' 建立正则表达式。
    regEx.Pattern = patrn   ' 设置模式。即:搜索方法
    regEx.IgnoreCase = True   ' 设置是否区分大小写。
    regEx.Global = True   ' 设置全程可用性。
    Set Matches = regEx.Execute(strng)   ' 执行搜索。我们可以理解为被搜索的字符串
    For Each Match in Matches   ' 遍历 Matches 集合。
      RetStr = RetStr & 匹配 & Match' 注意,在官方提供的示例中这里是错误的,
    这里是被匹配的名称
      RetStr = RetStr & 位于 & Match.FirstIndex & 。'这里是匹配内容的第一个字符,该数字从0开始
      RetStr = RetStr & 匹配的长度为& Match.Length & 个字符。 这里不用解释了吧?
      RetStr = RetStr & vbCRLF '这里是换行
    Next
    RegExpTest = RetStr
    End Function
    document.write(RegExpTest(is., IS1 is2 IS3 is4))
    '如果在asp中使用请将document替换为response


      在这个示例中我们可以看到方法Execute和对象Match是使用在集合Matches中的,Match和Matches是作为变量来使用的,为了我们很容易得看懂它,我们没有必要将他们换名字。关于对象Match的属性,我在上面的示例中都做了注释了。

      最后我们来看集合SubMatches,代码如下:(由于官方的这段代码很含糊,所以我修改了一下)

    Function SubMatchTest(inpStr)
    Dim Re, Match, Matches
    Set Re = New RegExp
    Re.Pattern = (w+)@(w+).(w+)
    Set Matches = Re.Execute(inpStr)
    Set Match = Matches(0) '由于这里没有使用循环,所以只能搜索一次。只匹配搜索到的第一个内容
    retStr = 电子邮件地址是:  & Match & vbNewline ' 这里是匹配的内容
    retStr = retStr & 电子邮件别名是:  & Match.SubMatches(0) '第一个括号中的内容
    retStr = retStr & vbNewline
    retStr = retStr & 组织是:  & Match. SubMatches(1)'第二个括号中的内容
    SubMatchTest = retStr
    End Function
    document.write(SubMatchTest(请写信到 dragon@xyzzy.com 。谢谢!))
    '如果在asp中使用请将document替换为response


      在上面的这段代码中我们看到了对象Match和集合Matches的另外一种用法,由此可见所有的集合均可以用这种方法,就像实用数组一样。看完上面的代码有些朋友可能想到既然在属性Pattern中已经提供了$1$2.....$n这种方法,为什么还要存在集合SubMatches呢?实际上在我们使用证则表达式的时候可能搜索要匹配的内容或字符串很长,然而我们还要对搜索到匹配的字符串进行进一步的处理,而$又不能实现这个,于是便有了集合SubMatches。

      到这里有关于VBScript的正则表达式的内容就全部说完了,上面的3个代码均可以放在<SCRIPT. Language=VBScript><SCRIPT>标签中使用也可以放在ASP中执行。

  • QTP对象库管理

    2009-11-25 16:26:11

    在QTP中,如果不能有效的管理对象,将大大加大后期脚本的维护成本。我们需要的是一个干净整洁的对象库,但由于QTP本身对于对象的管理操作的局限性,我们只有运用有限的方法,来应对无限的可能发生的情况。

    在录制过程中,QTP将抓取大量的WEB对象(包括Button、Link、text等),有些对象是重复出现的,可以重复利用。但如果不及时清理这些冗余的对象,势必造成对象库臃肿和复杂。

    下面,我们制定了一系列规范,来管理我们的对象库
    在QTP通过执行脚本中的语句来识别WEB页面中的对象,脚本语句包括Browser(Main、Sub_O、Sub_T)、Page、***(控件类型:如WebEdit、WebButton等)

    我们规定:
    1)Browser只允许出现3种,即主页面(Main),次页面(Sub_O)、第三页(Sub_T),其中主页面Main没有creatontime标记,次页面Sub_O的creatontime标记值为1,第三页面Sub_T的Sub_Ocreatontime标记值为2

    2)Page页的名称需和页面的Title对应

    3)出现重复的对象,需要合并到(运用MI公司提供的QuickTest Plus中的插件Repositories Merge Utility合并)

    实现步骤: a、设置环境变量:“Test settings”->"Environment"
                    b、Variable type:User-defined
                    c、Click “New”
                    d、input “name”、“Value”
                    (such as->name:ObjectPath_Product)
                    e、save
                    f、QTP脚本中写语句读取环境变量:
                    ( Such as->ObjectPath = Environment.Value    ("ObjectPath_Product")
                       Call SetObjectRepository(ObjectPath)
                   )
                    g、用VB写函数,用于调用对象库
                    (见如下代码),VB函数可以写在后缀名为VBS的文件中
                    h、在QTP中加载对象库文件:
                      “Test settings”->"Resources"
                      在"Object repository type"中加载对象库文件
                      点击“Set as Default”
                   i、 h、在QTP中加载VB函数:
                      “Test settings”->"Resources"
                      在"Associated library files"中加载VBS函数文件
                      点击“Set as Default”

    注:1)这里的Value我们可以输入对象库的存放地址,用于把文件地址传到QTP脚本中

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiaohe119/archive/2007/04/27/1587163.aspx

  • QTP学习

    2009-10-18 20:52:14

    DOM技术的应用

    1.最普通的方法
      Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").Set "helloworld" 

    2.描述性编程
      Browser("百度一下,你就知道").Page("百度一下,你就知道").webedit("name:=wd").Set "123"

    3.对象自身接口
      Browser("百度一下,你就知道").Page("百度一下,你就知道").WebEdit("wd").Object.value="helloworld"

    4.DOM技术
      Browser("百度一下,你就知道").Page("百度一下,你就知道").Object.getElementById("kw").value="helloworld"

    5.childobject结合描述性编程循环遍历获取对象
      '描述对象  
      Set Desc = Description.Create()  
      oDesc("micclass").Value = "WebEdit" 
      '获取webedit的数量  
      edit_count=Browser("百度一下,你就知道").Page("百度一下,你就知道").ChildObjects(oDesc).count  
     '获取子对象集合  
      set editobjects=Browser("百度一下,你就知道").Page("百度一下,你就知道").ChildObjects(oDesc)  
      For i=0 to edit_count-1  
        If editobjects(i).GetROProperty("name")="wd" then  
            editobjects(i).set "helloworld" 
        End If 
      Next 

    6.getElementsByName和getElementsByTagName返回的都是一个集合对象
      getElementsByName:
      '*****************************
      Set pageOjbect=Browser("百度一下,你就知道").Page("百度一下,你就知道")
      set editObjs= pageOjbect.Object.getElementsByName("wd")
      For each obj in editObjs
        obj.value="helloworld"
      Next
      '*****************************

      getElementsByTagName:
      '*****************************
      Set pageOjbect=Browser("百度一下,你就知道").Page("百度一下,你就知道")
      set editObjs= pageOjbect.Object.getElementsByTagName("input")  
      For i=0 to editObjs.length
        If editObjs.item(i).name="wd" Then
          editObjs.item(i).value="helloworld"
          Exit for
        End If
      Next
      Set editObjs=nothing
      Set pageObject=nothing
      '*****************************

    对象库

      DESCRIPTION PROPERTIES:用于对象识别时对比的属性
      ordinal indentifier :是针对出现相同对象时可以自动给对象进行编号,也就是INDEX
      Additional details:qtp的智能识别,意思就是如果打开了智能识别之后,QTP如果在页面上找不到对象之后,他会找最接近的一个对象进行匹配,,但是如果关闭了这个功能之后,只要有一个属性不匹配,QTP就会找不到对象的

  • (转)qtp 成为高手需要掌握常用com对象

    2009-09-16 10:32:11

    成为高手需要了解的基本com对象处理技术,了解常用的com对象的使用,如果你想成为高手,那么从下面对象开始吧:

    文件系统对象相关:
    ("scrīptING.FILESYSTEMOBJECT")

    应用:数据驱动技术常用,日志输入常用

    字典相关:
    ("scrīptING.DICTIONARY")

    应用:脚本配置控制开关 list对象item数据对比

    脚本外壳相关:
    ("Wscrīpt.SHELL")

    应用:最常用其中的sendkeys方法,利用在不可识别对象技术方面

    WINDOWS外壳相关:
    ("SHELL.APPLICATION")

     

    正则表达式相关:
    ("VBscrīpt.REGEXP")

    应用:网页解析,数据对比 验证点技术实现的一种

    编码与密码相关:
    ("scrīptPW.PASSWORD")
    ( "scrīptING.ENCODER" )

    应用:数据包传输测试过程中应用

    邮件发送的组件相关:
    ("JMAIL.MESSAGE")
    ("CDONTS.NEWMAIL")
    ("CDO.CONFIGURATION")
    ("EUDORA.EUAPPLICATION.1")
    ("NOVELLGROUPWARESESSION")

    应用:测试报告发送

    水晶报表相关:
     ("CRYSTALRUNTIME.APPLICATION")

    应用:测试报告美化,常用的是excel的报告输出,这种技术用的少

    IE浏览器相关:
    ("INTERNETEXPLORER.APPLICATION")

    应用:web测试用的比较多

    ADO相关:
    ("ADODB.CONNECTION")
    ("ADODB.COMMAND")
    ("ADODB.RECORDSET")
    ("ADODB.RECORD")
    ("ADODB.STREAM")
    ("DAO.DBENGINE.35")
    ("ADOX.CATALOG")
    ("ADOX.TABLE")

    应用:数据驱动,数据库验证,dao主要利用在access数据库处理

    SQL相关:
    ("SQLDMO.SQLSERVER")
    ("SQLDMO.LOGIN")
    ("SQLDMO.BACKUP")
    ("SQLDMO.USER")
    ("SQLDMO.BACKUPDEVICE")
    ("SQLDMO.DATABASE")
    ("SQLDMO.RESTORE")
    ("SQLDMO.APPLICATION")

    OFFICE相关:
    ("WORD.APPLICATION")
    ("EXCEL.APPLICATION")
    ("POWERPOINT.APPLICATION")
    ("EXCEL.SHEET")
    ("FRONTPAGE.APPLICATION")
    ("ACCESS.APPLICATION")
    ("MSGRAPH.APPLICATION")
    ("OUTLOOK.APPLICATION")

    应用:测试报告输出,数据驱动

    WMI相关:
    ("WBEMscrīptING.SWBEMDATETIME")
    ("WBEMscrīptING.SWBEMLOCATOR")
    ("WBEMscrīptING.SWBEMNAMEDVALUESET")
    ("WBEMscrīptING.SWBEMSINK", "SINK_")
    ("WBEMscrīptING.SWBEMREFRESHER")
    ("WBEMscrīptING.SWBEMLASTERROR")
    ("WBEMscrīptING.SWBEMOBJECTPATH")

    应用:初始化测试环境

    对象为我所用,我为测试所用

  • QTP:对象映射(自定义对象)应用(转)

    2009-09-14 14:17:25

    QTP版本:9.2英文版。

      一. 自动义对象应用

      当要操作的一些对象不识别时,且这些对象可以映射成标准Window控件时,则可以考虑自定义这些对象,并映射到相似的Window控件。这样就可以调用标准Window控件运行的方法来操作自定义对象了。

      要映射成相似的Window控件,则自定义的对象要有和标准Window控件相似的功能和操作。

      此法可以处理一些看起来像是标准Window控件的对象,但并不是所有这类对象都可行。如Delphi控件,大部分可以如此处理,但一些控件则不行哦。

      二. 自动义对象如何使用

      首先,需要对不识别的控件进行自定义,并做好与标准window控件的映射;

      其次,可以通过录制或描述性编辑调用这些自定义的对象;

      然后,就是像对待能识别的对象一样进行操作即可。

      注意:

      在移动脚本运行时(比如拷贝脚本至其他虚拟机运行),需要先运行自定义对象的定义脚本,然后再运行脚本。

      最好的方法是在要使用时,脚本中运行定义自定义对象的脚本,执行完成后则删除自定义的对象,恢复到原有配置。而由于QTP不提供删除单个自定义对象的功能,而提供了恢复默认配置的功能,因此只好使用恢复到默认对象配置的功能了。

      例:添加一个自定义对象的定义脚本如下:

    DimApp 'As Application
    ‘如果是在已经运行的QTP中运行,则可以用GetObject获取运行的QTP程序对象
    ‘如果是直接用VBS运行QTP,则可以用CreateObject建立QTP程序对象。
    SetApp =GetObject("","QuickTest.Application")
     
    ‘建立一个自定义对象“ttoolbar”,并映射到标准控件“WinToolbar”
    App.Options.ObjectIdentification("WinToolbar").CreateUserDefinedObject("ttoolbar")
    App.Options.ObjectIdentification("ttoolbar").OrdinalIdentifier = "location"
    App.Options.ObjectIdentification("ttoolbar").MandatoryProperties.RemoveAll()
    App.Options.ObjectIdentification("ttoolbar").MandatoryProperties.Add("nativeclass")
    App.Options.ObjectIdentification("ttoolbar").MandatoryProperties.Add("text")
    App.Options.ObjectIdentification("ttoolbar").AssistiveProperties.RemoveAll()
    App.Options.ObjectIdentification("ttoolbar").AssistiveProperties.Add("window id")
    App.Options.ObjectIdentification("ttoolbar").EnableSmartIdentification =False
    App.Options.ObjectIdentification("ttoolbar").BaseFilterProperties.RemoveAll()
    App.Options.ObjectIdentification("ttoolbar").OptionalFilterProperties.RemoveAll()

      以上脚本也可以通过“Generate Script...”导出,然后删掉不是自定义的对象定义脚本,并稍微修改一下即可。

      恢复默认对象配置的方法如下:

      App.Options.ObjectIdentification.ResetAll

      三. 如何自定义对象

      1.      选择“Tools”>>“Object Identification”;

      2.      在“Environment”框中选择“Standard Windows”,则“User-Defined…”按钮将变为可用;

      3.      点击“User-Defined…”按钮,将显示“Object Mapping”对话框;

      4.      单击指向手,然后单击要将其类作为用户定义的类添加的对象。用户定义的对象的名称将显示在“Class Name”框中。(其实这个“Class Name”框也可以自己填,如果自己清楚该填什么的话)

      提示:按住Ctrl键,可以更改窗口焦点或执行右键单击或鼠标悬停(以显示上下文菜单)等操作。注意:按Ctrl键时,您不能从Windows任务栏中选择应用程序,因此,必须确保要访问的窗口没有最小化。

      5.      在“Map to”框中,选择要将用户定义的对象类映射到的标准对象类,然后单击“Add”。类名和映射将添加到对象映射列表中。

      6.      如果要将其他对象映射到标准类,请对每个对象重复步骤4-5。

      7.      单击“OK”。“Object Mapping”对话框关闭,您的对象作为用户定义的测试对象添加到标准Windows测试对象类列表中。注意:您的对象具有角上带有一个红色U的图标,标识它为用户定义的类。

      8.      为用户定义的对象类配置对象标识设置,方式与任何其他对象类一样。

      四. 例子

      以下举一个例子,就拿我们公司正在用的Delphi开发的“XX系统”为例吧:

      *操作如下:点击ToolBar中的打开按钮->在文本区域写入内容->点击ToolBar中的关闭按钮->关闭窗口

      *XX系统的界面就不给了,不好意思。

      [直接录制]如果不加载插件,则QTP对Delphi程序是不识别的,录制的代码如下:

    **************************************************************************************
    Window("XX系统").Activate
    Window("XX系统").WinObject("TToolBar").Click 266,39
    Window("XX系统").WinObject("TNoteEditor").Click 371,50
    Window("XX系统").WinObject("TNoteEditor").Type "fdsfasd"
    Window("XX系统").WinObject("TToolBar").Click 570,32
    Window("XX系统").WinObject("TToolBar").Click 327,36
    Window("XX系统").Close
     **************************************************************************************
    [定义自定义控件再录制]
    *定义自定义控件:
    *定义自定义控件后再录制的脚本如下:
    **************************************************************************************
    Window("XX系统").Activate
    Window("XX系统").WinToolbar("TToolBar").Press "打开"
    Window("XX系统").WinEditor("TNoteEditor").Type "fdsafsdafdas"
    Window("XX系统").WinToolbar("TToolBar").Press "保存"
    Window("XX系统").WinToolbar("TToolBar").Press "关闭"
    Window("XX系统").Close
    **************************************************************************************
     
    [改造后的脚本]
    *稍微改造一下,脚本如下,这样就可以自动调用程序进行笔录操作,然后关闭程序:
    **************************************************************************************
    SystemUtil.Run "C:\Program Files\XXXXsoft\ XX系统\P_XXXX.exe"
    ‘这里只是为了说明如何使用映射,不然以下这个循环会有一定的问题的哦,需要改造一下。
    Do while not  Dialog("提示").WinButton("确定").Exist(0)
       wait 1
    Loop
    Dialog("提示").WinButton("确定").Click
    Window("XX系统").Activate
    Window("XX系统").WinToolbar("TToolBar").Press "打开"
    Window("XX系统").WinEditor("TNoteEditor").Type "dfdghfdgfsgfds"
    Window("XX系统").WinEditor("TNoteEditor").Type micReturn
    Window("XX系统").WinEditor("TNoteEditor").Type "gfdsgfd"
    Window("XX系统").WinEditor("TNoteEditor").Type micReturn
    Window("XX系统").WinToolbar("TToolBar").Press "保存"
    Window("XX系统").WinToolbar("TToolBar").Press "关闭"
    window("XX系统").Close
    **************************************************************************************
     
    *如果是在其他机器上运行,则还需要先运行以下定义自定义控件的代码:
    **************************************************************************************
    Dim App 'As Application
    Set App = GetObject("","QuickTest.Application")
     
    'Configuration of user-defined objects
    'Object identification configuration for user-defined object "ttoolbar"
    App.Options.ObjectIdentification("WinToolbar").CreateUserDefinedObject("ttoolbar")
    App.Options.ObjectIdentification("ttoolbar").OrdinalIdentifier = "location"
    App.Options.ObjectIdentification("ttoolbar").MandatoryProperties.RemoveAll()
    App.Options.ObjectIdentification("ttoolbar").MandatoryProperties.Add("nativeclass")
    App.Options.ObjectIdentification("ttoolbar").MandatoryProperties.Add("text")
    App.Options.ObjectIdentification("ttoolbar").AssistiveProperties.RemoveAll()
    App.Options.ObjectIdentification("ttoolbar").AssistiveProperties.Add("window id")
    App.Options.ObjectIdentification("ttoolbar").EnableSmartIdentification = False
    App.Options.ObjectIdentification("ttoolbar").BaseFilterProperties.RemoveAll()
    App.Options.ObjectIdentification("ttoolbar").OptionalFilterProperties.RemoveAll()
     
    'Object identification configuration for user-defined object "tnoteeditor"
    App.Options.ObjectIdentification("WinEditor").CreateUserDefinedObject("tnoteeditor")
    App.Options.ObjectIdentification("tnoteeditor").OrdinalIdentifier = "location"
    App.Options.ObjectIdentification("tnoteeditor").MandatoryProperties.RemoveAll()
    App.Options.ObjectIdentification("tnoteeditor").MandatoryProperties.Add("attached text")
    App.Options.ObjectIdentification("tnoteeditor").MandatoryProperties.Add("nativeclass")
    App.Options.ObjectIdentification("tnoteeditor").AssistiveProperties.RemoveAll()
    App.Options.ObjectIdentification("tnoteeditor").AssistiveProperties.Add("window id")
    App.Options.ObjectIdentification("tnoteeditor").EnableSmartIdentification = False
    App.Options.ObjectIdentification("tnoteeditor").BaseFilterProperties.RemoveAll()
    App.Options.ObjectIdentification("tnoteeditor").OptionalFilterProperties.RemoveAll()
    **************************************************************************************
     
    *在脚本运行结束时需要运行以下脚本,以清除自己的配置,防止影响别人脚本的运行:
    **************************************************************************************
    App.Options.ObjectIdentification.ResetAll
    Set App = Nothing
     **************************************************************************************

  • (转)使用QTP统计页面加载时间

    2009-09-14 14:10:23

    QTP是一款功能自动化测试工具,而页面加载时间或响应速度应该是性能测试的事情,其实QTP也可以实现对页面加载时间的统计功能。因为QTP使用的是VBS脚本,VBS脚本的强大之处在于它可以调用任何windows的COM组件和对象。那么问题解决的思路就很简单了,就是我们要利用VBS获取 IE网页,并统计网页加载的时间。

      分析很简单,但是在实现上却有几个技术问题:一、如何使用VBS分析网页。我们知道网页技术是基于DOM模型的(也不知道这么说是不是准确),那么只要我们能用VBS调用DOM下的document对象,那么我们就可以使用document的方法来实现我们的要求;二、如果能实现对DOM的调用,我们如何统计页面加载的各个阶段的时间,通过查阅资料可以知道,在document中有一个readystate方法,该方法共有五个返回值,分别对应网页初始化到网页加载完毕五个阶段,我们可以利用该方法实现我们的要求。

      实现的思路如下:

      1、利用createobject创建一个IE的实例,以访问document对象;

      2、利用document对象的readystate属性获取网页加载时各个阶段的时间,

      3、利用timer()实现对毫秒的统计。timer()函数的作用是统计从午夜时间到当前时间所过去的秒数,我们用两个timer值想减就可以得到两个时间点之间相隔的毫秒数。

      4、为了方便调用,将时间统计的代码封装成一个函数。

      最后代码如下:

    '在loadrunner脚本中,把要访问的url做参数化,变量名为SITEURL
    'timeCount方法返回一个字符串,字符串的内容是统计各个阶段发生的时间
    '可以使用各种方法查看result的内容
    SITEURL = "www.sina.com.cn"'设置要进行访问的URL
    result = timeCount(SITEURL)'返回运行结果
    MsgBox result '输出运行结果,在loadrunner中可以将该行注释掉

    '方法定义开始
    Public Function timeCount(url)
    Set dom = CreateObject("InternetExplorer.Application")  '创建一个IE的对象
    dom.Navigate(url)  '打开指定的URL
    time_start = Now()'获取统计开始时的时间
    timer_start = timer()'获取当前时间的毫秒数
    'a = dom.ReadyState'获取当前IE的状态值,将使用该状态值判断IE的当前状态
    dom.visible = True '设置IE可见
    While dom.busy or (dom.readyState<>4)'当IE处于BUSY状态或者加载未完成时(readystate不等于4)时,根据IE的状态统计时间,每毫秒统计一次
    wscrīpt.sleep 1 '时间间隔1毫秒,如果时间间隔比较长的话,很有可能会取不到状态值
    Select Case dom.readystate '判断dom.readystate的值

    Case 0 'IE未初始化,其实在该方法,readystate=0无意义,因为循环至少是从1开始的.
    time0 = Now()
    timer0 = timer()

    Case 1 '"正在发送请求"
    time1 = Now()
    timer1 = timer()

    Case 2 '"请求已经发送完成"
    time2 = Now()
    timer2 = timer()

    Case 3 '"可以接收到部分响应数据"
    time3 = Now()
    timer3 = timer()

    Case 4 '"页面加载完成"
    time4 = Now()
    timer4 = timer()

    End select
    wend
    time_end = Now() '统计结束时间
    'MsgBox "开始时间是:" & time1 & ";结束时间是"&time2

    timeCount = "统计开始时间:"&start_time&vbcrlf&"time0:"&time0&vbcrlf&"time1:"&time1&vbcrlf&"time2:
    "&time2&vbcrlf&"time3:"&time3&vbcrlf&"time4:"&time4&vbcrlf&"完成IE的初始化并发送请求:
    "&(timer1-timer_start)&"秒"&vbcrlf&"发送完成并接受服务端部分响应数据:
    "&(timer3-timer1)&"秒"&vbcrlf&"100%接收并完成HTML内容解析:
    "&(timer4-timer3)&"秒"&vbcrlf&"总共花费:"&(timer4-timer_start)&"秒"
    End Function

     代码中的SITEURL就是我们要进行测试的页面。

      这段代码虽然不长,但是却花了我整整4个小时的时间。一开始碰到的难题就是不知道VBS如何去调用document方法,在网上查了无数资料,大多是讲如何在HTML代码中进行调用,很少说到如何使用标准VBS去调用,其实到最后才明白,VBS调用访问document无非就是这样的一句代码:

      Set dom = CreateObject("InternetExplorer.Application")

      虽然简单,但是却花了我一个小时才明白。

      通过这样的一段代码时间,我现在清楚了两件事,第一:VBS作为脚本语言,它的强大之处在于它调用windows的COM能力,而VBS本身并没有什么复杂的技术和体系。第二:QTP永远只是一款工具,它能做什么取决于我们如何去使用。

  • 使用QTP完成回归脚本(转)

    2009-09-14 12:10:00

    最近组内在写项目的回归脚本,且组内新人较多,看到好多同学为写脚本而不知所措,现想把自己曾经学习QTP的笔记和经验跟大家分享下,希望有所帮助。

      QTP可以自动捕获、验证和重放用户的交互行为。它的自动化测试流程包括:

      ● 准备Test Case

      ● 录制脚本

      ● 修改增强脚本

      ● 调试脚本

      ● 回放脚本

      ● 脚本维护

      1. 准备Test Case

      在进行脚本编写之前,将要测试内容文档化,不建议直接录制脚本。

      测试内容文档化的好处

      – 在录制前将脚本设计好,可以保证脚本录制过程更流畅

      – 利于团队协作,设计测试案例和脚本开发可以不是同一个人

      – 便于后期的维护

      2. 录制脚本

      启动QTP的录制功能(面板上的Record),按照Test Case的操作步骤描述执行,QTP自动记录每一步操作,并自动生成VBscript脚本。

      3. 修改增强脚本

      录制好的脚本可能包含错误,也可能没达到预期的目标,这就需要在录制脚本的基础上,进行修改增强:

      – 删除录制过程中多余的操作,以最少的步骤完成必要的操作。

      – 如果后续操作的输入是前面操作的输出,则需要使用变量或者输入输出值进行替换。

      – 不是所有的操作都可以录制产生,需要手工编码实现这些功能,如对Excel文件的读写,数据库的操作等。

      – 录制产生的脚本为线性结构,可加入条件、循环控制语句,如if、while等语句,实现一些复杂的流程。

      – 脚本加入注释,便于阅读和维护。

      4. 调试脚本

      并非只有等到脚本回放失败时,才需对脚本进行调试,正确回放的脚本同样会包含错误。

      – Test Script由操作步骤和检查步骤组成;

      – 操作步骤只要能够执行成功结果均为Pass,如使用了非预期输入数据而也能执行成功;

      – 检查点步骤有预先设定的判断标准,但是如果标准是变量或者是参数,就需要仔细检查数据是否为预期数据

      – 在回放之前,可以通过插入断点,对脚本中的关键数据进行检查核对,确保脚本正式使用前Test Script本身正确性。

      5. 回放脚本

      通过前面一系列的工作,再点击面板上的Run按钮就可以回放Test Script里的操作了。

      6. 脚本维护

      随着工作的不断推进,脚本量会越来越多;被测程序的更新,也需要相应的更新测试脚本。脚本的维护变得愈发重要。

      – 采用版本管理工具保存脚本,如SVN,可以随时获取历史版本

      – 采用统一的脚本架构

      – 采用统一的命名规范

      – 添加充分的注释,避免时间久了连自己也无法马上读懂脚本。

      在今后的文章中,我将分别来描述以下QTP里的一些比较常用的几个功能点:

      ●对象识别及存储>>

      ●QTP 检查点(CheckPoint)>>

      ● 参数化

      ● 数据驱动

      ● 脚本复用

      ● 恢复场景

      ● 虚拟对象

      ● 脚本调试

      ● 正则表达式

  • QTP:vbs测试webservice脚本(转)

    2009-09-14 11:49:33

    脚本是写着玩的,有什么建议或者意见,欢迎各位行家指出。

      脚本部分:

    作者:  aslandhu
    '公司:  中科大讯飞科技股份有限公司
    '部门:  技术质量部
    '脚本功能:     webservice自动化测试,自动读取测试用例,用例配置文件,最终将测试结果写入用例中。
    '开发开始时间: 2009-4-20
    '******************************************************************webservice 测试开始*************************************************************
    '请在使用前调试脚本确保脚本能正常工作
    '请严格使用提供的模板编写用例,否则脚本无法正常工作
    '***************************************************************** 收集相关信息************************************************************************
    Dim SoapText,XmlHead,XmlLast,SoapQuest,MethodInput,XmlMethodString1,XmlMethodString2,WebserviceAddress,testResult,ResultPath
    MethodInput=InputBox("方法名称为:")
    Dim n,m,i,j,a,b,k,c 'n为参数个数,也即用例需要取值的列数量,m为用例数量即Excel行数,K为方法数量(保留)
    n=CInt(InputBox("参数个数为:"))
    k=CInt(inputbox("需要比较的返回值个数"))
    m=CInt(InputBox("Excel行数,即用例数:"))
    WebserviceAddress=Inputbox("接口URL为:")
    TestPath=Inputbox("完整用例路径:")
    Dim ArrayInfo()
    ReDim ArrayInfo(m,n)
    '**************************************************************** 拼装SOAP头尾消息*****************************************************************
    XmlHead="<?xml version=""1.0"" encoding=""utf-16""?>"&"<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">"&"<soap:Body>"
    XmlLast="</soap:Body>"&"</soap:Envelope>"
    XmlMethodString1="<"&MethodInput&" "&"xmlns=""http://tempuri.org/"">"'&"<model>"
    'XmlMethodString2="</model>"&"</"&MethodInput&">"
    XmlMethodString2="</"&MethodInput&">"
    '***************************************************************** 创建Excel对象,准备读取用例************************************************
    Set Excel = CreateObject("Excel.Application")
    oExcel.DisplayAlerts=FALSE
    oExcel.Visible = false
    oExcel.WorkBooks.Open(TestPath)
    oExcel.WorkSheets(MethodInput).Activate
    '***************************************************************** 将用例存入数组********************************************************************
    For i=1 To m  '行数3,b
      For j=1 To n  '列数2,a
      ArrayInfo(i,j)= oExcel.Cells(i,j).Value
     Next
    Next
    '**************************************************************** 开始组装SOAP主体*****************************************************************
    SoapText=""
    For b=2 To m
    For a=1 To n
    SoapText=SoapText&"<"&ArrayInfo(1,a)&">"&ArrayInfo(b,a)&"</"&ArrayInfo(1,a)&">"
    Next
    SoapQuest=XmlHead&XmlMethodString1&SoapText&XmlMethodString2&XmlLast
    'MsgBox(SoapQuest)
    WriteToFile  "c:\test.txt",SoapQuest
    '**************************************************************** 开始循环发送消息*********************************************************************
    '定义一XML的文档对象
    '初始化http对象
    Set h = createobject( "Microsoft.XMLHTTP")
    h.open "POST", WebserviceAddress, False
    h.setRequestHeader "Content-Type", "text/xml; charset=utf-8"
    h.setRequestHeader "SOAPAction", "http://tempuri.org/"&MethodInput
    h.send (SoapQuest)
    While h.readyState <> 4
    Wend
    '***************************************************************循环处理返回结果并将结果写入用例***********************************************
    For c=n+1 to n+k
    testResult=oExcel.Cells(1,c).Value
    If  oExcel.Cells(b,c).Value <>NodeData(h.responseText,testResult) then
       oExcel.Cells(b,c+k).Value ="false"
              oExcel.Cells(b,c+k).Font.Color = RGB(255, 0, 225)
       oExcel.Cells(b,c+k).Interior.Color = RGB(0, 255, 0) 'Background color
                     oExcel.Cells(b,c+k).Font.Bold = True
     else
       oExcel.Cells(b,c+k).Value ="true"
       oExcel.Cells(b,c+k).Font.Color = RGB(0, 0, 0)
       oExcel.Cells(b,c+k).Interior.Color = RGB(255, 255, 255) '
    end if
    Next
    SoapText=""
    Next

    '****************************************************************释放Excel对象,并将结果写到指定路径***************************************
    CheckFolder "C:\TestResult"
    ResultPath="C:\TestResult\"&MethodInput&".xls"
    oExcel.WorkSheets(MethodInput).SaveAs ResultPath
    oExcel.WorkBooks.Close
    oExcel.Quit
    Set Excel=nothing

    '*************************************************************** 以下是被调用的函数****************************************************************
    '获取结点值并输出到txt文本
    function NodeData(XmlString,Node)
    Dim ResultArray,NodeString,NodeDateLen,No,i
    ResultArray=Split(XmlString,Node,-1,1)
    No=UBound(ResultArray) '获取数组上界
    '循环查找符合要求的字节
    For i=1 To No Step 2
    NodeString=ResultArray(i)
    NodeDateLen=Len(NodeString)-3
    NodeData=Mid(NodeString,2,NodeDateLen)
    Next
    End function


    ''将string写入文本
    Sub WriteToFile (filepath,text)
      Dim fso, MyFile,txtFile
    if  IsFileExist(filepath)=true then
      Set fso = CreateObject("Scripting.FileSystemObject")
      Set txtFile = fso.GetFile(filepath)
      Set MyFile = txtFile.OpenAsTextStream(8, 0)
      MyFile.Write text&vbcrlf
      MyFile.Close
      else
      CreatedFile(filepath)
       Set fso = CreateObject("Scripting.FileSystemObject")
      Set txtFile = fso.GetFile(filepath)
      Set MyFile = txtFile.OpenAsTextStream(8, 0)
      MyFile.Write text&vbcrlf
      MyFile.Close
      end if
    End Sub

    '创建文本文件
    Sub CreatedFile(filepath)
     Set fso = CreateObject("Scripting.FileSystemObject")
        Set MyFile = fso.CreateTextFile(filepath, true)
        MyFile.WriteLine("<!-- Result -->")
        MyFile.Close
    End Sub

    '判断txt文件是否存在
    Function IsFileExist(filepath)
      Dim fso
      Set fso = CreateObject("Scripting.FileSystemObject")
      IsFileExist = fso.FileExists(filepath)
    End Function

    Sub CheckFolder(folderpath)
    Dim fso,CreateFolderSuccess,f
    Set fso=CreateObject("Scripting.FileSystemObject")
    If  fso.FolderExists(folderpath)=false Then
     Set f = fso.CreateFolder(folderpath)
      CreateFolderSuccess = f.Path
      Else
      Set fso=nothing
    End If
    End Sub

      脚本使用步骤:

      1、运行脚本,提示输入方法名称。

      2、提示输入参数个数:(参数个数为方法需要传入的参数个数,即用例中的输入)

      3、提示输入需要比较的返回值的个数:(指的是输出的结果的个数,用例中写了几列就输入几列(不带单位))

      4、提示输入Excel行数,即用例个数(包括第一列非用例,即总行数):

      5、提示输入接口URL(即接口链接地址):

      6、提示输入完整用例路径(即用例存放地址):

      7、等待执行一段时间

      8、查看C:\TestResult,可以获取测试结果如下:(出现与预期结果不一致的用例会使用绿色将结果标明)

      9、测试完成。

      注意事项:

      (1)目前仅实现一个方法一个脚本,且一个Excel只能存放一个方法的测试用例(后期改进)

      (2)未实现结果的统计(后期实现)

      (3)前面要求输入的内容必须准确可靠,否则脚本会执行出错(后期改进容错能力,会考虑加入脚本配置文件)

      (4)脚本必须配合指定的用例模板

      (5)建议脚本不要使用QTP执行,直接双击操作。在QTP上运行的话,脚本执行速度会非常慢。

1391/71234567>
Open Toolbar