Previously (Locators) we discussed the role of locators in UI automation; also discussed few of the locators’ implementation, but it would not be able to help you out when elements don’t have enough attributes or behavior and properties of elements are dynamic when attempting to locate these elements. Now, we will see some of the techniques here to locate elements in such situations. Normally we use CSS and XPath technique to locate elements when elements do not have enough attributes to make it unique over the page. In this section we will be exploring XPath in detail.
As we already know that XPath is a language based on the representation of the XML document and it provides the ability to navigate around the tree, selecting nodes using a variety of criteria. With XPath we can search elements backward and forward in the DOM hierarchy. This means that with XPath we can locate a parent element using a child element.
Selenium Webdriver provides xpath() method to locate elements using XPath.
Syntax: driver.findElement(By.xpath(“html/body/form/input”));
Following are the various ways to use xpath:
• Finding elements with absolute path
XPath absolute path refer to the very specific location of the element, considering it’s complete hierarchy in the DOM.
WebElement username = driver.findElement(By.xpath(“html/body/form/input”));
However, this strategy has limitations as it totally depends on the structure of the element on the page. If it changes, the locator will fail to locate the element.
• Finding elements with relative path
With relative path we can locate an element directly irrespective of its structure or hierarchy on the page. If multiple input elements exist on the page it will locate to the first occurrence.
WebElement username = driver.findElement(By.xpath(“//input”));
• Finding elements using index
In the previous example we used relative path to find the element on the page, but it has limitation of locating only the first occurrence. But combining the relative path strategy with index we can locate other occurrences of the element too.
WebElement password = driver.findElement(By.xpath(“//input[2[”));
In this example the index is locating the second occurrence of the input box which is password field on the login page.
• Finding elements using attributes value
Now the question is why we are using XPath strategy to find an element when element do have attribute? You might come across the situation where one attribute is not sufficient to locate an element and you need to combine other attribute(s) to create a precise match for that element.
WebElement LoginButton = driver.findElement(By.xpath(“//input[@type=’sumbit’ and @value=’Login’]”));
Performing partial match on attribute values: This is very useful for testing applications where attribute values are dynamically assigned and changed every time a page is requested. The following table explains the use of these xpath methods:
As we already know that XPath is a language based on the representation of the XML document and it provides the ability to navigate around the tree, selecting nodes using a variety of criteria. With XPath we can search elements backward and forward in the DOM hierarchy. This means that with XPath we can locate a parent element using a child element.
Selenium Webdriver provides xpath() method to locate elements using XPath.
Syntax: driver.findElement(By.xpath(“html/body/form/input”));
Following are the various ways to use xpath:
• Finding elements with absolute path
XPath absolute path refer to the very specific location of the element, considering it’s complete hierarchy in the DOM.
WebElement username = driver.findElement(By.xpath(“html/body/form/input”));
However, this strategy has limitations as it totally depends on the structure of the element on the page. If it changes, the locator will fail to locate the element.
• Finding elements with relative path
With relative path we can locate an element directly irrespective of its structure or hierarchy on the page. If multiple input elements exist on the page it will locate to the first occurrence.
WebElement username = driver.findElement(By.xpath(“//input”));
• Finding elements using index
In the previous example we used relative path to find the element on the page, but it has limitation of locating only the first occurrence. But combining the relative path strategy with index we can locate other occurrences of the element too.
WebElement password = driver.findElement(By.xpath(“//input[2[”));
In this example the index is locating the second occurrence of the input box which is password field on the login page.
• Finding elements using attributes value
Now the question is why we are using XPath strategy to find an element when element do have attribute? You might come across the situation where one attribute is not sufficient to locate an element and you need to combine other attribute(s) to create a precise match for that element.
WebElement LoginButton = driver.findElement(By.xpath(“//input[@type=’sumbit’ and @value=’Login’]”));
Performing partial match on attribute values: This is very useful for testing applications where attribute values are dynamically assigned and changed every time a page is requested. The following table explains the use of these xpath methods:
Syntax
|
Example
|
Description
|
starts-with()
|
input[starts-with(@
id,'ctrl')]
|
Starting with:
For example, if the ID of an element is ctrl_12, this will locate and
return elements with ctrl at the beginning of the ID.
|
ends-with()
|
input[ends-with(@id,'_
userName')]
|
Ending with:
For example, if the ID of an element is a_1_userName, this will
locate and return elements with _userName at the end of the ID.
|
contains()
|
Input[contains(@
id,'userName')]
|
Containing:
For example,if the ID for an element is panel_login_userName_textfield,
this will use the userNamepart in the middle to match and locate the
element.
|
• Finding elements with xpath axis
XPath axis help to locate elements based on the elements’ relationship with other elements in a document. The following table explains the use of these xpath axis methods:
Axis
|
Example
|
Description
|
ancestor
|
//td[text()='Product
1']/ancestor::table
|
Selects all ancestors
(parent, grandparent, and so on) of the current node.
|
Descendant
|
/table/
descendant::td/input
|
Selects all descendants
(children, grandchildren, and
so on) of the current node.
|
Following
|
//td[text()='Product
1']/following::tr
|
Selects everything in the document after the closing tag of the current
node.
|
following-sibling
|
//td[text()='Product
1']/following-sibling::td
|
Selects all siblings after the current node.
|
Preceding
|
//td[text()='$150']/
preceding::tr
|
Selects all nodes that appear before the current node in the document,
except ancestors, attribute nodes, and namespace nodes
|
preceding-sibling
|
//td[text()='$150']/
preceding-sibling::td
|
Selects all siblings before the current node.
|