Appium – Preparing for Automation – Part 2: Writing XPath to target Elements

In the previous blog post in this series we saw how to use the Appium Inspector and the UiAutomatorViewer to interrogate our app and find details of the various elements. In this post, we are going to explore how we can write XPATHs to target those elements.

If you have done any previous Selenium automation, then it is likely you will have at least some knowledge of how Xpath works. If this is all new to you (or you need a refresher) I would recommend working through the relatively short and concise Xpath Tutorials on TutorialsPoint here first, before continuing with this post…

Done that? Ok let’s continue!

USING RESOURCE-ID

So when we are writing Xpaths we ideally want to be targeting unique elements on our page, or we could run into problems when running the automation. By definition, the RESOURCE-ID of each element on the page should be unique (although it isn’t necessarily, so beware…), so if your element has a resourceID, you can pat your friendly developer on the back, and write a simple Xpath to target it.

Using our calcuator app from the previous post, say that we wanted to target the number 7:

In the screenshot we can see that the full resource-id for button 7 is “com.app.sonny.calculator:id/button7“. The class of the button is android.Widget.Button. We only need to include the part that is changing each time in the Xpath (i.e. the “button7“) so the Xpath to target this would be as follows:

xpath("//android.widget.Button[contains(@resource-id,'button7')]")

This Xpath says to look for a android.widget.Button that has a resource-id that contains the text ‘button7

USING CONTENT-DESC or TEXT

Sometimes the element will not have a resource ID, but it will have a unique CONTENT-DESC or TEXT. In that case, we can use an Xpath to target it. For example, to target the CLEAR button on the calculator:

xpath("//android.widget.Button[@text='clear']")

USING CLASS AND INDEX

On occasions you will find that the element you want has no resource-ID, content-desc or text (or at least, they are not unique). In this case, all is not lost! Every element displayed in your app will always have a class and an index number, so if necessary we can use that to target the element that we need.

Let’s look at an example. Suppose that we wanted to target the number 5, without using resource-id, content-desc or text.

To do that we can first target the LinearLayout that contains the number 5, which has a class “android.widget.LinearLayout” and index “1“.

We can then get the actual number 5 element by targeting the index “1” of the previous LinearLayout.

The Xpath would look like this:

xpath("//android.widget.LinearLayout[@index='1']/android.widget.Button[@index='1']")

Remember, your Xpath must target a unique element! If it doesn’t then you need to keep going up the hierarchy, adding more elements, until you have an Xpath that points to a unique element.

This post should give you a solid strategy to target the desired element in your app for the vast majority of cases, certainly whilst you are starting out. There are cases where this strategy might not be sufficient, for example when your app generates dynamic data, but the case for handling that depends on the design of your app.

In the next post, we are going to utilise everything we have learnt so far to start writing actual automated tests in our IDE.

  • neploch

    Hi James!
    You are making a great work, but there is no link/button etc to go from this page to the next part….