Saturday, March 23, 2013

3 Useful Techniques to shortening your xpath

I recently added a new feature to the WTF chrome extension to allows your to check your mapped PageObject elements by highlighting it on the screen when you click on the 'check' button.  It's a very useful tool for optimizing your css and xpath expressions.


For this blog post, I thought I'd like to take some time to go over how you can simplify your XPath web element selectors.  I'll cover simplifying CSS selectors in a future post.

If you used some sort of xpath finder tool, you'll probably realize that you'll get a very index heavy detailed xpath.  For example, the below xpath expression is the generated output of the WTF tool while mapping the git URL read only input box on this page https://github.com/wiredrive/wtframework. The below xpath is not idea since it is very brittle and highly dependent on the element's parent hierarchy.
/html/body/div/div[2]/div/div/div/div[2]/div[4]/div/span[4]/input
We'll go over 3 things you can do to shorten and make your xpath expressions more robust.

3 Useful Xpath techniques

Using '//' to do a deep find.

The '//' operator in XPath is your friend in simplifying your XPath.  The '//' will perform a deep find for the next element.  You'll find this useful for searching through things that can be many levels deep, which will let you decouple finding your element from it's parent elements.

Using contains() within a property selector

Next thing is the '[' and ']'.  Besides allowing you to select an index, it also allows you to select on any attribute of that tag.  For example "//*[@id='searchButton']" will find an element with ID search button.  In combination with the '//' operator, the '[...]' will allow you to filter down your elements quickly.

Inside the '[...]',  we have the 'contains()' xpath function.  This is a standard xpath function most browsers support, and will allow you to do a search within that element's attribute, which you can denote by using the '@' sign.

The '..' parent selector

Finally, the we have the '..' selector.  This allows you to select a parent element.  This is very useful for selecting elements that do not have unique identifiers, but are located near something that is.

For example, let's say I wanted to select this folder icon that's next to 'bin' that really has no unique properties.



But we do know that the 'bin' link next to that icon has a unique title.


A cool trick we can do here is to first do a deep find to select the link, then traverse up 2 parents so we select the the row (<tr>).  From there we can do a deep find to find the icon inside that row.

//a[@title='bin']/../..//*[contains(@class, 'mini-icon-directory')]"

Conclusion

Between those 3 techniques, you'll find you can shorten most xpath, make them easier to understand, and make them less brittle to site structure changes.

There are many other useful methods for shorting xpath.  I'd recommend reading over them to see what's available.  http://www.w3schools.com/xpath/xpath_functions.asp

2 comments:

man9ar00 said...

Good post. Some additional useful XPath techniques I use are:

(//yourXpathHere)[n]

to match element n from the result set of your XPath that has multiple matches

following-sibling, preceding-sibling to locate elements relative to another via siblings in place of or in addition to going up a parent.

and what I recently learned:

//div[div[contains(@name,'test')]]

which will find the parent/ancestor div that contains a div which has a name attribute matchin 'test'.

lostincoding said...

Nice post.
In my experience, the following techniques are also very useful:

id('anelement')//div[contains(@title,'atitle')]: search within the scope of id an id with title...

//div[contains(., 'a piece of text')] search a div whose text contains the string.

Also, instead of .. I would xpath axes such parent, preceding-sibling. I think it improves a lot readability.