Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon

Using Classes

Save for later
  • 26 min read
  • 28 Nov 2014

article-image

In this article by Meir Bar-Tal and Jonathon Lee Wright, authors of Advanced UFT 12 for Test Engineers Cookbook, we will cover the following recipes:

  • Implementing a class
  • Implementing a simple search class
  • Implementing a generic Login class
  • Implementing function pointers

(For more resources related to this topic, see here.)

Introduction

This article describes how to use classes in VBScript, along with some very useful and illustrative implementation examples. Classes are a fundamental feature of object-oriented programming languages such as C++, C#, and Java. Classes enable us to encapsulate data fields with the methods and properties that process them, in contrast to global variables and functions scattered in function libraries. UFT already uses classes, such as with reserved objects, and Test Objects are also instances of classes. Although elementary object-oriented features such as inheritance and polymorphism are not supported by VBScript, using classes can be an excellent choice to make your code more structured, better organized, and more efficient and reusable.

Implementing a class

In this recipe, you will learn the following:

  • The basic concepts and the syntax required by VBScript to implement a class
  • The different components of a class and interoperation
  • How to implement a type of generic constructor function for VBScript classes
  • How to use a class during runtime

Getting ready

From the File menu, navigate to New | Function Library…, or use the Alt + Shift + N shortcut. Name the new function library cls.MyFirstClass.vbs and associate it with your test.

How to do it...

We will build our MyFirstClass class from the ground up. There are several steps one must follow to implement a class; they are follows:

  1. Define the class as follows:
    Class MyFirstClass

  2. Next, we define the class fields. Fields are like regular variables, but encapsulated within the namespace defined by the class. The fields can be private or public. A private field can be accessed only by class members. A public field can be accessed from any block of code. The code is as follows:
    Class MyFirstClass
    Private m_sMyPrivateString
    Private m_oMyPrivateObject
    Public m_iMyPublicInteger
    End Class

    It is a matter of convention to use the prefix m_ for class member fields; and str for string, int for integer, obj for Object, flt for Float, bln for Boolean, chr for Character, lng for Long, and dbl for Double, to distinguish between fields of different data types. For examples of other prefixes to represent additional data types, please refer to sites such as https://en.wikipedia.org/wiki/Hungarian_notation.

    Hence, the private fields' m_sMyPrivateString and m_oMyPrivateObject will be accessible only from within the class methods, properties, and subroutines. The public field m_iMyPublicInteger will be accessible from any part of the code that will have a reference to an instance of the MyFirstClass class; and it can also allow partial or full access to private fields, by implementing public properties.

    By default, within a script file, VBScript treats as public identifiers such as function and subroutines and any constant or variable defined with Const and Dim respectively,, even if not explicitly defined. When associating function libraries to UFT, one can limit access to specific globally defined identifiers, by preceding them with the keyword Private.

    The same applies to members of a class, function, sub, and property. Class fields must be preceded either by Public or Private; the public scope is not assumed by VBScript, and failing to precede a field identifier with its access scope will result in a syntax error. Remember that, by default, VBScript creates a new variable if the explicit option is used at the script level to force explicit declaration of all variables in that script level.

  3. Next, we define the class properties. A property is a code structure used to selectively provide access to a class' private member fields. Hence, a property is often referred to as a getter (to allow for data retrieval) or setter (to allow for data change).

    A property is a special case in VBScript; it is the only code structure that allows for a duplicate identifier. That is, one can have a Property Get and a Property Let procedure (or Property Set, to be used when the member field actually is meant to store a reference to an instance of another class) with the same identifier. Note that Property Let and Property Set accept a mandatory argument. For example:

    Class MyFirstClass
    Private m_sMyPrivateString
    Private m_oMyPrivateObject
       Public m_iMyPublicInteger
     Property Get MyPrivateString()
       MyPrivateString = m_sMyPrivateString
    End Property 
    Property Let MyPrivateString(ByVal str)
       m_sMyPrivateString = str
    End Property
    Property Get MyPrivateObject()
       Set MyPrivateObject = m_oMyPrivateObject
    End Property 
    Private Property Set MyPrivateObject(ByRef obj)
       Set m_oMyPrivateObject = obj
    End Property
    End Class

    The public field m_iMyPublicInteger can be accessed from any code block, so defining a getter and setter (as properties are often referred to) for such a field is optional. However, it is a good practice to define fields as private and explicitly provide access through public properties. For fields that are for exclusive use of the class members, one can define the properties as private. In such a case, usually, the setter (Property Let or Property Set) would be defined as private, while the getter (Property Get) would be defined as public. This way, one can prevent other code components from making changes to the internal fields of the class to ensure data integrity and validity.

  4. Define the class methods and subroutines. A method is a function, which is a member of a class. Like fields and properties, methods (as well as subroutines) can be Private or Public. For example:
    Class MyFirstClass
    '… Continued
    Private Function MyPrivateFunction(ByVal str)
       MsgBox TypeName(me) & " – Private Func: " & str
       MyPrivateFunction = 0
    End Function 
    Function MyPublicFunction(ByVal str)
       MsgBox TypeName(me) & " – Public Func: " & str
       MyPublicFunction = 0
    End Function 
    Sub MyPublicSub(ByVal str)
       MsgBox TypeName(me) & " – Public Sub: " & str
    End Sub
    End Class

    Keep in mind that subroutines do not return a value. Functions by design should not return a value, but they can be implemented as a subroutine. A better way is to, in any case, have a function return a value that tells the caller if it executed properly or not (usually zero (0) for no errors and one (1) for any fault). Recall that a function that is not explicitly assigned a value function and is not explicitly assigned a value, will return empty, which may cause problems if the caller attempts to evaluate the returned value.

  5. Now, we define how to initialize the class when a VBScript object is instantiated:
    Set obj = New MyFirstClass

    The Initialize event takes place at the time the object is created. It is possible to add code that we wish to execute every time an object is created. So, now define the standard private subroutine Class_Initialize, sometimes referred to (albeit only by analogy) as the constructor of the class. If implemented, the code will automatically be executed during the Initialize event. For example, if we add the following code to our class:

    Private Sub Class_Initialize
    MsgBox TypeName(me) & " started"
    End Sub

    Now, every time the Set obj = New MyFirstClass statement is executed, the following message will be displayed:

    using-classes-img-0

  6. Define how to finalize the class. We finalize a class when a VBScript object is disposed of (as follows), or when the script exits the current scope (such as when a local object is disposed when a function returns control to the caller), or a global object is disposed (when UFT ends its run session):
    Set obj = Nothing

    The Finalize event takes place at the time when the object is removed from memory. It is possible to add code that we wish to execute, every time an object is disposed of. If so, then define the standard private subroutine Class_Terminate, sometimes referred to (albeit only by analogy) as the destructor of the class. If implemented, the code will automatically be executed during the Finalize event. For example, if we add the following code to our class:

    Private Sub Class_Terminate
    MsgBox TypeName(me) & " ended"
    End Sub

    Now, every time the Set obj = Nothing statement is executed, the following message will be displayed:

    using-classes-img-1

  7. Invoking (calling) a class method or property is done as follows:
    'Declare variables
    Dim obj, var 
    'Calling MyPublicFunction
    obj.MyPublicFunction("Hello") 
    'Retrieving the value of m_sMyPrivateString
    var = obj.MyPrivateString 
    'Setting the value of m_sMyPrivateString
    obj.MyPrivateString = "My String"

    Note that the usage of the public members is done by using the syntax obj.<method or property name>, where obj is the variable holding the reference to the object of class. The dot operator (.) after the variable identifier provides access to the public members of the class. Private members can be called only by other members of the class, and this is done like any other regular function call.

  8. VBScript supports classes with a default behavior. To utilize this feature, we need to define a single default method or property that will be invoked every time an object of the class is referred to, without specifying which method or property to call. For example, if we define the public method MyPublicFunction as default:
    Public Default Function MyPublicFunction(ByVal str)
    MsgBox TypeName(me) & " – Public Func: " & str
    MyPublicFunction = 0
    End Function

    Now, the following statements would invoke the MyPublicFunction method implicitly:

    Set obj = New MyFirstClass 
    obj("Hello")

    This is exactly the same as if we called the MyPublicFunction method explicitly:

    Set obj = New MyFirstClass 
    obj.MyPublicFunction("Hello")

    Contrary to the usual standard for such functions, a default method or property must be explicitly defined as public.

  9. Now, we will see how to add a constructor-like function. When using classes stored in function libraries, UFT (know as QTP in previous versions), cannot create an object using the New operator inside a test Action.

    In general, the reason is linked to the fact that UFT uses a wrapper on top of WSH, which actually executes the VBScript (VBS 5.6) code. Therefore, in order to create instances of such a custom class, we need to use a kind of constructor function that will perform the New operation from the proper memory namespace. Add the following generic constructor to your function library:

    Function Constructor(ByVal sClass)
    Dim obj
    On Error Resume Next
    'Get instance of sClass
    Execute "Set obj = New [" & sClass & "]"
    If Err.Number <> 0 Then
       Set obj = Nothing  
       Reporter.ReportEvent micFail, "Constructor", "Failed 
         to create an instance of class '" & sClass & "'." End If Set Constructor = obj End Function

    We will then instantiate the object from the UFT Action, as follows:

    Set obj = Constructor("MyFirstClass")

    Consequently, use the object reference in the same fashion as seen in the previous line of code:

    obj.MyPublicFunction("Hello")

How it works...

As mentioned earlier, using the internal public fields, methods, subroutines, and properties is done using a variable followed by the dot operator and the relevant identifier (for example, the function name).

As to the constructor, it accepts a string with the name of a class as an argument, and attempts to create an instance of the given class. By using the Execute command (which performs any string containing valid VBScript syntax), it tries to set the variable obj with a new reference to an instance of sClass. Hence, we can handle any custom class with this function. If the class cannot be instantiated (for instance, because the string passed to the function is faulty, the function library is not associated to the test, or there is a syntax error in the function library), then an error would arise, which is gracefully handled by using the error-handling mechanism, leading to the function returning nothing. Otherwise, the function will return a valid reference to the newly created object.

See also

The following articles at www.advancedqtp.com are part of a wider collection, which also discuss classes and code design in depth:

Implementing a simple search class

In this recipe, we will see how to create a class that can be used to execute a search on Google.

Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime

Getting ready

From the File menu, navigate to New | Test, and name the new test SimpleSearch. Then create a new function library by navigating to New | Function Library, or use the Alt + Shift + N shortcut. Name the new function library cls.Google.vbs and associate it with your test.

How to do it...

Proceed with the following steps:

  1. Define an environment variable as OPEN_URL.
  2. Insert the following code in the new library:
    Class GoogleSearch
    Public Function DoSearch(ByVal sQuery)
       With me.Page_
         .WebEdit("name:=q").Set sQuery
         .WebButton("html id:=gbqfba").Click
       End With
       me.Browser_.Sync  
       If me.Results.WaitProperty("visible", 1, 10000) Then
         DoSearch = GetNumResults()
       Else
         DoSearch = 0
         Reporter.ReportEvent micFail, TypeName(Me), 
           "Search did not retrieve results until timeout"    End If End Function Public Function GetNumResults()    Dim tmpStr    tmpStr = me.Results.GetROProperty("innertext")    tmpStr = Split(tmpStr, " ")    GetNumResults = CLng(tmpStr(1)) 'Assumes the number
         is always in the second entry End Function Public Property Get Browser_()    Set Browser_ = Browser(me.Title) End Property Public Property Get Page_()    Set Page_ = me.Browser_.Page(me.Title) End Property Public Property Get Results()    Set Results = me.Page_.WebElement(me.ResultsId) End Property Public Property Get ResultsId()    ResultsId = "html id:=resultStats" End Property Public Property Get Title()    Title = "title:=.*Google.*" End Property Private Sub Class_Initialize    If Not me.Browser_.Exist(0) Then      SystemUtil.Run "iexplore.exe",
           Environment("OPEN_URL")      Reporter.Filter = rfEnableErrorsOnly      While Not Browser_.Exist(0)        Wait 0, 50      Wend      Reporter.Filter = rfEnableAll      Reporter.ReportEvent micDone, TypeName(Me),
           "Opened browser"    Else      Reporter.ReportEvent micDone, TypeName(Me),
           "Browser was already open"    End If End Sub Private Sub Class_Terminate    If me.Browser_.Exist(0) Then      me.Browser_.Close      Reporter.Filter = rfEnableErrorsOnly      While me.Browser_.Exist(0)        wait 0, 50      Wend      Reporter.Filter = rfEnableAll      Reporter.ReportEvent micDone, TypeName(Me),
           "Closed browser"    End If End Sub End Class

  3. In Action, write the following code:
    Dim oGoogleSearch
    Dim oListResults
    Dim oDicSearches
    Dim iNumResults
    Dim sMaxResults
    Dim iMaxResults
    '--- Create these objects only in the first iteration
    If Not LCase(TypeName(oListResults)) = "arraylist" Then
    Set oListResults = 
       CreateObject("System.Collections.ArrayList") End If If Not LCase(TypeName(oDicSearches)) = "Dictionary" Then Set oDicSearches = CreateObject("Scripting.Dictionary") End If '--- Get a fresh instance of GoogleSearch Set oGoogleSearch = GetGoogleSearch() '--- Get search term from the DataTable for each action
    iteration sToSearch = DataTable("Query", dtLocalSheet) iNumResults = oGoogleSearch.DoSearch(sToSearch) '--- Store the results of the current iteration '--- Store the number of results oListResults.Add iNumResults '--- Store the search term attached to the number of
    results as key (if not exists) If Not oDicSearches.Exists(iNumResults) Then oDicSearches.Add iNumResults, sToSearch End If 'Last iteration (assuming we always run on all rows), so
    perform the comparison between the different searches If CInt(Environment("ActionIteration")) =
    DataTable.LocalSheet.GetRowCount Then 'Sort the results ascending oListResults.Sort 'Get the last item which is the largest iMaxResults = oListResults.item(oListResults.Count-1) 'Print to the Output pane for debugging Print iMaxResults 'Get the search text which got the most results sMaxResults = oDicSearches(iMaxResults) 'Report result Reporter.ReportEvent micDone, "Max search", sMaxResults
       & " got " & iMaxResults 'Dispose of the objects used Set oListResults = Nothing Set oDicSearches = Nothing Set oGoogleSearch = Nothing End If

  4. In the local datasheet, create a parameter named Query and enter several values to be used in the test as search terms.
  5. Next, from the UFT home page navigate to View | Test Flow, and then right-click with the mouse on the Action component in the graphic display, then select Action Call Properties and set the Action to run on all rows.

How it works...

The Action takes care to preserve the data collected through the iterations in the array list oListResults and the dictionary oDicSearches. It checks if it reaches the last iteration after each search is done. Upon reaching the last iteration, it analyses the data to decide which term yielded the most results. A more detailed description of the workings of the code can be seen as follows.

First, we create an instance of the GoogleSearch class, and the Class_Initialize subroutine automatically checks if the browser is not already open. If not open, Class_Initialize opens it with the SystemUtil.Run command and waits until it is open at the web address defined in Environment("OPEN_URL").

The Title property always returns the value of the Descriptive Programming (DP) value required to identify the Google browser and page.

The Browser_, Page_, and Results properties always return a reference to the Google browser, page, and WebElement respectively, which hold the text with the search results.

After the browser is open, we retrieve the search term from the local DataTable parameter Query and call the GoogleSearch DoSearch method with the search term string as parameter. The DoSearch method returns a value with the number of results, which are given by the internal method GetNumResults.

In the Action, we store the number itself and add to the dictionary, an entry with this number as the key and the search term as the value.

When the last iteration is reached, an analysis of the results is automatically done by invoking the Sort method of oListResults ArrayList, getting the last item (the greatest), and then retrieving the search term associated with this number from the dictionary; it reports the result.

At last, we dispose off all the objects used, and then the Class_Terminate subroutine automatically checks if the browser is open. If open, then the Class_Terminate subroutine closes the browser.

Implementing a generic Login class

In this recipe, we will see how to implement a generic Login class. The class captures both, the GUI structure and the processes that are common to all applications with regard to their user access module. It is agnostic to the particular object classes, their technologies, and other identification properties. The class shown here implements the command wrapper design pattern, as it encapsulates a process (Login) with the main default method (Run).

Getting ready

You can use the same function library cls.Google.vbs as in the previous recipe Implementing a simple search class, or create a new one (for instance, cls.Login.vbs) and associate it with your test.

How to do it...

  1. In the function library, we will write the following code to define the class Login:
    Class Login
    Private m_wndContainer 'Such as a Browser, Window, 
       SwfWindow Private m_wndLoginForm 'Such as a Page, Dialog,
       SwfWindow Private m_txtUsername 'Such as a WebEdit, WinEdit,
       SwfEdit Private m_txtIdField 'Such as a WebEdit, WinEdit,
       SwfEdit Private m_txtPassword 'Such as a WebEdit, WinEdit,
       SwfEdit Private m_chkRemember 'Such as a WebCheckbox,
       WinCheckbox, SwfCheckbox Private m_btnLogin   'Such as a WebEdit, WinEdit,
       SwfEdit End Class

    These fields define the test objects, which are required for any Login class, and the following fields are used to keep runtime data for the report:

    Public Status 'As Integer
    Public Info 'As String

    The Run function is defined as a Default method that accepts a Dictionary as argument. This way, we can pass a set of named arguments, some of which are optional, such as timeout.

    Public Default Function Run(ByVal ArgsDic)
       'Check if the timeout parameter was passed, if not 
         assign it 10 seconds    If Not ArgsDic.Exists("timeout") Then ArgsDic.Add
         "timeout", 10    'Check if the client window exists    If Not me.Container.Exist(ArgsDic("timeout")) Then      me.Status = micFail      me.Info   = "Failed to detect login
           browser/dialog/window."      Exit Function    End If    'Set the Username    me.Username.Set ArgsDic("Username")    'If the login form has an additional mandatory field    If me.IdField.Exist(ArgsDic("timeout")) And
         ArgsDic.Exists("IdField") Then      me.IdField.Set ArgsDic("IdField")    End If    'Set the password    me.Password.SetSecure ArgsDic("Password")    'It is a common practice that Login forms have a
         checkbox to keep the user logged-in if set ON    If me.Remember.Exist(ArgsDic("timeout")) And
         ArgsDic.Exists("Remember") Then      me.Remember.Set ArgsDic("Remember")    End If    me.LoginButton.Click End Function

    The Run method actually performs the login procedure, setting the username and password, as well as checking or unchecking the Remember Me or Keep me Logged In checkbox according to the argument passed with the ArgsDic dictionary.

    The Initialize method accepts Dictionary just like the Run method. However, in this case, we pass the actual TOs with which we wish to perform the login procedure. This way, we can actually utilize the class for any Login form, whatever the technology used to develop it. We can say that the class is technology agnostic. The parent client dialog/browser/window of the objects is retrieved using the GetTOProperty("parent") statement:

    Function Initialize(ByVal ArgsDic)
       Set m_txtUsername = ArgsDic("Username")
       Set m_txtIdField = ArgsDic("IdField")
       Set m_txtPassword = ArgsDic("Password")
       Set m_btnLogin   = ArgsDic("LoginButton")
       Set m_chkRemember = ArgsDic("Remember")
       'Get Parents
       Set m_wndLoginForm = 
         me.Username.GetTOProperty("parent")    Set m_wndContainer =
         me.LoginForm.GetTOProperty("parent") End Function

    In addition, here you can see the following properties used in the class for better readability:

    Property Get Container()
       Set Container = m_wndContainer
    End Property
    Property Get LoginForm()
       Set LoginForm = m_wndLoginForm
    End Property
    Property Get Username()
       Set Username = m_txtUsername
    End Property
    Property Get IdField()
       Set IdField = m_txtIdField
    End Property
    Property Get Password()
       Set Password = m_txtPassword
    End Property
    Property Get Remember()
       Set Remember = m_chkRemember
    End Property
    Property Get LoginButton()
     Set LoginButton = m_btnLogin
    End Property
    Private Sub Class_Initialize()
       'TODO: Additional initialization code here
    End Sub
    Private Sub Class_Terminate()
       'TODO: Additional finalization code here
    End Sub

    We will also add a custom function to override the WinEdit and WinEditor Type methods:

    Function WinEditSet(ByRef obj, ByVal str)
    obj.Type str
    End Function

    This way, no matter which technology the textbox belongs to, the Set method will work seamlessly.

  2. To actually test the Login class, write the following code in the Test Action (this time we assume that the Login form was already opened by another procedure):
    Dim ArgsDic, oLogin 
    'Register the set method for the WinEdit and WinEditor
    RegisterUserFunc "WinEdit", "WinEditSet", "Set"
    RegisterUserFunc "WinEditor", "WinEditSet", "Set"
    'Create a Dictionary object
    Set ArgsDic = CreateObject("Scripting.Dictionary")
    'Create a Login object
    Set oLogin = New Login
    'Add the test objects to the Dictionary
    With ArgsDic
    .Add "Username", 
       Browser("Gmail").Page("Gmail").WebEdit("txtUsername") .Add "Password",
       Browser("Gmail").Page("Gmail").WebEdit("txtPassword") .Add "Remember",
       Browser("Gmail").Page("Gmail")
       .WebCheckbox("chkRemember") .Add "LoginButton",
       Browser("Gmail").Page("Gmail").WebButton("btnLogin") End With 'Initialize the Login class oLogin.Initialize(ArgsDic) 'Initialize the dictionary to pass the arguments to the
    login ArgsDic.RemoveAll With ArgsDic .Add "Username", "myuser" .Add "Password", "myencriptedpassword" .Add "Remember", "OFF" End With 'Login oLogin.Run(ArgsDic) 'or: oLogin(ArgsDic) 'Report result Reporter.ReportEvent oLogin.Status, "Login", "Ended with "
    & GetStatusText(oLogin.Status) & "." & vbNewLine &
    oStatus.Info 'Dispose of the objects Set oLogin = Nothing Set ArgsDic = Nothing

How it works...

Here we will not delve into the parts of the code already explained in the Implementing a simple search class recipe. Let's see what we did in this recipe:

  • We registered the custom function WinEditSet to the WinEdit and WinEditor TO classes using RegisterUserFunc. As discussed previously, this will make every call to the method set to be rerouted to our custom function, resulting in applying the correct method to the Standard Windows text fields.
  • Next, we created the objects we need, a Dictionary object and a Login object.
  • Then, we added the required test objects to Dictionary, and then invoked its Initialize method, passing the Dictionary as the argument.
  • We cleared Dictionary and then added to it the values needed for actually executing the login (Username, Password, and the whether to remember the user or keep logged in checkboxes usually used in Login forms).
  • We called the Run method for the Login class with the newly populated Dictionary.
  • Later, we reported the result by taking the Status and Info public fields from the oLogin object.
  • At the end of the script, we unregistered the custom function from all classes in the environment (StdWin in this case).

Implementing function pointers

What is a function pointer? A function pointer is a variable that stores the memory address of a block of code that is programmed to fulfill a specific function. Function pointers are useful to avoid complex switch case structures. Instead, they support direct access in runtime to previously loaded functions or class methods. This enables the construction of callback functions. A callback is, in essence, an executable code that is passed as an argument to a function. This enables more generic coding, by having lower-level modules calling higher-level functions or subroutines.

This recipe will describe how to implement function pointers in VBScript, a scripting language that does not natively support the usage of pointers.

Getting ready

Create a new function library (for instance, cls.FunctionPointers.vbs) and associate it with your test.

How to do it...

  1. Write the following code in the function library:
    Class WebEditSet
       Public Default Function Run(ByRef obj, ByVal sText)
           On Error Resume Next
            Run = 1 'micFail (pessimistic initialization)
           Select Case True
               Case   obj.Exist(0) And _
                       obj.GetROProperty("visible") And _
                       obj.GetROProperty("enabled")          
                       'Perform the set operation
                       obj.Set(sText)                  
               Case Else
                   Reporter.ReportEvent micWarning, 
                     TypeName(me), "Object not available."              Exit Function        End Select        If Err.Number = 0 Then            Run = 0 'micPass        End If    End Function End Class

  2. Write the following code in Action:
    Dim pFunctiontion
    Set pFunctiontion = New WebEditSet
    Reporter.ReportEvent 
    pFunctiontion(Browser("Google").Page("Google")
    .WebEdit("q"), "UFT"), "Set the Google Search WebEdit",
    "Done"

How it works...

The WebEditSet class actually implements the command wrapper design pattern (refer to also the Implementing a generic Login class recipe). This recipe also demonstrates an alternative way of overriding any native UFT TO method without recurring to the RegisterUserFunc method.

First, we create an instance of the WebEditSet class and set the reference to our pFunctiontion variable. Note that the Run method of WebEditSet is declared as a default function, so we can invoke its execution by merely referring to the object reference, as is done with the statement pFunctiontion in the last line of code in the How to do it… section. This way, pFunctiontion actually functions as if it were a function pointer. Let us take a close look at the following line of code, beginning with Reporter.ReportEvent:

Reporter.ReportEvent 
pFunc(Browser("Google").Page("Google").WebEdit("q"), "UFT"),
"Set the Google Search WebEdit", "Done"

We call the ReportEvent method of Reporter, and as its first parameter, instead of a status constant such as micPass or micFail, we pass pFunctiontion and the arguments accepted by the Run method (the target TO and its parameter, a string). This way of using the function pointer actually implements a kind of callback. The value returned by the Run method of WebEditSet will determine whether UFT will report a success or failure in regard to the Set operation. It will return through the call invoked by accessing the function pointer.

See also

The following articles are part of a wider collection at www.advancedqtp.com, which also discusses function pointers in depth:

  • An article by Meir Bar-Tal at http://www.advancedqtp.com/ function-pointers-in-vb-script-revised
  • An article by Meir Bar-Tal at http://www.advancedqtp.com/using-to-custom-property-as-function-pointer

Summary

In this article, we learned how to implement a general class; basic concepts and the syntax required by VBScript to implement a class. Then we saw how to implement a simple class that can be used to execute a search on Google and a generic Login class. We also saw how to implement function pointers in VBScript along with various links to the articles that discusses function pointers.

Resources for Article:


Further resources on this subject: