info@pragmatictesters.com +94 11 253 8512

Mastering XPath for Selenium Test Automation


Introduction

Selenium test automation engineers must be very comfortable in locating elements in web pages. XPath and CSS are very powerful location strategies used in Selenium as compared to other location strategies (id, name, link, partialLinkText, tagName etc).Mastering XPath or CSS is essential for the Selenium test automation engineers to locate dynamic web elements. It is noted that new Selenium automation engineers do not pay much attention to master location strategies. This leads to failure of test automation efforts when web pages with dynamic contents are automated. Most of the testers rely on extracting the XPaths from Firebug/Firepath like tools. The tools cannot be used directly for dynamic web elements. We will discuss XPath in detail with examples.

We have created Similar blog post for CSS too.

XPath for locating Web Elements

I have my own way of introducing  (explaining) XPath to the trainees in my training sessions.

When A=B and B=C. I ask the students what can be derived from these expressions. Immediately they reply with A=C.

Then I give following two statements

  • XPath is used for  locating the elements in XML documents
  • XML and HTML has similar syntax (HTML is an XML file)

Hence XPath can be used for locating elements in HTML pages/web pages.

Why do we need to master many XPath syntaxes


We may not be able to locate the elements directly using their unique attributes as some element do not have unique attributes. Some attributes are dynamically changed.[/box] Hence we may have to locate them differently than the static elements.

  • Locate elements with respective a known element
  • Locate elements with partial fixed attribute values
  • Locate element without attributes or without unique attributes
  • XPath can do bidirectional navigation (Going forward and backward)
  • XPath is one of most flexible and strongest location strategy

 

Types of XPath

  • Absolute XPath

Absolute XPaths starts with the root of the html pages.

Absolute XPaths are not advisable for most of the time due to following reasons

  1. Absolute XPaths are lengthier and not readable
  2. Absolute XPaths are brittle when minor structural changes are done to the web pages

Absolute XPaths shall be used only when a relative a XPath cannot be constructed. (highly unlikely). Absolute XPaths tends to break as web pages/content is changed. Hence it not recommended to use absolute XPath in Selenium.

Most of the beginners tend use absolute XPaths when they copy them from tools like FireBug. Theses XPaths are tend to break (brittle) most of the time.

Syntax: Absolute XPaths start with  /html

Example : /html/body/div[1]/div/div[2]/form/div[2]/input

  • Relative XPath

Relative XPaths is used for locating an element from a known element. The element of your choice is referred relative to a known element.

Syntax : Relative XPaths are started with two  forward slashes. //

Example : //div[@id=’divUsername’]/input

Absolute XPaths are faster than the relative XPaths

IF there are multiple elements for an XPath?


Selenium will select the first element in the path if there are multiple candidates for a given XPath. If you want to specify the location of the element square brackets with the sequence number  shall be used.

Examples :

  • To select the third input element :  //form/input[3]
  • To select the last input element :  //form/input[last()]

Locating elements by position is discussed further in a separate section

What should be considered when choosing a XPath?


It is important to consider following while choosing a XPath from available options.

A good locator is,

  • Unique
  • Descriptive
  • Unlikely to change

Sample HTML


Following simple HTML is used in most of the CSS examples in this blog post.

<html><body>

<form id=’login’>

<input name=’txtUserName’ id=’txtUsername’ type=’text’ class=’userName’ >

<input name=’txtPassword’ id=’txtPassword’ type=’password’ class=’password’ >

<input name=’submit’ id=’btnLogin’ type=’submit’ class=’button’>

</form>

</body></html>

Locating Elements with Known Attributes


Following syntax can be used for locating elements when at least one attributes are unique and static (not changed).

ffffffffff

//*[@attributeName=’value’]

Let’s consider the username field

<input id=”txtUsername” type=”text” name=”txtUsername”>

Examples :

  1. //*[@id=’txtUsername’]
  2. //*[@name=’txtUsername’]
  3. //*[@type=’text’]

Third XPath is not used even though it is a valid XPath. BUT It is not unique. There might be many elements with attribute type=’text’.

Locating Elements with known Element and Attributes

ffffffffff

//elementName[@attributeName=’value’]

Let’s consider the username element again

<input id=”txtUsername” type=”text” name=”txtUsername”>

Examples :  

  1. //input[@id=’txtUsername’]
  2. //input[@name=’txtUsername’]
  3. //input[@type=’text’]

Third option is valid but it is not unique. Hence it is discouraged to use in test scripts. There could be many elements with type=’text’.

Locating Elements with Known Visible Text (exact match)


Following syntax is used for locating elements containing some text

ffffffffff

//elementName[text()=’exact text’] or

//*[text()=’exact text’]

<a target=”_blank” href=”http://www.pragmatictestlabs.com“>Pragmatic</a>

Examples :

//a[text()=’Pragmatic’]

//*[text()=’Pragmatic’]

aaaaaaaaa  The text is case sensitive.

Locating by the visible text is not advisable if you are testing a multilingual application and same text is appearing in more than one location.

Locating Elements when part of the visible text is known (partial match)

ffffffffff

//elementName[contains(text(),’part of the text’)]

//elementName[contains(.,’part of the text’)]

//*[contains(text(),’part of the text’)]

<a target=”_blank” href=”http://www.orangehrm.com”>OrangeHRM, Inc</a>

Examples :

//a[contains(text(),’Orange’)]

//a[contains(.,’Orange’)]

//*[contains(text(),’Orange’)]

Ensure closing brackets are available.

Locating elements when starting text is known

ffffffffff

//elementName[starts-with(text(),’starting text’)] ,

Example :

//a[starts-with(text(),’Orange’)]

Locating Elements with Dynamic Attributes


Following syntax could be used when a part of the attribute values are NOT changed. We can use the non changing value for locating the element.

ffffffffff

//elementName[contains(@attributeName,’part of the value’)]

Example :

//a[contains(@href,’orangehrm.com’)]

You can use //elementName[starts-with(@attributeName,’part of the value’)]

And  //*[contains(@attributeName,’part of the value’)] too

The ends-with function is part of xpath 2.0. Browsers generally only support 1.0 at the time of this writing. Hence ends-with is not included.

Locating Elements with Attributes

ffffffffff

//*[@attributeName=’value’]

Example :

//*[@id=’txtUsername’]

Locating Elements with Multiple Attributes


Sometimes it may not be possible to locate an element with a single attribute. In real world we have similar issue. We cannot locate a person with just first name or last name. We will have to use combination of first name and last name to locate a person without any confusions.

ffffffffff

//*[attribute1=’value1’][attribute2=’value2’]…[attributeN=’valueN’]

Example :  

//*[@id=’txtUsername’][@name=’txtUsername’]

You can include the element name too

ffffffffff

//elementName[attribute1=’value1’][attribute2=’value2’]…[attributeN=’valueN’]

Example :

//input[@class=’button’][@type=’submit’][@value=’LOGIN’][@name=’Submit’]

Locating elements relative to known element


If an element of our interest do not have a unique attribute(s)/locator, we need to locate the element with respective to a known element.

We do this very well in our real life. We always give direction to a new location with respective an already known location (a landmark). Giving direction to your home from a well know shop, statue, railway station etc.

XPath has thirteen (13) different axes. We will look into a subset of useful axes in this blog post.

 XPath Axes

Figure: XPath Axes

Source : XPath Expression components. http://www.iro.umontreal.ca/~lapalme/ForestInsteadOfTheTrees/HTML/ch04s01.html

XPath Axis name Description
ancestor Parent of a known element , its parents
descendants Children of a known element, its children
following Elements after the known element
following-sibling Sibling elements after the known element

When using those axis notations make sure to have a good understanding on the DOM structure of your web page.

Locating a parent element

The parent axis contains the parent of the context node.ffffffffff//<knownXpath>/parent::* or//<knownXpath>/parent::elementName

yyyyyyXPath of the known element : //div[@id=’divUsername’]Now we can locate the parent form element with respect to the div element//div[@id=’divUsername’]/parent::form Also//div[@id=’divUsername’]/parent::*This can be written as //div[@id=’divUsername’]/..  alsoThere can be only one parent to a context (known) element. Hence specifying the element name is optional.

Locating a child element

The child axis contains the children of the context nodeffffffffff//<xpathOfKnownElement>/child::<elementName>  or//<xpathOfKnownElement>/child::*

tttttttXpath of the known element //div[@id=’divUsername’]Xpath to the child element is //div[@id=’divUsername’]/child::spanYou can use / instead of child:: from the XPath. //div[@id=’divUsername’]/span

Locating ancestors of a known element

The ancestor axis contains the ancestors of the known element ; ancestor axis consist of the parent of known element and the parent’s parent so on.ffffffffff//<xpathOfKnownElement>/ancestor::<elementName> or  //<xpathOfKnownElement>/ancestor::*

qqqqqqExamples ://input[@id=’txtUsername’]/ancestor::form//input[@id=’txtUsername’]/ancestor::*Where there are multiple elements first will be selected by Selenium.

Locating following elements

Keyword following can be used for locating an element anywhere below the tree with respect to the known element.ffffffffff//<xpathOfKnownElement>/following::<elementName> or//<xpathOfKnownElement>/following::*

dawfe//input[@id=’txtUsername’]/following::inputAny descendant elements are excluded

Locating preceding element  

Keyword preceding is used for locating an element above the tree with respect to a known (xpath) element.Example : //*[@id=’txtPassword’]/preceding::div[1]Any ancestors are excluded

Locating following sibling

Following could be used to locate the following sibling elements with respective to a known element.ffffffffff//<xpathOfKnownElement>/following-sibling::<elementName> or//<xpathOfKnownElement>/following-sibling::*

yyyyyyyyyyyyExample : //*[@id=’txtUsername’]/following-sibling::span

Locating preceding sibling

ffffffffff//<xpathOfKnownElement>/preceding-sibling::<elementName> or//<xpathOfKnownElement>/preceding-sibling::*

aaaaExample ://span[contains(text(),’Username’)]/preceding-sibling::input

Locating Optional XPaths

You may know possible (options) XPaths in advance but not sure which one will be available/correct at the time of the testing. Possible XPaths shall be separated by | character.ffffffffffXPath1|Xpath2If the first xpath is available first element is selected by Selenium for further actions. If both are available first one is Selected.Don’t keep spaces between the pipe character and the XPaths.

Locating an element by position

This can be used for locating an element explicitly when there are many elements matching the XPath.ffffffffffXpath[position] ,  Xpath[last()] ,  Xpath[last()-n] and Examples ://div[@id=’branding’]/a[2]//form/input[last()]//form/input[last()-1]For selecting an element before a given element //form/input[position()<3 ] selects first 2 input elements

Validating XPath

It is important to ensure XPath used in your automation script is valid before running the script. There are number of tools available to validate the correctness of the XPaths.

Verify using FirePath

Install Firebug on your Firefox browser. Then install FirePath which will appear as an addon to Firebug.

  • Open context menu on the web page. Select Inspect with Firepath
  • Select XPath from drop down (usually XPath is selected by Default) .
  • Type the XPath
  • Click Eval button to verify the XPath

qqqqqqqqqqqqq
Verify using FireFinder

You can use FireFinder also to verify the Xpath. Install Firebug on your Firefox browser. Then install FireFinder on your browser.

  • Open Firebug (using context menu in web page).
  • Select FireFinder tab.
  • Type the XPath
  • Click Filter button to verify the XPath
  • Matching element(s) will be displayed (if available)

lllll


Practice XPath

You can use XLab for practicing the XPath

<<We are looking for developing a XLab site with HTML>>

xPath or CSS

CSS and XPath are the most popular, widely used and powerful location strategies within the Selenium test automation community.CSS has gained wider acceptance from the test automation engineers due to following reasons. (People in favour of CSS says)

  • CSS more readable ( simpler )
  • CSS is faster (especially in IE)

Those who are in favour of XPath says about it’s ability to transverse  around the page where CSS cannot. XPath can traverse up and down the DOM. CSS can traverse only down the DOM.These claims may be already outdated :-). Some research demonstrate that there is no significant difference in speed.Mastering both of them is a good idea for the Selenium test automation engineers who wish to build their career around Selenium.It is better to a use single location strategy for a project for number of reasons.Some gurus advice hybrid approach. They use ID first and and moving to CSS. XPath is used only when it is required.

Quick Reference

XPath Description
//*[@attribute=’value’] Locating element with known attribute.
//element[@attribute=’value’] Locating element with known element and attribute.
//element[text()=’exact text’] Locating Elements with Known Visible Text (exact match)
//*[text()=’exact text’] Locating Elements with Known Visible Text (exact match)
/elementName[contains(text(),’part of the text’)] Locating Elements when part of the visible text is known (partial match)
//*[contains(text(),’part of the text’)] Locating Elements when part of the visible text is known (partial match)
//element[starts-with(text(),’starting text’)] Locating elements when starting text is known
//elementName[contains(@attributeName,’part of the value’)]
//*[contains(@attributeName,’part of the value’)]
//*[attribute1=’value1’][attribute2=’value2’]…[attributeN=’valueN’]
///parent::*
///parent::elementName
///ancestor::
///ancestor::*
///following::
///following::*
///preceding:: ///preceding::*
///following-sibling:: ///following-sibling::*
///preceding-sibling:: ///preceding-sibling::*
XPath1|Xpath2
Xpath[position] , Xpath[last()] , Xpath[last()-n]



References

[1]. Selenium Easy. 2016. XPath tutorial for Selenium | Selenium Easy. [ONLINE] Available at:https://www.seleniumeasy.com/selenium-tutorials/xpath-tutorial-for-selenium. [Accessed 25 August 2016]. 
[2]. XPath Tutorials  [ONLINE] Available at:http://www.zvon.org/xxl/XPathTutorial/General/examples.html. [Accessed 25 August 2016].
[3]. Xpath “ends-with” does not work – Stack Overflow. 2016. Xpath “ends-with” does not work – Stack Overflow. [ONLINE] Available at: http://stackoverflow.com/questions/22436789/xpath-ends-with-does-not-work. [Accessed 25 August 2016].

[4]. 4.1 XPath expression components. 2016. 4.1. XPath expression components. [ONLINE] Available at:http://www.iro.umontreal.ca/~lapalme/ForestInsteadOfTheTrees/HTML/ch04s01.html. [Accessed 25 August 2016].

Your Turn To Talk

Leave a reply:

Your email address will not be published.