第10章Descriptive Programming(DP)描述性编程
描述性编程提供了和运行时对象交互执行交互的方法。运行时对象在对象库里是不存在的。该技术也证明了当被测应用程序还不能被录制时开发测试用例是有用的。
Object Identification 对像识别
为了在测试脚本回访过程中识别对象,QTP在对象库中为对象存储了一个或多个属性。在运行时,QTP使用这个属性来唯一识别出一个对象。图10-1显示了一个简单的对象库,该对象库包含了对一个网页对象和其3个控件对象的描述。
对象库中的“Google Search”对象包含了3个记录的属性:“type”,”name”, “html tag”。注意,QTP记录了3个属性,例如是该测试对象的强制定义的属性,但在运行时识别对象时,并不是所有的属性都是必须的。
Implicit Properties
当我们使用描述性编程来定义对象描述时,有些固定的属性不需要我们明确的提供,因为QTP会自动根据所参考的测试对象类型来赋予固定的值。例如,上面的“Google Search”是一个WebButton,QTP会给“html tag”赋值为INPUT,“type”赋值为submitted。但是,在一种情况下,如果参考的是一个通用WebElement时,需要明确定义每个重要的属性。
什么时候该使用描述性编程
下面举例说明了在哪些情况下,适合使用描述性编程来代替传统的通过对象库定义测试对象:
l 当被测应用程序的对象在自然情况下是动态的,在运行时需要作特殊的处理来识别他们。最好的例子是点击一个连接,该连接会根据应用程序的不同使用者而改变,如”Logout<Username>”
l 当对象库变得非常大时。如果对象库太大,会降低QTP回放时的性能。
l 当我们不想使用对象库时。下面的场景解释了为什么我们可能不使用对象库。
l 当需要修改对象库对象试,而该对象所在的对象库是只读的,或是共享对象库,修改会影响其他脚本,变得不可空。
l 当我们想要操作许多相似或格式一致的对象时,如在一个页面上有20个文本框,并以txt_1, txt_2,到txt_20的格式命名。在这种情况下,在对象库里添加20个对象不是好的编程方法,应该使用动态定义的描述性编程语句。
描述性编程的语法
有以下2种方法老创建描述性编程语句:
l 使用描述性对象
l 使用描述性字符串
使用描述性对象
使用该方法,可以创建一个描述性对象,并定义识别该对象的属性和属性值。描述性对象的创建和初始化和数据字典对象非常相似。使用该方法来描述“Google Search”:
‘ 创建一个描述性对象
Dim btnGoogelSearch
Set btnGoogelSearch=Description.Create
‘添加描述性识别属性属性
btnGoogelSearch(“type”).value=”submit”
btnGoogelSearch(“type”).RegularExpression=False
btnGoogelSearch(“name”).value=”Google Search”
btnGoogelSearch(“html tag”).value=”INPUT”
Description.Create创建了一个新的对象,用于存储描述性编程的描述。每个描述性对象的属性支持一个赋值和一个正则表示式标记。默认情况下,正则表达式标记为真,表明使用VBS正则表达式语法来解释属性的赋值字符串。
‘使用描述性对象btnGoogelSearch,点击一个按钮
Browser(“Browser”).Page(“Page”).WebButton(btnGoogelSearch).Click
NOTE:在一个语句中,一旦开始使用描述性编程语法,该语句的剩下部分必须继续使用描述性编程。在上面的语句中,根据Page参考,开始使用的是对象库参数,WebButton参考开始使用描述性编程语法。
在上述代码中,使用描述性对象,需要用几行代码来定义“Google Search”按钮。现在我们提供子程序, 可以完成大部分的赋值工作:
'该函数将字符串或数组转换成描述性对象
Sub CreateDescription(ByVal dpObjName, ByVal dpObjStringOrArray)
'该变量用于存放所有的属性
Dim propArray
'该变量用于存放属性的名称和对于的属性值
Dim valArray
If varType(dpObjStringOrArray)<vbArray Then
'将字符串转换成数组,用于创建描述
propArray=Split(dpObjStringOrArray, ",")
else
propArray=dpObjStringOrArray
End If
'创建描述性对象
ExecuteGlobal "set" & dpObjName & "=Description.Create"
Dim i
For i=Lbound(propArray) to Ubound (propArray)
'从property:=value中将属性名和属性值分开
valArray=Split(propArray(i), ":=")
ExecuteGlobal dpObjName & " (" " & valArray(0) & " ").value = " " & valArray(1) & " " "
Next
End Sub
上面的方法可以这样使用:
'Usage
descArray = Array("html tag:=INPUT","Name:=Submit")
descStr1 = "Name:=Submit"
descStr2 = "Name:=Submit,html tag:=INPUT"
CreateDescription "dpSubmit1",descArray
CreateDescription "dpSubmit2",descStr1
CreateDescription "dpSubmit3",descStr2
Micclass识别器
Micclass是识别器,用于描述QTP测试对象的类型。例如:”micclass:=WebButton” 是WebButton对象的一个明确的属性。当页面上只有一个按钮时,除了“micclass:=WebButton”,不需要使用其他的属性描述。我们可以在任何测试对象上使用GetTOProperty结合micclass来决定测试对象的类型。
' 显示浏览器
Msgbox Browser("Browser").GetTOProperties("micclass")
'显示网页
Msgbox Browser("Browser").Page("Page").GetTOProperties("micclass")
NOTE:“Class Name”并不像QTP对象识别器显示的那样,它不是测试对象类型的属性。在对象识别器中,micclass被映射为Class Name。
使用描述性字符串
在这种描述性编程方法中,我们不需要创建描述性对象,而是使用描述性字符串来识别图10-1中的“Google Search”按钮。在下面的第二行代码中,我们使用了三个描述性字符串:
'获取网页对象参数
Set oPg=Browser("Google").Page("Google")
'使用字符串型描述来获取按钮对象
Set oButton=oPg.WebButton("html tag:=INPUT", "type:=submit", "name:=Google Search")
但是, 就如我们之前说的, 不需要定义所有的属性来识别一个对象.
‘用一个属性来获取button对象
Set oButton=oPg.WebButton("name:=Google Search")
Enumerating ChildObjects获取子对象
QTP提供了ChildObjects方法来获取子对象。要获取一个网页上所有文本框对象的集合,可以使用如下代码:
‘Create a description object创建一个描述性对象
Set dpAllTxt = Description.Create
'Set the description for WebEdit only
dpAllTxt("micclass").value = "WebEdit"
'Get all the objects macthing the description获取所有匹配该描述的对象
Set allTextboxes = Browser("title:=.*").Page("title:=.*").ChildObjects(dpAllTxt)
'Loop through all of them在所有WebEdit对象中循环
iCount = allTextboxes.Count - 1
For i = 0 to iCount
Set oTxt = allTextboxes.item(i)
oTxt.Set "This is Text box #" & (i+1)
Next
当传递给ChildObjects一个空的描述对象时,返回所有的子对象。
'Create a description object创建一个描述性对象
Set dpAllChilds= Description.Create
''Set the description for WebEdit only
'dpAllTxt("micclass").value = "WebEdit"
'Get all the objects macthing the description获取所有匹配该描述的对象
Set allChilds = Browser("title:=.*").Page("title:=.*").ChildObjects(dpAllChilds)
'Loop through all of them在所有WebEdit对象中循环
iCount = allChilds.Count - 1
For i = 0 to iCount
msgbox allChilds.item(i).GetTOProperty("micclass")
Next
Converting an OR-based script to a DP-based script将基于对象库的脚本转换成基于描述性编程的脚本
将基于对象库的脚本转换成基于描述性编程的脚本,需要为每个描述性编程语句仔细地选择需要的对象库对象属性,来唯一地识别出运行时的对象。假设下面的基于对象库的语句,记录了windows计算器计算2乘以5:
'Launch the calculator application
SystemUtil.Run "calc.exe"
'Activate the window
Window("Calculator").Activate
'Perform various operations
Window("Calculator").WinButton("2").Click
Window("Calculator").WinButton("*").Click
Window("Calculator").WinButton("5").Click
Window("Calculator").WinButton("=").Click
'Check the results
Window("Calculator").WinEdit("Edit").Check CheckPoint("Edit")
上述代码的对象库如下图:
观察该对象库,我们发现对象是通过text label给识别的。转换成描述性编程,可以使用如下的代码:
'Run the calculator application
SystemUtil.Run "calc.exe"
With Window("regexpwndtitle:=Calculator")
'Activate the window
.Activate
'Perform various operations
.WinButton("text:=2", "nativeclass:=Button").Click
'* is regular expression and we should use a \ before that
.WinButton("text:=\*","nativeclass:=Button").Click
.WinButton("text:=5","nativeclass:=Button").Click
.WinButton("text:==","nativeclass:=Button").Click
'Check the results. We cannot create checkpoint object using
'DP but we can run a already created checkpoint on a object
'identified using DP
.WinEdit("nativeclass:=Edit").Check CheckPoint("Edit")
.Close
End With
NOTE: 我们使用的是regexpwndtitle:=Calculator来识别计算器窗口,也可以使用regexpwndclass:=SciCal,因为该属性对于计算器应用程序也是唯一的。为防止序窗口标题会不断变化,最好选择window class 或其他属性。
在描述性编程中,选择一个或多个合适的属性来识别对象是很重要的。像x,y,abx_x等属性,每次运行时都会改变,所以不是个好的选择。像title, regexpwdtitle等属性,在多数情况下,更可靠。
Using a VBScript DP object repository 使用VBS描述性编程对象库
在逻辑上模拟QTP对象库,将描述性编程对象定义放在VBS库文件中。
UserForm.vbs
'Delcare DP string definition
Const dpBrowser="micClass:=Browser"
Const dpPage="micClass:=Page"
Const dpFirstName="name:=txtLastName"
Const dpLastName="name:=txtLastName"
Const dpSubmit="name:=submit"
有2种方法将上述代码包含到一个或多个脚本中:
l 通过Test Setting Resource 标签关联VBS文件
l 使用ExecuteFile语句在一个或多个测试Action中加在 VBS文件
Script
‘运行IE
systemutil.Run "iexplore.exe"
Browser(dpBrowser).Sync
‘输入数据
Browser(dpBrowser).Page(dpPage).WebEdit(dpFirstName).Set "Tarun"
Browser(dpBrowser).Page(dpPage).WebEdit(dpLastName).Set "Lazlwani"
'点击提交按钮
Browser(dpBrowser).Page(dpPage).WebButtion(dpSubmit).Click
该技术还可以用于实现多语言测试脚本。为不同的语言创建不同的VBS 文件,例如,dpOR_EN.vbs, dpOR_FR.vbs, dpOR_DN.vbs等