This short article complements a previous one I have published on how to Override the Object Exist Property. As previously indicated, one of the most powerful features QuickTest Professional (QTP) provides is the ability to override methods of object classes with custom functions tailored to serve specific purposes (Bar-Tal, 2008b). In this brief article we will see that it is also technically possible to add object methods, thus expanding the ways by which objects can be handled. For example, one might wish to get the background color of a row in a WebTable or ListView, or to check that if specific values are displayed, the font color and style are as expected. This is obviously very useful, since again we can gain from registering such generic functions and reusing them afterwards across tests, applications and projects.
The method for implementing such an extensibility follows the same lines outlined in Yaron Assa’s "A Fresh Look on RegisterUserFunc" (2008) and my own previous article (Bar-Tal, 2008b) in which I explained the motivation to override the objects’ Exist property.
The implementation steps are:
-
Analyze the requirement (to which object classes it’s relevant, etc.);
-
Design the solution;
-
Code the function (keep in mind that any function to be registered to an object class must get a ByRef obj argument as in the example below);
-
Test the function;
-
Register the function to the required object classes;
-
Test that it is added to the object class or classes using the QTP editor’s intellisense or by inserting a step (pressing F7 in QTP GUI during design time). Test that using the function this way works properly.
The example below shows a NotExists function that complements the Exist property overriding mentioned in Bar-Tal, 2008b. Addressing the Analyze phase suggested above, it might be questioned why one needs a separate registered function to check for object inexistence instead of using the aforementioned Exists function with a Negation (Not) command. The need is fundamental, as when one wishes to check for a Window or Browser having closed properly. Well, again the motivation stems from QTP’s weird and unreliable behavior with respect to this basic object detection functionality. I tried to use it this way (i.e., by putting a Not obj.Exists(0) statement) and actually QTP got stuck in too many cases. My conclusion so far is that since using the Exist functionality is basically for the purpose of detecting the existence of an object (i.e., that it is indeed loaded to memory), then to check for object inexistence one needs a similar mechanism to the proposed Exists, but with a reversed logic.
So, the following function emerged:
'*******************************************************************************
Public Function NotExists(ByRef obj, ByVal intTimeoutMSec)
'*******************************************************************************
'Function : NotExists
'Waits until an object is unloaded or the specified timeout expires.
'
'Comment : It’s possible to register this function to any object class using:
' RegisterUserFunc <Class>, "NotExists", "NotExists"
'
'Arguments : ByRef obj - Any Object
' ByVal intTimeoutMSec
'
'Returns : True - if object unloaded within the specified timeout.
' False - if the timeout expired.
'
'Developed By: Meir Bar-Tal
'
'Date : 14-May-2008
'
'*******************************************************************************
Dim objTimer
If Not IsNumeric(intTimeoutMSec) Then
intTimeoutMSec = Environment("DEFAULT_TIMEOUT_MSEC")
End If
'Ensure the Timeout argument is an integer (Environment vars are parsed as strings)
intTimeoutMSec = CInt(intTimeoutMSec)
Set objTimer = MercuryTimers.Timer("ObjectExistTimer")
objTimer.Start
Do
NotExists = Not obj.Exist(0)
If NotExists Then
objTimer.Stop
Exit Do
End If
Wait Environment("DEFAULT_SAMPLING_INTERVAL_SEC"), _
Environment("DEFAULT_SAMPLING_INTERVAL_MSEC")
Loop Until objTimer.ElapsedTime > intTimeoutMSec
objTimer.Stop
'*******************************************************************************
End Function
'*******************************************************************************
"Actually here the Exist property is used in a special way: an immediate response is requested every time, and the sampling interval (i.e., the delay between each time QTP checks for object existence) is controlled using Environment variables" (Bar-Tal, 2008b). As far as observed, this function works reliably and QTP does not get stuck when using the function.
As pointed out in the articles mentioned above, one great benefit of method registration is the ability to maintain code very efficiently. So, to be able to continue to use this function across tests, applications and projects without changing a single line of code, all we need to do is, taking the Browser class for example:
RegisterUserFunc "Browser", "NotExists", "NotExists"
Of course, this must be done for each object class as required.
To summarize, QTP’s RegisterUserFunc method enables also to add object methods. The case of adding an overridden version of checking for unloaded objects with the unreliable Exist property was briefly introduced and a way of implementing and registering such a method was exemplified.
Posted in Meir Bar-Tal's Blog, QTP Hacks



Meir Bar-Tal




May 31st, 2008 at 11:46 am
Hi Meir,
Thanks for posting the article.
You mention in ‘3. Code’ that the first argument, the object passed into the function, must be a byref. Isn’t this only if you plan to modify the object in some way? Otherwise it’s safer to use a byval so that unintentional modification of the object cannot affect the calling scope.
Glenn
May 31st, 2008 at 1:57 pm
Thanks for your comment, Glenn.
What you say is true, and every automation developer should certainly keep this in mind.
However:
1. I didn’t find anything explicit about this in QTP reference. However, the examples given there do not define whether the Test Object passed to the custom function should be ByVal or ByRef. Leaving it undefined makes it ByRef which is VBScript default.
2. Actually the function is registered to the object class, and there might be certain cases in which you’d very much need to manipulate the test object. For example, think about the discovery by Will Roden, posted last week in our site, about the possibility to Init a Web object after the page reloads to keep the correct reference. If the object would be passed ByVal, then no effect would be achieved on the original object.
Best Regards,
Meir
June 1st, 2008 at 11:25 pm
Very nice. Keep up the good work.
I am new to VBscript. Is there somewhere I can pick up advanced concepts? Like Dani’s book showed me how the COM APU searches the registry for the CLSID and the GUID. I would like to learn more about this and other advanced concepts. What should I be googling for? Most sites show only basic things.
June 2nd, 2008 at 10:05 am
Thanks.
You’re invited to dig in our knowledge base. There are plenty of resources on advanced design and coding techniques.
June 18th, 2008 at 5:26 am
Found something out which may be handy.
If an object does not exist, the minimum time an “obj.Exist(0)” execution will take is the “object synchronysation timeout” (found in File > Settings > Run tab).
You can change this value programmatically by using:
Setting(”DefaultTimeout”) ‘milliseconds
So I’ve found that temporarily changing this value at the start of the your “Exist” and “NotExist” functions will make it more accurate.
ie.
Public Function NotExists(ByRef obj, ByVal intTimeoutMSec)
If Not IsNumeric(intTimeoutSec) Then
intTimeoutMSec = Setting(”DefaultTimeout”)
Else
intTimeoutMSec=intTimeoutMSec + Setting(”DefaultTimeout”)
End If
vCurrDefTimeout=Setting(”DefaultTimeout”)
Setting(”DefaultTimeout”)=1000
‘—code ommitted
‘—code ommitted
‘—code ommitted
Setting(”DefaultTimeout”)=vCurrDefTimeout
End Function
June 18th, 2008 at 7:18 am
Hi Mohamed Ali,
Your comment is inaccurate.
Quote:
“The length of time (in milliseconds) to search for the object before returning a True or False value.
If an object does not exist, the minimum time an “obj.Exist(0)” execution will take is the “object synchronysation timeout” (found in File > Settings > Run tab).”
This is incorrect.
The object synchronisation timeout is used only if NO VALUE is specified (i.e., obj.Exist).
When using obj.Exist(0), it returns TRUE or FALSE immediately.
Please look again in Quicktest Professional reference.
The only thing that is correct is that it’s possible to change the Setting(”DefaultTimeout”) value during runtime.
Regards,
Meir Bar-Tal
October 7th, 2008 at 5:15 pm
Hi All,
Could you please let me know the more about timer function.
Cheers….!
Thiru
October 12th, 2008 at 10:51 am
Gladly.
The MercuryTimers object is a collection of timers. A timer enables you to delay execution or to measure time from a point in the script to another. The MercuryTimers object supports multiple timers to run at the same time. You start a timer by giving it a unique id (or string key, as above), and calling its start method. You can stop it with the stop method and get the elapsed time with the ElapsedTime property.