Saturday, 23 May 2015

Finding relative elements in Selenium using XPath

Why finding the relative elements on the page is required?
Well- most of the elements on the webpage can be found using 8 methods then why do we need to find the elements with reference to other elements? There are 2 reasons for this.

  1. Sometimes developers do not provide the id for the element making it difficult to find the element. We can find the element by other methods but they will return many elements.
  2. Sometimes developers provide the id attributes but their value contains numbers. An if you write xpath or use id having numbers, you are heading to the hell. Because such id values are never reliable and fixed.
How to write XPath expressions that find the relative elements?
We can use following-sibling and preceding-sibling keywords as shown below.
In below image, we have input box with name as "q". Yes, we can use xpath directly in this case. But consider a scenario where you do not have name attribute or the textbox attributes are changing at run time. 
In that case, you have a very robust method to find out the textbox using label next to it. There is a rare possibility that label for the textbox will change. So how to write xpath now? We can use following-sibling keyword as shown below. So even if the position of the textbox changes tomorrow, below xpath will be able to find that easily.

//td[contains(text(),'Name')]//following-sibling::td//input























Or other way around, We can find the label of the textbox using below xpath.

//input[@name='q']//parent::td//preceding-sibling::td

More xpath expressions are given below.

  1. //th[contains(text(),'Example')]//following-sibling::th//text()
  2. //span[text()='abc']//parent::td//following-sibling::td
  3. //input[contains(@value,'Google')]
  4. //span[text()='Contents']//preceding-sibling::input
  5. //a[contains(@id,'xyz')]
  6. (//span[text()='" + key + "']//parent::td//following-sibling::td//span)[1]
  7. //span[text()='Exp Date']//ancestor::td
  8. //span[text()='Exp Date']//ancestor::td//preceding-sibling::td
  9. //span[text()='Exp Date']//ancestor::td[1]//preceding-sibling::td
  10. (//a[contains(@id,'xyz')])[2]
Another example to understand the relative element concept is given below.

On below url, we have a table with update button in each row.
http://www.softpost.org/selenium-test-page/

Imagine that you have a requirement where in you have to click on Update button for a given Employee Id. So if you are asked to click on Update button for Employee with Id 142, it should click on second update button. Ordinary developer will use the copy and paste the XPATH for second button. But we have a problem here. The number of employees are not constant. So if today we have a Employee Id 142 at second row. But after few days, it might move to 6th position or any other position. So we should write the xpath expression in such a way that we should be able to click on the correct Update button even though position of the row changes.

If columns are fixed, you can use below XPATH.
//td[contains(text(),'172')]//following-sibling::td[2]//button

If columns are not fixed, you can use below XPATH provided that a row has only one button.
//td[contains(text(),'172')]//parent::tr//button

Both the xpath expressions above, find the button relative to the TD tag that contains Employee Id. So even if Employee Id row changes, Selenium will find the correct button using relative xpath expression.


Above XPATH expressions can also be used to clicking button in specific cell.


What do you think on above selenium topic. Please provide your inputs and comments. You can write to me at reply2sagar@gmail.com

No comments:

Post a Comment

Buy Best Selenium Books