本文由
Peter 发表在:
迈向破灭的回旋曲
通 常情况下,当在录制一个操作时, QTP 会将被操作对象加入到对象库里( Object Repository )。一旦对象存在于对象库里,我们就可以在专家 视图里通过添加相关的对象方法来对该对象进行操作。我们可以通过引用层次型对象库里的对象描述( Object Description )来添加相应的方 法。因为 QTP 对象库中的每个对象都具有唯一名称,所以在引用时对象名是必须需要指定的。然后在测试运行期间, QTP 在对象库中根据这个对象的名称和父对象来查找对象,并使用为这个测试对象存储的测试对象描述,在网站或应用程序中标识该对象。 例 如我们用 QTP 录制 Yahoo Mail 登录情况时我们需要输入用户名,于是在录制时我们就会录下一个 WebEdit 对象,它的缺省逻辑名为 “login” ,该编辑字段位于名为 “Yahoo! Mail - The best” 的页面上,并且该页面在浏览器中使用名称 Yahoo! 进行录制。 那么如果我们想要应用该对象,就可以在专家视图输入以下信息: Browser("Yahoo!").Page("Yahoo! Mail - The best").WebEdit("login").Set “xxx” 或者我们也可以调用一些方法,获取改对象在运行时的对象名,如: Browser("Yahoo!").Page("Yahoo! Mail - The best").WebEdit("login").GetROProperty(“name”) 然 而,我们可以发觉到,上面的例子在处理对象时,对象已经存在于对象库里,因此我们可以应用这个对象的逻辑名。实际使用中,情况往往并非如此简单,我们经常 会遇到很多在页面上动态产生的对象,换而言之,对象库里没有这些对象,我们也无从引用。因此我们必须采用其他的技术来完成这类操作,这也就是我们需要讲解 的 Descriptive Programming 。为了满足上面提到的动态对象的处理问题, QTP 允许用户通过将对象属性编码到测试脚 本里来动态识别对象,这就是我们通常意义下称为的 Descriptive Programming 。通过这种方式,我们可以指示 QTP 不通过引用对象库和 对象名来对实际对象进行操作。具体操作中,我们只需要为 QTP 提供对象的一组属性和值,这样 QTP 就可以来识别相应的对象并对其进行操作。这相当于,告诉 QTP 要识别对象的一些关键特征,根据这些特征 QTP 就可以一一匹配然后识别出来这个对象。而且,更为重要的是,通过这种 Descriptive Programming 的方式,还可以让 QTP 识别具有某些相同属性的对象。我们先来举个例子来看一下:我们假设当前的 Windows 系统中打开了若干的 Yahoo 主页面(多于一个),现在我们要关闭所有的正在浏览 Yahoo 主页面的浏览器。对于上面那个例子来说,我们先看一个简单一点的情况,假设只有且仅有一个 Yahoo 主页面:那么我们可以用下面的方法来 Window("Text:=Yahoo! - Microsoft Internet Explorer").Close 我 们可以看到语句里我们要查找的对象是 Window 窗口标题为 “Yahoo! - Microsoft Internet Explorer” ,然后把它关 闭,具体的语法说明我们稍后为解释。但是上面的语句仅仅适合前面提到的条件 “ 只有且仅有一个 Yahoo 主页面 ” ,如果有多个同样的窗口就会出错,原因是通 过语句可以匹配到多个对象,而 QTP 不知道应该对哪个对象进行关闭动作。我们需要进一步的缩小匹配范围: Dim i i = 0 while (Window("Text:="Yahoo!" - Microsoft Internet Explorer", "index:="&i).exist) Window("Text:=Yahoo! - Microsoft Internet Explorer", "index:="&i).close i = i +1 wend 这里我们可以看到,对于具有相同属性的对象,我们可以通过 index 参数来对其进行区别,第一个对象为 index=0 ,第二个为 index=1 等等,依次类推。当然我们还可以通过 CreationTime 和 Location 参数来定位对象,这里就不详细叙述了。 通 过上面的例子,我们对 Descriptive Programming 有一个基本了解了,下面我们详细讲解一下 Descriptive Programming :在具体实现中,我们有两种类型的 Descriptive Programming 方法。可以列出直接在 测试语句中描述对象的属性和值的集合;或者向 Description 对象中添加属性和值的集合,然后在语句中输入 Description 对象的名称。 下面我们分别举例介绍。 2 、直接在语句中输入编程描述通过多个指定描述对象的 property:=value 对,可以直接在语句中描述对象,这是最直接有效的方法。常规语法为: TestObject("PropertyName1:=PropertyValue1", "..." , "PropertyNameX:="PropertyValueX""} TestObject - 测试对象的类。 PropertyName:=PropertyValue - 测试对象的属性及其值。各个 property:="value" 对之间应用逗号和引号分开。例如:以下语句指定 Mercury Tours 页面中名为 author 且索引值为 3 的 WebEdit 测试对象。当测试运行时, QTP 将查找具有匹配属性值的 WebEdit 对象,并输入文本 jojo 。 Browser("Mercury Tours").Page("Mercury Tours").WebEdit("Name:="Author"", "Index:="3"").Set "Mark Twain" 我们也可以从从描述中的特定位置(从 Page 对象描述开始)开始使用 Descriptive Programming 。 Browser("Mercury Tours").Page("Title:="Mercury" Tours").WebEdit("Name:="Author"", "Index:="3"").Set "jojo" 此外,如果我们希望在在一个测试或组件中多次使用相同的 Descriptive Programming ,则可以将创建的对象赋值给变量,这样使用会方便很多。 例如:我们需要完成下面一系列操作 Window("Text:=HyperSna").WinButton("Caption:= 日期 ").Click Window("Text:=HyperSna").WinButton("Caption:= 时间 ").Click Window("Text:=HyperSna").WinButton("Caption:= 确定 ").Click 那么,为了方便其见,我们可以将 Window("Text:=HyperSna") 赋值到一个变量,然后再使用,参见下面的代码: Set WinHyper = Window("Text:="HyperSna"") WinHyper.WinButton("Caption:= 日期 ").Click WinHyper.WinButton("Caption:= 时间 ").Click WinHyper.WinButton("Caption:= 确定 ").Click 如果使用了 VBScript 里面的 With 语句,还可以简化为以下代码: With Window("Text:="HyperSna"") .WinButton("Caption:= 日期 ").Click .WinButton("Caption:= 时间 ").Click .WinButton("Caption:= 确定 ").Click End With 下面我们来看一个更为详细的例子,在 QTP 产品缺省安装里面自带了一个网上订机票的示例称为 Mercury Tour ,我们看一下在订票过程中何时需要用 Descriptive Programming 。首 先登入系统后,如果需要订票,就要先搜索航班,此时系统要求输入订票乘客的数量,假设我们在第一次录制脚本时选择了 1 个 Passenger ,并成功完成订 票。然后,我们需要参数化乘客数量来测试订票系统,我们会发现回放会失败。原因在于,不同的乘客的数量导致在订票时需要输入每个乘客的姓名,而录制时,只 输入了一个乘客的姓名。而乘客姓名的输入框是随着乘客数量的变化而动态生成的,我们不可能从对象库里得到没有录制的对象,因此必须使用 Descriptive Programming 。 在录制单个乘客时,我们得到的录制语句是: Browser("Welcome: Mercury Tours").Page("Book a Flight: Mercury").WebEdit("passFirst0").Set "Michael" Browser("Welcome: Mercury Tours").Page("Book a Flight: Mercury").WebEdit("passLast0").Set "Wang" 显然 WebEdit("passFirst0") 和 WebEdit("passLast0") 是录制时产生的对象并存放到对象库里的。通过对象库,我们可以看到对象的属性如下 系 统对于发生多个 FirstName 时,命名规则是 passFirst0 , passFirst1… 依次类推。因此只要通过简单的 Descriptive Programming 就可以完成动态 FirstName 与 LastName 的识别工作。这里我们假设参数化的乘客数已经赋值给 intPassNum ,下面是脚本中的关键语句: counter = 0 For i = 0 to (intPassNum) Browser("Find a Flight:").Page("Book a Flight:").WebEdit("name:="passFirst""&i).Set "Michael" Browser("Find a Flight:").Page("Book a Flight:").WebEdit("name:="passLast""&i).Set "Wang" counter = counter + 1 Next 3 、使用 description 对象 使 用 Description 对象可以返回包含一组 Property 对象的 Properties 集合对象。 Property 对象由属性名和值组成。然 后,可以在语句中指定用返回的 Properties 集合代替对象名。(每个 property 对象都包含一个属性名和值)。 要创建 Properties 集合,可以使用以下语法输入 Description.Create 语句: Set MyDescription = Description.Create() 创 建 Properties 对象(例如,以上示例中的 MyDescription )后,就可以输入语句,以便在运行会话期间在 Properties 对象中 添加、编辑、删除或检索属性和值。这样,就可以在运行会话期间,使用动态方法确定哪个属性以及多少个属性应包含在对象描述中。 在 Properties 集合中填充一组 Property 对象(属性和值)后,可以在测试语句中指定用 Properties 对象代替对象名。 例如,假设我们需要完成以下一个操作: Window("Error").WinButton("text:=OK", "index:="1"").Click 我们可以通过 Description 对象来实现同样的功能,参加下面的代码: Set MyDescription = Description.Create() MyDescription("text").Value = "OK" MyDescription("index").Value = 1 Window("Error").WinButton(MyDescription).Click Set MyDescription = Nothing |