QTP is backed by a strong scripting engine, which provides many powerful features that helps us in extending the tool and its automation capabilities. QTP is designed such that it allows us to define  and automate the application with reusable code.

One of these powerful features is, “method overriding”. It is the ability to replace the methods of an object with a custom function designed to meet the specific requirement.

Object Method Overriding with RegisterUserFunc

Consider a case where it is required to automate that upon clicking a button, the status is checked – before and after clicking the button. If the requirement is to be performed on the click operation for all the buttons object, we need to have a solution where we can override the click method, in which we can specify to check the status of button before and after clicking the button ELSE we need to write the same piece of code for all the objects every time. There could be other requirements as well, like you need to report all the steps performed, into result or you want to change completely the way an existing method works. You might have some cases where you want to define a method for an extended object (using Extensibility accelerator).

Let’s consider an example

Before setting a value to the text input box, it is required that the text box needs to enabled and cleared out.  Let’s  take the Search box on Google where we need to perform below steps

  • check for existence and the status of text box.
  • Clear the existing data from text box if any.
  • Set the value

The approach which we will usually take here, would be as below

If Browser("Google").Page("Google").WebEdit("Search").Exist Then
Reporter.ReportEvent micPass,"Search Box","1. Search Box Exists."

Browser("Google").Page("Google").WebEdit("Search").Click
Browser("Google").Page("Google").WebEdit("Search").Set ""
Reporter.ReportEvent micPass,"Search Box","2. Search Box Cleared."

Browser("Google").Page("Google").WebEdit("Search").Set "LearnQTP"
Reporter.ReportEvent micPass,"Search Box","3. Value is Set in Search Box."

Else
Reporter.ReportEvent micFail,"Search Box","Search Box Does Not Exist."
End If

Looks good!! but this is good only if you have do this for one or two objects. Scripting will be worse if you have to repeat the same for all the similar objects in the application. No one wants to write a huge code and put efforts into writing repetitive statements. Can you think of any other way or the best viable solution here?

What if we can replace the object method itself here, let’s say we want to replace behavior of ‘Set’ method for WebEdit object and instruct it do all the required steps mentioned above before doing the actual Set operation. Seems difficult, right? QTP makes it really very simple. It has a built-in function known as RegisterUserFunc, which registers user-defined function or procedure as a method of specified Test Object class.

You need to create a custom function to implement the required steps including the original method and override the method of object class with it in a RegisterUserFunc statement. This function temporarily replaces the method definition with the custom function. As soon as QTP triggers the subjected method, the custom function gets called and the statements within it are performed.

RegisterUserFunc TestObjectClass(string), MethodName(string), FunctionName(string), [optional]SetAsDefault(boolean)

Where
TestObjectClass is the Object with which you want to register the method. e.g: WebEdit, WebButton etc
MethodName is the name that you want to use while calling the method. e.g: For a WebEdit, it can be Set
FunctionName is the actual name of the user-defined function, i.e. the name that is used during function definition. e.g SetEdit for Set
SetAsDefault indicates whether the registered function is used as the default operation for the test object. Default Value: False

RegisterUserFunc statement should be executed at the beginning of your test run, so that it can override the methods from the beginning. To avoid confusion on where to put the statement, it is recommended to keep it in a library file and associate it with the test.

It is now very simple to accomplish the above task. We just need to create a custom function which will include all the required steps. In the example above, the main objective of the step is to set a value in the text box, which is being done by using SET method of WebEdit object. We need to add few more steps before we actually go to the primary one (SET). So, here we will replace or override the SET method with our user defined function, lets say we name it as SetSearchText and put the statements for the required steps as shown below.

Function SetSearchText()

If Browser("Google").Page("Google").WebEdit("q").Exist Then
Reporter.ReportEvent micPass,"Search Box","1. Search Box Exists."

Browser("Google").Page("Google").WebEdit("q").Click
Browser("Google").Page("Google").WebEdit("q").Set ""
Reporter.ReportEvent micPass,"Search Box","2. Search Box Cleared."

Browser("Google").Page("Google").WebEdit("q").Set "LearnQTP"
Reporter.ReportEvent micPass,"Search Box","3. Value is Set in Search Box."

Else
Reporter.ReportEvent micFail,"Search Box","Search Box Does Not Exist."
End If

End Function

If you look at the above code, you will notice that this particular Function will be applicable for one object only. This does not solve the purpose if we have to create a function every time for each instance of object. It is almost same as we were doing earlier. Basically the function should be a generic one, which can work with all instances of the object. Remember that we need to override the method completely for the object.

RegisterUserFunc provides the reference of the test object and other inputs (like value passed) to use it and implement operation. When we use RegisterUserFunc, it automatically passes the reference of the object to the user defined function. While creating your function, have an object as a parameter. If the method which you are going to override accepts an input, (e.g. WebEdit accepts a value to be passed at Set statement) in such a case, you will have to include one more parameter to the function.

So now your custom function would be

Function SetSearchText(obj, text)

If obj.Exist Then
Reporter.ReportEvent micPass,"Search Box","1. Search Box Exists."

obj.Click
obj.Set ""
Reporter.ReportEvent micPass,"Search Box","2. Search Box Cleared."

obj.Set "LearnQTP"
Reporter.ReportEvent micPass,"Search Box","3. Value is Set in Search Box."

Else
Reporter.ReportEvent micFail,"Search Box","Search Box Does Not Exist."
End If

End Function

Now you can use RegisterUserFunc statement to replace the existing method.

RegisterUserFunc "WebEdit", "SET", "SetSearchText"

Now, every time a SET method gets triggered for WebEdit, SetSearchText method will be called and QTP will perform all the steps into it. Remember that, it will work throughout your run session. At any time during the run session, it can be unregistered by using the complimentary function UnregisterUserFunc.

UnRegisterUserFunc TestObjectClass(string), MethodName(string)

Where
TestObjectClass is the Object with which you want to Unregister the method. e.g: WebEdit, WebButton etc
MethodName is the method you want to unregister.

As I mentioned earlier, while defining your function, if the function accepts an argument or parameter then your function should also accept the same along with the test object as a parameter. The point to note here is that the overriding method must have the same number of arguments that of overridden method. for example, for SET method, the correct Function definition could be

Function SetSearchText (obj, text)

but it will be incorrect if you mention it as

Function SetSearchText(obj, text, value)

In the example mentioned above for set google search text, we have seen, how RegisterUserFunc is useful to override the existing methods of object with a custom user defined function. In the next example, you will find, how RegisterUserFunc can help in implementing a new method for any test object.

Let’s consider an application with menu control. This menu is a simple HTML Control with additional behavior and functionality. Hover is one of the functionality to get the sub menu options. The requirement is in three steps

  1. Hover the Main Menu,
  2. Hover the Sub Menu ,
  3. Click Required Menu Option.

Below example use the sample site CSS3 Menu.

We will automate the menu Selection at the page “Product Info > 2.2 Installation > 2.2.1 FAQ”. These sub menu appears, when you move the mouse to the option i.e. hover. The menu options are basically the link objects.

Here the problem which you will face is that there is no hover method available for Link object. The code below will add the required method (Hover) for the object (Link).

Function Hover(obj)
x = obj.getroproperty("abs_x") + (obj.getroproperty("width"))/2
y = obj.getroproperty("abs_y") + (obj.getroproperty("height"))/2

Set devicereplay = CreateObject("Mercury.devicereplay")
devicereplay.MouseMove x, y

Set devicereplay = Nothing

Wait 1
End Function

Registeruserfunc "Link", "Hover", "Hover"

This adds the method for the object.

Method Appears in the Intellisence

Method Appears in the Intellisence

Keep the above code in a function library and associate with the test containing the sample code below.You will need to add the required objects into object repository for the example to work.

Browser("CSS3 Menu -- Elegant Dark").Page("CSS3 Menu -- Elegant Dark").Link("Product Info").Hover
Browser("CSS3 Menu -- Elegant Dark").Page("CSS3 Menu -- Elegant Dark").Link("2.2 Installation").Hover
Browser("CSS3 Menu -- Elegant Dark").Page("CSS3 Menu -- Elegant Dark").Link("2.2.1 FAQ").Click

I have tried explaining Object Method Overriding using RegisterUserFunc in as simple language as possible, I hope you have enjoyed it. Please let me know your feedback in the comments section below.