QA
Junior QASeleniumFree question

How do you write dynamic XPath? Explain XPath axes and functions.

60-second answer

Dynamic XPath uses functions and relationships instead of fixed positions, so it survives UI changes. Useful functions are contains, starts-with, text and normalize-space, for example a button whose id starts with "submit", or a link containing the text "Logout". Axes let me navigate from a stable element to the one I need: parent, child, ancestor, descendant, following-sibling and preceding-sibling. For example, find the row containing "Order 1024" and then the "Cancel" button in that same row. I always prefer relative XPath starting with double slash.

Explanation

Functions:

  • //input[contains(@id,'email')]
  • //button[starts-with(@id,'btn-save')]
  • //a[text()='Logout'] and //span[normalize-space()='Total']
  • //input[@type='text' and @name='city']

Axes:

  • //label[text()='Email']/following-sibling::input
  • //td[text()='Order 1024']/parent::tr//button[text()='Cancel']
  • //input[@id='qty']/ancestor::form
  • (//div[@class='card'])[last()]

Example

A table of orders has auto-generated IDs. Anchor on the visible order number and walk to the button in that row instead of using the generated ID.

Sample code

By cancelForOrder(String orderNo) {
    return By.xpath("//td[normalize-space()='" + orderNo + "']"
                  + "/ancestor::tr//button[text()='Cancel']");
}

driver.findElement(By.xpath("//label[text()='Email']/following-sibling::input"))
      .sendKeys("qa@x.com");
driver.findElement(cancelForOrder("1024")).click();