Xpath Tutorial Part 2: A Practical Approach for Selenium Users

Here is the link to Part 1.

Technique #1 (Static Elements)

Scenario: Elements in a form such as a user registration or admission form.

These are elements that have constant properties such as IDs and/or names. These properties don’t change upon page refresh or on different browser sessions. They are usually not auto-generated either.

Selenium has a search by id and/or name therefore, don’t use XPath such as //input[@id=username] or //input[@name=’postalAddress’] for static elements. Searching by ID and name is faster and easier.

To make sure that an element is static you need to refresh the page few times using Ctrl-F5 to make sure the element id or name doesn’t change. If you are landed on the current web page by submitting a form (or using http post) then you need to restart the steps that got you to the page where the target element resides.

Examples:

Go to mail.yahoo.com and do an inspect element on username field. The id=username now refresh and try again. As you can see the id doesn't change so it could be used to target username field in Selenium.

<input type="text" value="" autocomplete="off" autocorrect="off" placeholder="Yahoo ID" aria-required="true" tabindex="1" maxlength="96" id="username" name="login">

Browse to http://proof.subject-7.com/zul/samplePage.zul. Inspect the box in front of “Lastname” write down the id and do a refresh and look at the id again. As you can see, the id changes each time and hence you know the element is not static.

<input type="text" value="" class="z-textbox" style="width:80%;" id="b3EQe">

Here is the HTML excerpt on page refresh:
<input id="o17Qe" style="width:80%;" class="z-textbox" value="" type="text">

Technique #2 (Menu Links)
Scenario: Menus are common structures in web pages. A menu structure usually looks like this:
<ul>
<li>
Link 1
</li>
</ul>

To get to the menu link remember that you are looking for a "Link". An XPath that targets the actual text on the screen won't really work. Here are some examples:

Sample HTML 1:
<li class="">
<a href="services.html">
<cufon>
<canvas />
<cufontext>Services</cufontext>
</cufon>
<em>
</a>
</li>

Target Element: Capture Services menu on the reference site www.subject-7.com.

Sample XPath: //*[contains(text(),'Services')]/ancestor::a
The expression works like this:

//* Find all elements
[contains(text(),'Services')] Containing the text "Services"
ancestor::a Then find an ancestor that is a link

Note how we start by a broad query and we narrow it down as we go. When you try this with Firepath make sure you get 1 match only. Most times when your XPath query matches more than one element on the page you wind up with weird behavior when running your test.

Sample HTML 2:
<li id="gn-iphone">
<a href="/iphone/" onclick="s_objectID="http://www.apple.com/iphone/_1";return this.s_oc?this.s_oc(e):true">
<span>iPhone</span>
</a>
</li>

Target Element: Capture iPhone menu on the reference site www.apple.com
Sample XPath:. //*[contains(text(),'iPhone')]/ancestor::a