Xpath changes with every build given by developer in iOS

Xpath changes with every build given by developer in iOS. Hence, the automation script written for previous build fails when executed for a new one?

Xpath changes — it means that developer is changing the layout or elements position of the app continously.

Yes the script will fail. If the elements have Name or label attributes, there will be very less failures, provided they do not change them in every build.

Thanks hemche!

Is there a way to write/optimize xpath in iOS apart from the system generated one such as this //UIAApplication[1]/UIAWindow[1]/UIAButton[7] ; we do not have any properties in iOS like name or id so how do we come up with a locator which is unique and does not change with every build…Am I missing something?

It is a common scenario most of the Appium Test Developers face.

//UIAApplication[1]/UIAWindow[1]/UIAButton[7] ---- Appium will always look for 7th Button on the screen irrespective of the label or text on the button. Suppose in future if another button is added before this one, that button will be clicked.

So, it is always safe and better to use condition based Xpath when you don’t have Name or any other unique attributes.
If you can ping us the screenshot of the app window in inspector, it will help us to suggest you how to write an unique xpath.

Meanwhile, you should keep pushing developers for getting atleast one unique attribute for the elements !
All the Best !

Please advice on how to use properties other than xpath to create a unique id.

This is assuming there is only one tableView in the page.

If you can pass stock name as input, you can use below code for clicking on the stock name.

driver.findElementByClassName("UIATableView").findElementByIosUIAutomation(".cells().firstWithPredicate(\"ANY staticTexts.label CONTAINS \'"+stockCode+"\'\")").click();

This statement clicks on the GOOG line.

driver.findElementByClassName("UIATableView").findElementByIosUIAutomation(".cells().firstWithPredicate(\"ANY staticTexts.label CONTAINS \'GOOG\'\")").click();

If you want to click on delete button, just replace staticTexts.label in above commands with buttons.label

In your screenshot all of your elements have other attributes you can be leveraging. xpath based purely on index is horribly brittle for exactly the reason you’ve encountered. You should be using some other attribute in your xpath, if possible. Such as:

//UIAButton[@name="Delete GOOG"]

However, if your data is dynamic and you have absolutely no idea what values to expect you’ll have to randomize your tests based on what data is displayed in the app, then get creative with managing your indexes. For example, if you just want to randomly delete one of the items in the table do something like:

  • Randomly pick one of the UIATableCell
  • Either note it’s index, 3 in your screenshot, then programmatically compose the xpath for the button based on the cell’s index such as: xpath = '//UIAButton[cell_index]'
  • Or use xpath axes in for the button xpath where you find the preceding-sibling of the cell you’re working with.

Hopefully that helps.