OK, you don’t have ids on the controls you need to access. Now what do you do. I was faced with this situation. I needed to verify that one menu item followed another. Neither of the menu items had an id. I could simply use indicies on the links. That would have made for a very brittle test (one that breaks easily). I happened to notice that the parent cell (TD) had a unique class (sideNav). If I could associate my test with that cell, it would be a bit more stable.
Within the cell was a list structure (UL), with each list item (LI) followed by a link that contained text. I was supposed to make sure that the link with text of “Item-of-Interest” was followed by the link with the text “Following-Item”. The structure of this list was very regular: list item followed by a link, followed by text, followed by the next list item.
<TD class=sideNav>
<UL>
<LI>
<A>
#text
<LI>
<A>
#text
<LI>
<A>
#text
<LI>
<A>
#text
<LI>
<A>
#text
<LI>
<A>
#text <– Item-of-Interest
<LI>
<A>
#text <– Following-Item
<LI>
<A>
#text
If I just used indicies to locate the links, an additional link to Item-of-Interest in front of the list could break the test. That is not an unusual situation on our website. In addition, using the “sideNav” class provided some additional insurance that I was testing what I thought I was testing. I decided I could locate the cell with class=sideNav, loop through the list until I found the first text I was looking for and test the next link to see that it had the “Following-Item” text. The code below is a sample of how to implement the test.
i = 1 while $br.cell(:class, "sideNav").ul(:index,1).li(:index, i).link(:index, 1).exists? if $br.cell(:class, "sideNav").ul(:index,1).li(:index, i).link(:index, 1).text =~ /Item-of-Interest/i if $br.cell(:class, "sideNav").ul(:index,1).li(:index, i + 1).link(:index, 1).exists? assert($br.cell(:class, "sideNav").ul(:index,1).li(:index, i + 1).link(:index, 1).text =~ /Following-Item/i) end end i += 1 end
The statement that begins with “while” and ends with “.exists?” is there to prevent the test from failing with an exception if the combination does not exist. I loop through the list items with an index so that once I find the first text, I will look for the “Following-Item” text at index+1. Again, I do an “exists?” test before I do the assert to keep the code from throwing an exception.
It turns out that this worked out OK for testing this condition. Although it is not the best situation, using the cell class to identify the area was better than just using indicies.
Tags: automated software testing, Ruby, software testing, Watir
January 26, 2008 at 2:15 pm
When implementing functional web testing and the html controls have unique id or name attribute, you end up writing a lot of woodo code.
With InCisif.net we created something we call the “HTML Control Naming Algorithm” that will find what can be the best unique identifier at record time.
This solve more cases but not all, then you can use the following
methods that can find any HTML control based on their tag, any attribute using regular expression. And it is not XPath.
Page.ControlBy
Page.ControlOfType
Page.ElementsByTagName
These methods also support C# lambda expression so can write yourself the C# code that describe the HTML control you are looking for.
Frederic Torres
http://www.InCisif.net
Web Testing with C# or VB.NET
February 2, 2008 at 7:57 pm
I am not sure what woodo code is. I know the way to make the most resilient tests is to have unique ids on all the controls you use.
That said, I strongly believe in using whatever tools work best for a particular situation. If this tool provides value, then use it.
Jim
April 9, 2008 at 5:31 pm
I just ran into the same issue using WatiN C# on a page that has 2 anchor links with the same name=”0″ id and I needed to retrieve the second one. im still working on getting it to work but this article helps me because it validates that other people have had this issue.