Let’s suppose we have a function called GetProperty, which we would like to register to all objects available to us. Now, if we do it manually, it can be quite time-consuming since any sort of AUT has many objects, and if you’re working in an environment where multiple technologies are involved, this can even get a little boring. Now, though, there is a simple way of register all our objects to the function by simply calling the method RegisterUserFuncX.
Before we see how the method RegisterUserFuncX works, let’s create a function GetProperty function, which we will first manually register to the objects in our multi-technology (Standard Windows, Web, Siebel) AUT:
Function GetProperty(Object) GetProperty = Object.GetTOProperty("micclass") End Function
'Web RegisterUserFunc "Link", "GetProperty", "GetProperty" RegisterUserFunc "WebEdit", "GetProperty", "GetProperty" 'Standard Windows RegisterUserFunc "WinEditor", "GetProperty", "GetProperty" 'Siebel RegisterUserFunc "SiebList", "GetProperty", "GetProperty"
Now, this is just an example. There are obviously many more objects I would have to register the function with. However, instead of doing this manually, I can simply use the below method and register any given function to all objects automatically:
Function RegisterUserFuncX(TOMethodName, FunctionName) Dim oRegistry, arrSubKeys, sSubKey, sKeyPath Const HKEY_LOCAL_MACHINE = &H80000002 sKeyPath = "SOFTWARE\MERCURY INTERACTIVE\QuickTest Professional\MicTest\Test Objects" Set oRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\." &_ "\root\default:StdRegProv") oRegistry.EnumKey HKEY_LOCAL_MACHINE, sKeyPath, arrSubKeys For Each sSubKey In arrSubKeys RegisterUserFunc sSubKey, TOMethodName, FunctionName Next Set oRegistry = Nothing End Function
If we have to associate all objects in our AUT to the custom function, we would just call the above method once to do our job:
Call RegisterUserFuncX("GetProperty", "GetProperty")
This is the equivalent of registering the GetProperty method to all objects manually – which requires writing many individual RegisterUserFunc statements. The concept behind this method is that in the following folder of our Registry (regedit), we have all the objects stored:
HKEY_LOCAL_MACHINE\SOFTWARE\MERCURY INTERACTIVE\QuickTest Professional\MicTest\Test Objects
Therefore, instead of registering single object classes to our function, we can use the method RegisterUserFuncX and register any given function to all objects at once. The above function can also be tweaked to only register Web Objects, or Windows, or objects of an environment of your choice. This would involve manipulating the For..Each loop a bit:
'Register all the Web Objects For Each sSubKey In arrSubKeys If InStr(1, sSubKey, "Web") > 0 Then RegisterUserFunc sSubKey, TOMethodName, FunctionName End If Next
Limitations
- This technique doesn’t well as its supposed to in terms of Siebel Objects (See Tarun’s comment here). This is because the Siebel Objects in the Registry are named differently as opposed to how the Object Spy identifies them. Objects in the Registry are named as “Sbl..” as opposed to “Sieb..”, which is the main reason for this shortcoming.
The above limitation has been resolved: Certain objects are available in QTP’s
DATfolder, and by modifying the actual code in this post for XMLs, all objects can still be registered easily to custom methods. Credits go to Motti for reporting this resolution. - Another limitation of this approach is due to the dynamically executing RegisterUserFunc statements, which end up in the lack of Intellisense during test-design. This can be overcome by using RegisterUserFuncX to print all the necessary RegisterUserFunc statements and pasting the output to our libraries. Full credit goes to Tarun for helping us find this limitation.
I hope this helps. Thanks for visiting Relevant Codes :)
FaceBook
LinkedIn
Twitter
YouTube
{ 1 trackback }
{ 11 comments… read them below or add one }
Hi Anshoo,
I just started QTP learning and read the whole QTP unplugged book by Tarun Lalwani, but this concept is not there in the book. It is a very useful way to register custom function for all objects.
I have one question:
Could you please let me know in real-time what could be the scenario where we want to acheive some thing like this..
I have a few methods that need to be registered to all the objects I work with. One of these methods will be released sometime next week. Once that is out and if you get a chance to read about it, you will realize that its something that needs to be registered for all objects regardless of the environment/technology of the AUT. This custom function is mainly for such uses.
I didn’t want you to wait until next week, so here it is: http://relevantcodes.com/getroproperties-custom/
:)
Well we have a similar issue in our BPT project where we had to write multiple statements of RegisterUserFunc to associated functions. But there are few issues with this approach
- Since all the statements use RegisterUserFunc dynamically the intellisense doesn’t pickup the new function. In case of Keyword BPT components it becomes impossible to use this
- The object name that you enumerate will not have correct names for Siebel objects. I don’t why this happens but there is a mismatch in case of Siebel
- The approach should included a filter by name. I included a name filter like Win* which will only register it for Win objects
To overcome these issue instead of registering the functions at run-time we generate all the RegisterUserFunc lines using this approach and paste it in our code
Thank you, Tarun. Your advice is always helpful..
+ I should have addressed the issues with Siebel objects. I was completely aware of it, but I don’t know how I missed it. The objects in Registry are named as “Sbl..” instead of “Sieb..”, which is what causes such behavior. I will update the post giving full credit to your comment as soon as possible.
+ Spot on about Intellisense as well.
I think the fair thing to do with this approach would be to limit this approach to only Web and Windows environments, and let users modify the code individually for their respective applications.
First of all. Thanks very much for your useful post.
I just came across your blog and wanted to drop you a note telling you how impressed I was with the information you have posted here.
Please let me introduce you some info related to this post and I hope that it is useful for software testing community.
There is a good Software Testing resource site, Have alook
http://SoftwareTestingNet.com
simi
Thank you, Simi. I saw your website, it contains a lot of useful information other than test automation. I’m sure its helping a lot of readers. Good luck, and thanks again.
Very cool idea, however the Siebel limitation is not entirely correct, for Siebel there are two flavours of test objects, objects called Sbl* use QTP’s internal support for Siebel applications before 7.7 and Sieb* use the STA API, these objects are defined by Siebel dynamically and are therefore not stored in the registry (you can find them in
QTP\dat\SiebelObjects.xml).More interestingly (to my mind) is that you’ll have the same problem for all test objects that are not defined in QTP proper, for example objects defined by extensibility (either Web or Java) do not appear in the registry but in xml configuration files.
Thanks for sharing this, Motti. I completely skipped over the Data folders. I will update the article with this information, citing your comment as the source. :)
Hi,
can u explain Functional decomposation frame work .
Functional Decomposition? Any alias to this name? I haven’t heard (or read) about it before..