vbscriptfunction-pointershp-uft

VBScript Function as Parameter, or similar Construct


I'm trying to put together tests in HP Unified Functional Testing the way a programmer would. For those unaware, the tool uses VBScript as its driver.

Because I want to use data from the same DataTable across multiple UFT actions -- and because the Global table already has a different set of data on it -- I want to retrieve data from an external file. UFT happily supports this function.

My current plan is that, depending on which test I'm running, I will iterate through only a range of rows in that table.

This is the script I've come up with:

' 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

I don't want to have to repeat all this boilerplate every time I want to use this pattern. I'd really like to have something like:

In a Function Library:

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

In the original action...

sub Payload1()
    MsgBox(DataTable.Value("LastName", dtLocalSheet))
end sub
LoopThroughSheetAnd "PersonFile.xlsx", Payload1

In a separate action, 3 or 4 steps later...

sub Payload2()
    ' compare the data against another data source
end sub
LoopThroughSheetAnd "PersonFile.xlsx", Payload2

The above code doesn't work in VBScript. A type mismatch error is thrown as soon as we try to pass Payload1 as a parameter.

How could one reasonably pull this off in VBScript? Bonus points if the answer also works in UFT.


Solution

  • You can pass functions as parameters with the GetRef() function. Here's a utility map function, like you'd find in JavaScript that accepts an array and calls a function for each element of the array:

    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")
    

    Now you could write SomeFunc so that it operates on a value and returns an updated value:

    Function SomeFunc(i)
        SomeFunc = i + 1
    End Function
    

    This works fine. map calls SomeFunc using the function "pointer" we passed to it.

    You could do something similar with your LoopThroughStreetAnd function:

    LoopThroughStreetAnd "PersonFile.xlsx", GetRef("Payload2")