VBScript函数作为参数,或类似的构造

问题描述 投票:3回答:4

我正在尝试将测试整合到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,则可获得加分。

vbscript function-pointers hp-uft
4个回答
6
投票

可以通过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")

2
投票

GetRef一样,VBScript中的standard回调方法使用this demo


0
投票

使用对象时,可以将对方法的调用包装在对象中,然后可以传递该对象。 (这大约已经在其他语言中发生过,您只需要在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

使用ExecuteAction1Wrapper也可以像下面这样写。您也可以编写工厂类以方便使用。

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

-1
投票

[当我写问题时,我的记忆开始了,然后我开始研究我曾经发现的“功能”。

在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在范围内不存在。

© www.soinside.com 2019 - 2024. All rights reserved.