Advanced Locator Strategies

Posted by Isaac Murchie in MobileMobile Development & Testing

Appium is built to implement the Selenium WebDriver JSON Wire Protocol specification, extended to enable the automation of mobile devices. By and large, the extensions to the WebDriver spec are encoded within the draft Mobile JSON Wire Protocol spec.

In order to find elements in a mobile environment, Appium implements a number of locator strategies that are specific to, or adaptations for, the particulars of a mobile device. Three are available for both Android and iOS:

class name

The class name strategy is a string representing a UI element on the current view.

  • For iOS it is the full name of a UIAutomation class, and will begin with UIA-, such as UIATextField for a text field. A full reference can be found here.
  • For Android it is the fully qualified name of a UI Automator class, such android.widget.EditText for a text field. A full reference can be found here.
The client libraries for Appium support getting a single element, or multiple elements, based on the class name. This functionality is in the Selenium clients (e.g., Python).

[code language="python"]

python

driver.find_element_by_class_name('android.widget.DatePicker') [/code]

accessibility id

The accessibility id locator strategy is designed to read a unique identifier for a UI element. This has the benefit of not changing during localization or any other process that might change text. In addition, it can be an aid in creating cross-platform tests, if elements that are functionally the same have the same accessibility id.

  • For iOS this is the accessibility identifier laid out by Apple here.
  • For Android the accessibility id maps to the content-description for the element, as described here.
For both platforms getting an element, or multiple elements, by their accessibility id is usually the best method. It is also the preferred way, in replacement of the deprecated name strategy.

The client libraries specific to Appium support getting elements by accessibility id. The methods are not yet implemented in the standard Selenium clients.

[code language="python"]

python

driver.find_element_by_accessibility_id('my_accessibility_identifier') [/code]

xpath

The xpath locator strategy is also available in the WebDriver protocol, and exposes the functionality of XPath language to locate elements within a mobile view. An XML representation of the view is created in Appium, and searches are made against that image.

The Selenium clients have methods for retrieving elements using the xpath locator strategy.

[code language="python"]

python

driver.find_element_by_xpath('//UIAApplication[1]/UIAWindow[1]/UIATextField[1]') [/code]

id

In the mobile environment, ids are not, as in WebDriver, CSS ids, but rather some form of native identifier.

  • For iOS the situation is complicated. Appium will first search for an accessibility id that matches. If there is none found, a string match will be attempted on the element labels. Finally, if the id passed in is a localization key, it will search the localized string.
  • For Android, the id is the element's android:id.

Accessing the underlying automation tools

Finally, Appium exposes two methods of using the underlying device automation technology directly, in order to find elements. This is especially useful when a test needs some fine-grained control over finding elements.

-android uiautomator

Android's UI Automator framework provides a number of ways to find elements. You can use the UI Automator API, in particular the UiSelector class to locate elements. In Appium you send the Java code, as a string, to the server, which executes it in the application's environment, returning the element or elements.

To find, for instance, all elements that are clickable in a view, you would use the following Java code (adapted from here):

[code language="java"] UiDevice device = UiDevice.getInstance(getInstrumentation()); UiObject cancelButton = device .findObject(new UiSelector() .text("Cancel")) .className("android.widget.Button")); [/code]

In Appium, this is reduced to the UiSelector code itself, which is sent to the appropriate find method:

[code language="python"]

python

command = 'new UiSelector().text("Cancel")).className("android.widget.Button")' driver.find_element_by_android_uiautomator(command) [/code]

-ios uiautomation

When automating an iOS application, Apple's UI Automation framework can be used to find elements. This JavaScript API has methods to access to the view and everything on it.

In order to find a textfield (in UI Automation terminology, a UIATextField element) with the label or name "User Text", the following JavaScript would be used (adapted from here):

[code language="javascript"] var textField = UIATarget.localTarget().frontMostApp().mainWindow().textFields()["User Text"]; [/code]

In Appium, this can be done executed by sending in the JavaScript command, as a string, beginning after the UIATarget.localTarget().frontMostApp().mainWindow() call. That is to say,

[code language="python"]

python

command = '.textFields()["User Text"]' driver.find_element_by_ios_uiautomation(command) [/code]

You can also use predicate searching within iOS UI Automation in Appium, to control element finding even further. See here for details.

Conclusion

Using these strategies, it is possible to have control over finding elements, whether single or multiple, in a mobile application. This control forms the foundation of any automation, as once elements are found they can be queried for information as well as interacted with. By giving tests access to all elements in a variety of ways, Appium allows tests and testers to choose their preferred methodologies.

Discuss: Advanced Locator Strategies
0 Comments

Free Trial

Get access to a free 14-day trial version, or contact Sales for more information.