09 Apr Chapter-4: Appium Locator Finding Strategies
Understanding how to properly use Locators is key to building your automation scripts. After all, if you’re unable to “find” the UI element, you cannot control it (such as clicking a button).
In Mobile (or Web) Automation Testing automating any scenario follows these 2 steps:
- Find the UI element locators (uniquely).
- Perform an action on that element.
In this chapter we focus on the first step and will look into all the available Locator Finding Strategies and discuss each strategy’s pros and cons.
So What is an Element Locator?
An Element Locator is nothing but an address that identifies a UI Element on a Mobile App (or Website). As there are many UI elements present on a single mobile application screen there can be a chance that same (generic)address can refer to more than one element. This means that we need to find a unique address for the element. As you will see, sometimes this is easy, and other times you have to do some further exploration to uniquely identify your UI element. The way in which you uniquely identify the element is called a locator strategy. Appium makes many different strategies available.
If you recall our simple test cases in Chapter 2, our Android example used the following code for identifying the Textview:
Here id is the Locator strategy and Login Screen is the unique id(address). Think of reading it as “Finding the element by <locator strategy> <element unique id>”. So in this example we’re telling Appium to use the “id” strategy (used for finding elements by unique ID) and the ID we’re using is “Login Screen”.
The below image describes how can you find the Textview element for any android application (in Java).
Figure-1:Locator Strategy(Java Example).
As you may expect, there are many different locator strategies available to you, including:
- Accessibility ID
- Class name
- Image (Recently Introduced)
- Android UiAutomator (UiAutomator2 only)
- Android View Tag (Espresso only)
- IOS UIAutomation
Learning which type of Locator Strategy to use is part of the learning process of becoming comfortable with Appium. We will go through all Locator Strategies and discuss them in detail. Don’t worry about memorizing all of them … at this stage in your journey you just need to become familiar with them and eventually you’ll understand which are best to use in which scenarios. In fact, there are some tricks coming up later that will automatically suggest which strategy to use! Often during your script development you’ll wrestle with trying to identify a UI element. When that happens, refer back to these different locator strategies to see which might best fit your needs.
NOTE: All of the above Locator Strategies can be inspected using the Appium Inspector Tool(for Android and iOS both). We will learn about that tool in the next chapter. The screenshots that follow are using this Inspector to illustrate the locator. The mobile app is depicted in the leftmost pane and when clicking an element we see the attributes in the rightmost pane.
- This is the best preferred locator strategy in Appium. Always use this one if you can.
- It is a Cross-platform locator strategy as this works in a similar way on iOS and Android which makes your code more reusable.
- iOS: If the accessibility id property(attribute) value is set at development time (by the app developers) then you can inspect it using the Appium Inspector(Android & iOS) or UiAutomatorViewer(Android). When Accessibility Id property value is not defined by developer, it is by default equals to the Name of that UI Element.
- Android: Accessibility Id property is equals to content-desc property(attribute) on Android.
Figure-2:Locator Type: Accessibility Id on Android Sample Application.
Example Usage in different programming languages:
WebElement chromeButtonElement = driver.findElementByAccessibilityId(“buttonStartWebviewCD”); MobileElement mobileElement = (MobileElement)chromeButtonElement;
element = self.driver. find_element_by_accessibility_id(“buttonStartWebviewCD”)
let element = await driver. elementByAccessibilityId(“buttonStartWebviewCD”);
$els = $this->element($this->using('accessibility id')->value(‘buttonStartWebviewCD’));
- Finding an element using Class Name is generic and it does not guarantee to find the unique element because many elements have the same class name.
- iOS: In iOS the class name is the fully qualified name of UIAutomation class, and it starts with “UIA” keyword such as UIAButton, UIARadioButton and UIATextField for old versions of iPhone Apps, and on recent versions made on Swift programming language you can find the “XCUITest” keyword.
- Android: In Android, the class name is the fully qualified name of the UIAutomator class and these are examples of it: android.widget.TextView , android.widget.Button, android.widget.ImageButton, android.widget.CheckBox etc.
- Now, in the above image (fig. 2), as you can see for the Chrome Button the class name is android.widget.ImageButton which is same for the User Registry button. Which leaves the question, how do you get the right button? The answer is using “Indexing”
- In figure-2 above the index value of the Chrome Image Button is 0 while in below image you can see the index value of User Registry Image button is 1, so by combination of locator and Index you can get the needed Unique UI locator. This is NOT ADVISABLE as it does not provide stability. There is a strong likelihood of indexes changing, for example if a new Image button is added to the screen!).
Figure-3: Index of class Name: android.widget.ImageButton
- You can get the indexed values using the relevant programming languages methods.
- This JAVA code will get the User Registry Image Button which has Class name= android.widget.ImageButton and Index=2.
List<MobileElement> mobileElements = (MobileElement) driver.findElementsByClassName(“android.widget.ImageButton”); MobileElement mobileElement = mobileElement.get(1);
Using Selenium Methods:NOTE: Actually You can get locators by two ways in Appium (for id, name, className, and xpath).
WebElement element = driver.findElement(By.className(“android.widget.ImageButton”)); // OR WebElement element = driver.findElementByClassName(“android.widget.ImageButton”);
Using Appium (Selenium Wrapper) Methods:
MobileElement mobileElement = (MobileElement) driver.findElement(By.className(“android.widget.ImageButton”)); // OR MobileElement mobileElement = (MobileElement) driver.findElementByClassName(“android.widget.ImageButton”);
In Mobile Application Automation id is are in form of Native context, it is not similar to Selenium WebDriver’s CSS id.
- id are also cross-platform locator strategy similar like accessibility id.
- iOS: It will find elements by name and label attribute but before that Appium will try to search for a accessibility id that will match with the given id string.
- For Figure-4 screenshot below both locator strategies are valid.
driver.findElementById("IntegerA"); // ORdriver.findElementById("TextField1");
Figure-4:Locator Type:Id on iOS Sample Application.
Android: In Android, it’s resource-id attribute. It contains common <package-name>:id/<id-name> string format.Figure-4:Locator Type:Id on iOS Sample Application.
- You can use either that full string (ex. io.selendroid.testapp:id/startUserRegistration) or only <id-name> (startUserRegistration). So in the below code both options are valid.
driver. findElementById("io.selendroid.testapp:id/startUserRegistration"); // OR driver.findElementById("startUserRegistration");
Figure-5:Locator Type:Id on Android Sample Application.
- iOS & Android: It’s the Name of the element on both platforms. This isn’t used as often as accessibility id and id strategies are mostly used.
- In below image you can find the Name attribute using:
MobileElement element = driver.findElementByName("IntegerA");
Figure-6: Locator Type:Name on iOS Sample Application.
Writing XPaths in Appium
- This locator strategy analyzes the XML structure of the app and locates the element with respect to the other elements.
- The XPath is originally designed to allow for the navigation of XML data with the purpose of locating unique UI elements.
- XPath selectors are not cross-platform.
- This strategy should only used when there is no Accessibility Id, Id or Name assigned to an UI Element. XPath has performance and stability issues but is very “brittle” changing across platforms and even device manufacturers.
- This strategy comes to the rescue when you’ve tried the above strategies and failed. As it depends on Parent XML nodes it’s really very fragile because when any new UI element gets added or removed, the XML structure is changed rendering your locators broken.
- Now the question is why you would ever use XPath ?
- It allows for the formulation of complex queries.
- It can literally find any UI element in the XML structure available to Appium. So even if no ID or Name is present, you can still find it with XPath.
- If you are using the Appium Inspector for inspection of the Application XML structure then Appium will give you the XPath directly without any extra effort.
Figure-7: Locator Type:XPath on iOS Sample Application.
- Using XPath you can use any attribute or/and combination of attributes in order to find the element uniquely. Apart from the above Xpath in the screenshot, all of the following XPaths are valid and find the Compute Sum button uniquely.
MobileElement computeSumButton = driver.findElementByXPath ("//XCUIElementTypeButton[@name="ComputeSumButton"]"); // OR MobileElement computeSumButton = driver.findElementByXPath("(//XCUIElementTypeButton)"); // OR MobileElement computeSumButton = driver.findElementByXPath ("//XCUIElementTypeButton[@label='Compute Sum']");
You can learn more about how you can find the Xpath from: https://www.w3schools.com/xml/xpath_syntax.asp, and from this link you can learn more about how you can properly use XPath with Appium:
- Appium supports Image Comparison as a locator strategy which is using the OpenCV library in the backend.
- The strings which are being used by this locator strategy are Base64-encoded image files.
- So you need to convert image files into Base64-encoded image files first and you need to pass that String into the locator.
- Below is the example:
String base64Image = //Code which will to convert Image file to Base-64 String WebElement element = driver.findElementByImage(base64Image);
- We will look into this locator strategy in more details in a dedicated chapter later on.
Android UiAutomator (UiAutomator2 only)
- This is an Android Platform specific locator strategy.
- This is rarely used to find the element locators as it requires to have prior knowledge of the UiSelector API (and of course it’s Android only).
- It’s performance is slightly better than XPath.
- In this example we find the first Button element having the text Login:
String selector = "new UiSelector().text(“Cancel”)) .className(“android.widget.Button”))"; MobileElement element = (MobileElement) driver.findElement(MobileBy.AndroidUIAutomator(selector));
Android View Tag (Espresso only)
- This is also an Android Platform specific locator strategy.
- It locates an element using it’s view tag.
- This is iOS Platform specific locator strategy. It uses Apple’s Instruments framework.
- It performs better than XPath.
String selector = "**/XCUIElementTypeCell[`name BEGINSWITH "P"`]/XCUIElementTypeButton"; MobileElement element = (MobileElement) driver.findElement(MobileBy.iOSClassChain(selector));
- In the above example we will find the 4th button anywhere under the UI hierarchy and whose name begins with the character ‘P’.
Hopefully you’re starting to get an idea of when to use which locator. Don’t worry if it isn’t immediately clear … the more you start building Appium scripts and the more you keep reviewing these it will become more intuitive.
Generally speaking you will find you should mostly likely use Accessibly Id and Id automation strategies. XPath is incredibly flexible as a fallback when no ID exists, but tends to be brittle. Your best option is to work with the developers to add unique IDs if they don’t exist. This will make for far more robust test scripts.