Relevant Codes

A Test Development Resource for HP QuickTest Professional.

RegisterUserFuncX: Register Methods To All QTP Objects Automatically

by Anshoo Arora on December 8, 2009

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

  1. 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 DAT folder, 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.

  2. 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 :)

{ 26 comments… read them below or add one }

1 Deter December 9, 2009 at 10:57 pm

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..

Reply

2 Anshoo Arora December 10, 2009 at 2:17 pm

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.

Reply

3 Anshoo Arora December 10, 2009 at 8:00 pm

I didn’t want you to wait until next week, so here it is: http://relevantcodes.com/getroproperties-custom/

:)

Reply

4 Tarun Lalwani December 11, 2009 at 9:58 pm

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

Reply

5 Anshoo Arora December 11, 2009 at 10:11 pm

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.

Reply

6 simi December 29, 2009 at 1:12 pm

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

Reply

7 Anshoo Arora January 1, 2010 at 3:21 am

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.

Reply

8 Motti January 19, 2010 at 6:42 am

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.

Reply

9 Anshoo Arora January 20, 2010 at 9:28 am

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. :)

Reply

10 sriram March 4, 2010 at 3:52 am

Hi,
can u explain Functional decomposation frame work .

Reply

11 Anshoo Arora March 4, 2010 at 7:40 pm

Functional Decomposition? Any alias to this name? I haven’t heard (or read) about it before..

Reply

12 Christian Desserich April 27, 2010 at 9:35 am

Hey Anshoo, sorry to comment on such an old post, but I had a question. To get this only to work on web objects, you said to add the “If InStr(1, sSubKey, “Web”) > 0″ code, and Tarun suggested adding filtering to the method. If you do it the “InStr” way, you get these objects:

WebArea, WebButton, WebCheckBox, WebEdit, WebElement, WebFile, WebList, WebRadio, WebRadioGroup, WebTable, WebTulip3Button, WebTulip3CheckBox, WebTulip5Area, WebXML.

However, I would think if you were wanting to register to all web objects, you would want to register to these objects (defined by QTP as web objects):

Browser, Frame, Image, Link, Page, ViewLink, WebArea, WebButton, WebCheckBox, WebEdit, WebElement, WebFile, WebList, WebRadioGroup, WebTable, WebXML

You miss registering to links, images, etc. I was wondering, if there was a more elegant way to get all the web objects, including links and images? If you added exceptions to the “filter” then you might as well just write out all the RegisterUserFunc statements by hand. I didn’t see anything in the registry that grouped the objects at first glance, but I haven’t had the experience you have had, so (shrug)…

P.S. What the heck is a WebTulip anyway?

Reply

13 Anshoo Arora April 27, 2010 at 10:18 am

Please disregard the comment above. You’re absolutely correct. Just went over the registry to see how the objects have been organized.

One way I can think of to associate all objects to a given environment is by arranging them into collections, or text/XMLs and read data from them. This would be a one time effort. Another possible path is to Motti’s comment – I haven’t been able to find XMLs for Web or Windows though.

PS. I generally do not filter by environment and run this method for all objects.

* I have just removed the above comment because it contained misleading information.

Reply

14 Anonymous April 27, 2010 at 10:56 am

I looked briefly into it, but I couldn’t find any XML file that called out the objects by environment. Maybe if I had more time I could figure something out. Anyway, for those who wish to register to Web objects only, there are really only a few:

[code=qtp]
RegisterUserFunc "Browser", "", ""
RegisterUserFunc "Frame", "", ""
RegisterUserFunc "Image", "", ""
RegisterUserFunc "Link", "", ""
RegisterUserFunc "Page", "", ""
RegisterUserFunc "ViewLink", "", ""
RegisterUserFunc "WebArea", "", ""
RegisterUserFunc "WebButton", "", ""
RegisterUserFunc "WebCheckBox", "", ""
RegisterUserFunc "WebEdit", "", ""
RegisterUserFunc "WebElement", "", ""
RegisterUserFunc "WebFile", "", ""
RegisterUserFunc "WebList", "", ""
RegisterUserFunc "WebRadioGroup", "", ""
RegisterUserFunc "WebTable", "", ""
RegisterUserFunc "WebXML", "", ""
[/code]

Reply

15 Christian Desserich April 27, 2010 at 10:59 am

Woops, that was me ^.

One a side note, what does this blog support in the comments? Obviously bbcode didn’t work.

Reply

16 Christian Desserich April 27, 2010 at 11:00 am

Ahh, it’s HTML.

RegisterUserFunc "Browser", "", ""
RegisterUserFunc "Frame", "", ""
RegisterUserFunc "Image", "", ""
RegisterUserFunc "Link", "", ""
RegisterUserFunc "Page", "", ""
RegisterUserFunc "ViewLink", "", ""
RegisterUserFunc "WebArea", "", ""
RegisterUserFunc "WebButton", "", ""
RegisterUserFunc "WebCheckBox", "", ""
RegisterUserFunc "WebEdit", "", ""
RegisterUserFunc "WebElement", "", ""
RegisterUserFunc "WebFile", "", ""
RegisterUserFunc "WebList", "", ""
RegisterUserFunc "WebRadioGroup", "", ""
RegisterUserFunc "WebTable", "", ""
RegisterUserFunc "WebXML", "", ""

Reply

17 Anshoo Arora April 27, 2010 at 11:22 am

To embed a few code words within a paragraph, I generally use ‘code’ and for formatted code snippets, I use the ‘pre’ tag (within braces). I have modified your code above within < p r e > < / p r e > tags (without spaces).

Reply

18 Motti April 27, 2010 at 12:28 pm

Each active test object which lives in the registry has a Info/Package string value, for all built in web test objects this will be WebPackage.

Regarding XML files, these are relevant for extensibility add-ins only (in this respect Sieb* objects are extensibility objects) and not for the built in packages. Please note that all this is undocumented and may change in future versions of QTP.

Reply

19 Christian Desserich April 27, 2010 at 12:34 pm

Thanks Motti. I think I should be able to do something with that. Nice blog you have. I love “The First Bug.”

Reply

20 Motti April 27, 2010 at 12:42 pm

Glad to help and thanks for the kind words.

Reply

21 Christian Desserich April 27, 2010 at 1:27 pm

Motti, thanks a bunch for the suggestion. This works to register to all Web objects:

Function WebRegisterUserFuncX(TOMethodName, FunctionName)
	Dim oRegistry, arrSubKeys, sSubKey, sKeyPath, out
	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
			oRegistry.GetStringValue HKEY_LOCAL_MACHINE, sKeyPath & "\" & sSubKey & "\Info", "package", out
			If Not IsNull(out) Then
				If out = "WebPackage" Then
					RegisterUserFunc sSubKey, TOMethodName, FunctionName
				End If
			End If
		Next
	Set oRegistry = Nothing
End Function

Reply

22 Christian Desserich April 27, 2010 at 1:30 pm

Try again:

Function WebRegisterUserFuncX(TOMethodName, FunctionName)
	Dim oRegistry, arrSubKeys, sSubKey, sKeyPath, out
	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
		oRegistry.GetStringValue HKEY_LOCAL_MACHINE, sKeyPath & "\" & sSubKey & "\Info", "package", out
		If Not IsNull(out) Then
			If out = "WebPackage" Then
				RegisterUserFunc sSubKey, TOMethodName, FunctionName
			End If
		End If
	Next

	Set oRegistry = Nothing
End Function

Reply

23 Anshoo Arora April 28, 2010 at 2:51 am

Nice, Christian!

Reply

24 Dennis June 3, 2010 at 7:15 am

Hi, Anshoo,

I want to get some further introduction for Set oRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\." &_ "\root\default:StdRegProv") . I know this is related to VBScript, even WScript.

Could you kindlly provide some?

Thank you in advance.

Regards,
Dennis

Reply

25 Anshoo Arora June 7, 2010 at 8:53 am

Dennis,

This is a concept of WMI. You can find a lot of information about WMI from Google, but this may be a pretty good starting point..

Reply

26 Dennis June 8, 2010 at 12:47 am

Anshoo,

Thank you very much for your kindness.

Reply

Leave a Comment

{ 1 trackback }

Previous post:

Next post: