This very interesting discussion in out forums convinced me to write an article explaining my approach to automating non-unique web (and other environments) controls.
Non-unique Web Controls
If the world was perfect, our application would have unique, well named controls, all easily identifiable and immediately usable by our scripts. More often than not, though, our applications are a mess of unordered controls, with cryptic names, who are deemed non-standard by QTP. In the worst cases, we’re stuck with unnamed non-unique controls, who are only identified by their infamous Index property. And we all know that we should never ever ever trust the Index property.
Here’s an example for such a case:
First
Second
Third
Forth
While it’s absolutely clear to us which WebEdit goes with which label, QTP is completely blind to the connection between the two, and treats all the WebEdits as non-unique unrelated controls. Try to add them to your object repository, and you’ll get stuck with WebEdit, WebEdit_2, WebEdit_3, And WebEdit_4, with only the Index property to set them apart. If it were a table, we could’ve used the GetRowWithCellText and ChildItem commands to build some sort of workaround, but this structure isn’t even a proper table.
But do not despair, a solution will soon follow!
Registeration is FREE, quick and private.
You can either Register or Login if you have already registered
Other cases and environments
The example we’ve explored is relatively easy. The HTML code was clean and simple, and the path from the anchor to the target was self evident. Real world cases are usually much more complex and obscure, but the basic methodology holds:
Find an anchor, try to establish its relationship with the relevant target, track that relationship through the runtime objects, and formulate it into code.
Use that to get the target’s unique ID, and reach it with QTP.
In cases where the relationship is very tangled up (like javascript trees, for example), don’t even try using the HTML code, and go straight to tools like DebugBar, Firebug, and others.
Is this workaround unique to the Web environment? What about other environments such as .Net and Java?
Well, almost any environments which gives us access to Runtime Objects has similar hierarchical structure and properties. In .Net, for example, we can use the .Parent and .Controls properties to move up and down the application hierarchy, and the .Handle property to describe the target control in QTP (through the “hwnd” TestObject property).
And just like we have DebugBar and Firebug to help us with the HTML hierarchy, we have QTP’s built in .Net spy, as well as external open-source spy tools to help us in .Net and Java.
Actually, other environments usually allow us to accomplish ever greater goals than those described in this article: You can read our article on automating .net custom controls for a more elaborate use of the .Net runtime objects capabilities.
Posted in web


Yaron Assa




April 28th, 2009 at 11:51 am
Very cool!!
But please note that uniqueID is an IE only DOM property :(.
April 28th, 2009 at 12:54 pm
Currently only IE allows QTP to show the runtime objects, so as you say in mathematics: without loss of generality, let’s assume that the RO object has the uniqueID property :)
April 28th, 2009 at 6:16 pm
it’s just an excellent article.
i am impressed from the depth of the descriptions and examples. as well as the high level of the code snippets.
Yaron is king :)
April 29th, 2009 at 8:04 am
Nice method, although I prefer to do this with reusable functions:
(simplified:)
call getWebElementWithText(oPage, oWebelement, “first”)
call getChildObject(oWebelement, “WebEdit”, oChild)
oChild.set “1′=’1′; drop table users;”
May 13th, 2009 at 2:16 pm
Excellent tip with the uniqueID, I never used it in that way before, it was always my problem: to get the QTP object back after you found the runtime object.
Very nice, thanks!
May 13th, 2009 at 2:34 pm
By the way you could have used the parentElement method, and then use the getelementsbytagname(”INPUT”) method on the parent to get the Input regardless if he is first or second child.
May 18th, 2009 at 9:45 am
Good job
same thing i used in Web Tree control
http://rajivkumarnandvani.wordpress.com/2009/04/08/web-tree-control-vb-script-qtp/
May 26th, 2009 at 9:05 pm
Hi Yaron Assa,
I am very impressed from the depth of the descriptions and examples of your article: “Using web anchors to automate non-unique controls”.
But I am facing the problem, when I implement the approach suggested by you.
Problem:
When I am trying to identify the WebEdit box with the help of WebElement (First) using the following code:
Browser(”creationtime:=0″).Page(”micclass:=page”).WebElement(”innertext:=First”, “html tag:=SPAN”).Object.nextSibling.firstChild
Or
Browser(”creationtime:=0″).Page(”micclass:=page”).WebElement(”innertext:=First”, “html tag:=SPAN”).Object.nextSibling.lastChild
I am getting the Error:Object does not support this action:firstChild.
Kindly find the Source HTML.
First
Second
Third
Forth
‘———————————————-
Thanks!
Devendra Sharma
June 15th, 2009 at 2:03 am
Thanks for sharing this amazing technique with us, Yaron. I haven’t yet had a chance to incorporate this technique in one of our projects, but I can’t wait to!
-Anshoo
August 17th, 2009 at 1:16 pm
I am getting an error in this line in QTP 9.2
MsgBox Browser(”index:=0″).Page(”index:=0″).WebElement(”innertext:=First”, “html tag:=SPAN”).Object.nextSibling.firstchild.value
The error is:–> Object doesn’t support this property or method: ‘firstchild.value’
August 31st, 2009 at 9:00 am
Can I re-use the same snippet for clicking on an web Image?
October 28th, 2009 at 11:34 am
Hi,
The Approach presented is really great.
But I am facing the same issues as others have commented above and is as follows:
When I am trying to identify the WebEdit box with the help of WebElement (First) using the following code:
Browser(”creationtime:=0″).Page(”micclass:=page”).WebElement(”innertext:=First”, “html tag:=SPAN”).Object.nextSibling.firstChild
Or
Browser(”creationtime:=0″).Page(”micclass:=page”).WebElement(”innertext:=First”, “html tag:=SPAN”).Object.nextSibling.lastChild
I am getting the Error:Object does not support this action:firstChild
I am using QTP 10.0. Please help resolve the issue.