RegisterUserFuncX: Register Methods To All QTP Objects Automatically

by Anshoo Arora ON December 8, 2009 · Posted In All, QTP · 36 comments

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. See Tarun’s comment here.

Subscribe to Relevant Codes (by Anshoo Arora)

Hello! We're always posting interesting articles on Relevant Codes. Why not subscribe so you don't miss out?

Leave a Comment

{ 35 comments… read them below or add one }

ravi May 2, 2012 at 6:15 am

i just wanted to know when to use this registerUserFunc . at what situations the usage will come in to picture. can u pls help me out.
Thanks in Advance.

Reply

Anshoo Arora May 2, 2012 at 2:08 pm

Ravi, just quoting the help-file:

Enables you to add new methods to test object classes or change the behavior of an existing test object method during a run session.

Sub Copy (edit)
    Edit.Click 3, 3
    Edit.SetSelection 0, Len(Edit.GetROProperty("text"))
    Edit.Type micCtrlDwn + "c" + micCtrlUp
End Sub

One way to call the code above:

Call Copy(Dialog("Login").WinEdit("Agent Name:"))

Using RegisterUserFunc:

RegisterUserFunc "WinEdit", "Copy", "Copy" 

Dialog("Login").WinEdit("Agent Name:").Copy

You’re simply adding a new static method to the test object class.

Reply

ravi May 7, 2012 at 5:24 am

Thanks a lot Anshoo…

Reply

sonal March 6, 2011 at 12:29 pm

Hi,

i have one basic question. Why do we register? What is the need for registerin? When should we register?

Thx,
sonal

Reply

Tarun Lalwani October 27, 2010 at 10:01 pm

@Anand, RegisterUserFunc is only for methjods available with QTP Test Object. When you use HTML DOM you have already left the QTP world and there are no overriden functions that exists

Reply

Anand Tambey October 27, 2010 at 5:39 am

One of my colleague tried to use HTML DOM with QTP and he found that overridden function (via registeruserfunc) is not working.

For example a link object is formed by DOM and click method executed. It would not call overriden function. The reason thought by him seems appropriate – As we use micclass in registeruserfunc and micclass is not used in DOM, it will not work.

Do you know such limitations of registeruserfunc and is there any workaround?

Reply

Anshoo Arora November 14, 2010 at 5:22 pm

Hmm.. I have used DOM methods with RegisterUserFunc. Also have a few methods written on this site that use DOM methods with RegisterUserFunc. Would you like to share the method that you have written?

Reply

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

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

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

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

sriram March 4, 2010 at 3:52 am

Hi,
can u explain Functional decomposation frame work .

Reply

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Motti April 27, 2010 at 12:42 pm

Glad to help and thanks for the kind words.

Reply

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

Anshoo Arora April 28, 2010 at 2:51 am

Nice, Christian!

Reply

Dennis June 8, 2010 at 12:47 am

Anshoo,

Thank you very much for your kindness.

Reply

Anand Tambey November 15, 2010 at 2:34 am

Hi Anshoo,

Yes Anshoo, DOM object/methods could be used inside overriden function body. However DOM object itself can not call overridden function defined for that test object. Have you came across such scenario and found it working. If not,is there any workaround for such limitation?

Here is the example code where DOM object can not call overridden function:-

‘Needs OR for Google page
Function MySet (obj, sVal)

Dim sPrev

sPrev = obj.GetROProperty(“value”)

Reporter.ReportEvent micDone, “Previous Value was ” & sPrev, sPrev

MySet=obj.Set(sVal)

Reporter.ReportEvent micDone, “Set Value is ” & sVal, sVal

End Function

‘Without using overriden function – Calling default SET
Browser(“Google”).Page(“Google”).WebEdit(“q”).Set “QTP”

set pgObj = Browser(“Google”).Page(“Google”)
set txtObj = pgObj.Object.all.namedItem(“q”)

‘Defined overridden function
RegisterUserFunc “WebEdit”, “Set”, “MySet”

‘With using overridden function – Calling MySet – This will not work with DOM object – Error
txtObj.Set “Inception – Dreaming now…”

‘With using overridden function – Calling MySet – This will work with test object
Browser(“Google”).Page(“Google”).WebEdit(“q”).Set “Inception – In Real World…”

‘Undefined overridden function
UnRegisterUserFunc “WebEdit”, “Set”

Browser(“Google”).CloseAllTabs

Reply

Anshoo Arora December 5, 2010 at 9:43 pm

Anand,

Your observation is correct. But, it is to be noted that RegisterUserFunc only works for test object classes. Once you add .Object to any test object class, the class is no longer recognized as a QTP test object class. This can be tested by added “.Object” to any test object and trying to retrieve its original test class – won’t work.

Reply

{ 1 trackback }

Previous post:

Next post: