我正在尝试将测试整合到HP Unified Functional Testing中程序员的方式。对于那些不知道的人,该工具使用VBScript作为其驱动程序。
因为我想在多个UFT操作中使用同一DataTable中的数据-并且因为Global表已经具有不同的数据集-我想从外部文件中检索数据。UFT很高兴支持此功能。
我目前的计划是,根据我正在运行的测试,我将仅迭代该表中的一系列行。
这是我想出的脚本:
' targets the local sheet, but
' not the same value as dtLocalSheet
Const sheetNum = 2
dim sheetRowCount
DataTable.ImportSheet "PersonFile.xlsx", 1, sheetNum
sheetRowCount = DataTable.GetSheet(sheetNum).GetRowCount
dim firstRow, lastRow
firstRow = Parameter("FirstPersonIndex")
lastRow = Parameter("LastPersonIndex")
If sheetRowCount < lastRow Then
lastRow = sheetRowCount
End If
If sheetRowCount >= firstRow Then
Dim i
For i = firstRow To lastRow
DataTable.SetCurrentRow i
' begin payload
MsgBox(DataTable.Value("LastName", dtLocalSheet))
' end payload
Next
End if
我不想重复所有这些样板每次我想使用这种模式。我真的很喜欢这样的东西:
在函数库中:
sub LoopThroughSheetAnd(sheetFile, doThis)
' targets the local sheet, but
' not the same value as dtLocalSheet
Const sheetNum = 2
dim sheetRowCount
DataTable.ImportSheet sheetFile, 1, sheetNum
sheetRowCount = DataTable.GetSheet(sheetNum).GetRowCount
dim firstRow, lastRow
firstRow = Parameter("FirstRow")
lastRow = Parameter("LastRow")
If sheetRowCount < lastRow Then
lastRow = sheetRowCount
End If
If sheetRowCount >= firstRow Then
Dim i
For i = firstRow To lastRow
DataTable.SetCurrentRow i
call doThis()
Next
End if
end sub
在原始动作中...
sub Payload1()
MsgBox(DataTable.Value("LastName", dtLocalSheet))
end sub
LoopThroughSheetAnd "PersonFile.xlsx", Payload1
[在另一操作中,需要3或4个步骤...
sub Payload2()
' compare the data against another data source
end sub
LoopThroughSheetAnd "PersonFile.xlsx", Payload2
以上代码在VBScript中不起作用。引发类型不匹配错误尝试将Payload1
作为参数传递时。
[如何在VBScript中合理地实现这一目标?如果答案也适用于UFT,则可获得加分。
您可以通过GetRef()
函数将函数作为参数传递。这是一个实用程序map
函数,就像您在JavaScript中发现的那样,它接受一个数组并为该数组的每个元素调用一个函数:
Sub Map(a, f)
Dim i
For i = 0 To UBound(a)
' Call a function on each element and replace its value with the function return value
a(i) = f(a(i))
Next
End Sub
Map MyArray, GetRef("SomeFunc")
现在您可以编写SomeFunc
,以便它对一个值进行运算并返回更新后的值:
Function SomeFunc(i)
SomeFunc = i + 1
End Function
这很好。 map
使用传递给它的函数“指针”调用SomeFunc
。
您可以使用LoopThroughStreetAnd
函数执行类似的操作:
LoopThroughStreetAnd "PersonFile.xlsx", GetRef("Payload2")
使用对象时,可以将对方法的调用包装在对象中,然后可以传递该对象。 (这大约已经在其他语言中发生过,您只需要在VBScript中手动进行即可。)
唯一的问题是,以这种方式调用的任何方法都必须为Public
。
我将使用诸如“ Func1”,“ Func2”,“ Action1”,“ Action2”等的命名方案,具体取决于函数的可用性以及它们是否返回值。
Dim s : Set s = New Something : s.Run
Class Something
Public Sub HowToPassMe(pValue)
WScript.Echo pValue
End Sub
Public Sub Run
Dim action : Set action = New Action1Wrapper
Set action.Target = Me
Dim se : Set se = New SomethingElse
se.DoSomethingElse action
End Sub
End Class
Class SomethingElse
Public Sub DoSomethingElse(pAction1)
pAction1.Action1("something")
End Sub
End Class
Class Action1Wrapper
Private mTarget
Public Property Set Target(value) : Set mTarget = value : End Property
Public Sub Action1(p1)
mTarget.HowToPassMe(p1)
End Sub
End Class
使用Execute
,Action1Wrapper
也可以像下面这样写。您也可以编写工厂类以方便使用。
Class Action1Wrapper
Private mTarget
Public Property Set Target(value) : Set mTarget = value : End Property
Private mName
Public Property Let Name(value) : mName = value : End Property
Public Sub Action1(p1)
Execute "mTarget." & mName & "(p1)"
End Sub
End Class
Class Action1Factory_
Public Function Create(pTarget, pName)
Dim a1 : Set a1 = New Action1Wrapper
Set a1.Target = pTarget
a1.Name = pName
Set Create = a1
End Function
End Class
Dim Action1Factory : Set Action1Factory = New Action1Factory_
用作:
Dim action : Set action = Action1Factory.Create(Me, "HowToPassMe")
Dim se : Set se = New SomethingElse
se.DoSomethingElse action
[当我写问题时,我的记忆开始了,然后我开始研究我曾经发现的“功能”。
在HP UFT的背景下,此方法无效,但是,如果您正在运行cscript或使用Classic ASP,您可以延迟声明一个函数,或替换先前的声明,更改其工作方式。
VBScript可让您声明相同的函数或子例程在一个程序中多次。它将最后一个声明视为正确的声明。
您可以通过物理分隔在cscript和ASP中解决此问题该函数的不同版本,这样一个人就不会被另一个人淹没。您必须注意不要将两者放置在彼此附近的任何地方,或者您(后继者)可能患有动脉瘤,试图调试结果。
老实说,最好以其他方式重构代码。
现在,有了免责声明,以下示例适用于cscript或wscript。
由于无论如何这在UFT中均不起作用,因此我将从头开始编写。
在WrapperSub.vbs:
中' Sub WrapperSub_Payload doesn't exist in this file.
' It must be declared by the calling file or the program will crash.
Sub WrapperSub()
wscript.echo("This begins the wrapper.")
WrapperSub_Payload
wscript.echo("This ends the wrapper.")
End Sub
在WrapperSubUseA.vbs:
With CreateObject("Scripting.FileSystemObject")
call ExecuteGlobal(.openTextFile("WrapperSub.vbs").readAll())
End With
Sub WrapperSub_Payload
wscript.echo("This is payload A.")
End Sub
WrapperSub
在WrapperSubUseB.vbs:
With CreateObject("Scripting.FileSystemObject")
call ExecuteGlobal(.openTextFile("WrapperSub.vbs").readAll())
End With
Sub WrapperSub_Payload
wscript.echo("This is payload B.")
End Sub
WrapperSub
>cscript wrappersubusea.vbs
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
This begins the wrapper.
This is payload A.
This ends the wrapper.
>cscript wrappersubuseb.vbs
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.
This begins the wrapper.
This is payload B.
This ends the wrapper.
注意,如果占位符为WrapperSub_Payload
在源文件中声明,该占位符将始终执行而不是预期的子例程。这可能是由于ExecuteGlobal在解析当前文件后执行导致占位符在本地声明后加载。
[当您在UFT中尝试此操作时,将WrapperSub.vbs的内容放在函数库中-函数库正确地忽略了调用者的作用域。然后它将失败,因为WrapperSub_Payload
在范围内不存在。