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 XPaths starts with the root of the html pages.
Absolute XPaths are not advisable for most of the time due to following reasons
- Absolute XPaths are lengthier and not readable
- 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/div/div/form/div/input
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.
- To select the third input element : //form/input
- 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,
- Unlikely to change
Following simple HTML is used in most of the CSS examples in this blog post.
<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’>
Locating Elements with Known Attributes
Following syntax can be used for locating elements when at least one attributes are unique and static (not changed).
Let’s consider the username field
<input id=”txtUsername” type=”text” name=”txtUsername”>
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
Let’s consider the username element again
<input id=”txtUsername” type=”text” name=”txtUsername”>
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
//elementName[text()=’exact text’] or
<a target=”_blank” href=”http://www.pragmatictestlabs.com“>Pragmatic</a>
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)
//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>
Ensure closing brackets are available.
Locating elements when starting text is known
//elementName[starts-with(text(),’starting text’)] ,
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.
//elementName[contains(@attributeName,’part of the value’)]
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
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.
You can include the element name too
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.
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|
Locating a parent element
The parent axis contains the parent of the context node.//<knownXpath>/parent::* or//<knownXpath>/parent::elementName
XPath 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 node//<xpathOfKnownElement>/child::<elementName> or//<xpathOfKnownElement>/child::*
Xpath 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.//<xpathOfKnownElement>/ancestor::<elementName> or //<xpathOfKnownElement>/ancestor::*
Examples ://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.//<xpathOfKnownElement>/following::<elementName> or//<xpathOfKnownElement>/following::*
//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::divAny ancestors are excluded
Locating following sibling
Following could be used to locate the following sibling elements with respective to a known element.//<xpathOfKnownElement>/following-sibling::<elementName> or//<xpathOfKnownElement>/following-sibling::*
Example : //*[@id=’txtUsername’]/following-sibling::span
Locating preceding sibling
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.XPath1|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.Xpath[position] , Xpath[last()] , Xpath[last()-n] and Examples ://div[@id=’branding’]/a//form/input[last()]//form/input[last()-1]For selecting an element before a given element //form/input[position()<3 ] selects first 2 input elements
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
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)
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.
|//*[@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’)]|
|Xpath[position] , Xpath[last()] , Xpath[last()-n]|
. 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].
. XPath Tutorials [ONLINE] Available at:http://www.zvon.org/xxl/XPathTutorial/General/examples.html. [Accessed 25 August 2016].
. 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.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].