Locators
In Appium, locators are used to find and interact with elements in your mobile app. For example, if you want to click a button or input text into a field, you need to first locate that element on the screen. Appium provides several ways (or strategies) to locate these elements, depending on how the app is built.
Choosing the right locator strategy is crucial to ensuring your tests are reliable and maintainable.
Why Are Locators Important?
Locators are essential because they:
- Identify elements: Help you find the buttons, text fields, images, etc., in your app.
- Interact with elements: Once located, you can perform actions like clicking, typing, or swiping.
- Handle dynamic elements: Many mobile apps have elements that change frequently, and effective locators help handle those changes.
Types of Locators in Appium
Appium provides different locator strategies for identifying elements in mobile apps, whether they are Android or iOS apps. Below are the common locator strategies available in Appium 2.x.
- By ID (AppiumBy.id)
- Description: This is the most straightforward way to locate an element. Every element in a mobile app usually has a unique resource ID (Android) or accessibility ID (iOS).
- Usage: Best used when elements have stable, unique IDs.
- Example: driver.findElement(AppiumBy.id("com.example:id/loginButton"));
- By Accessibility ID(AppiumBy.accessibilityId)
- Description: Accessibility IDs are used for accessibility features, but they are also a very stable way to locate elements. This strategy works across both Android and iOS.
- Usage: Preferred for cross-platform apps because the same locator can work on both Android and iOS.
- Example: driver.findElement(AppiumBy.accessibilityId("loginButton"));
- By XPath (AppiumBy.xpath)
- Description: XPath is a powerful way to locate elements based on their XML structure in the app. It allows you to navigate through elements based on hierarchy or attributes.
- Usage: Use XPath when no stable IDs or accessibility IDs are available. However, it can be slower and more fragile.
- Example: driver.findElement(AppiumBy.xpath("//android.widget.Button[@text='Login']"));
- By Class Name (AppiumBy.className)
- Description: You can locate elements based on their class names, like android.widget.Button for buttons or android.widget.TextView for text fields.
- Usage: This is useful when you want to interact with all elements of a particular type, such as all buttons.
- Example: driver.findElement(AppiumBy.className("android.widget.Button"));
- By Tag Name (AppiumBy.tagName)
- Description: Similar to className, you can locate elements using their tag name. This is more common in web or hybrid apps when automating webviews.
- Usage: Works best for webviews or when automating a mobile browser.
- Example: driver.findElement(AppiumBy.tagName("input"));
- By Android UIAutomator (AppiumBy.androidUIAutomator)
- Description: This locator strategy is specific to Android and uses the UIAutomator framework. It allows you to write complex queries for finding elements.
- Usage: Use this for more complex queries on Android apps.
- Example: java driver.findElement(AppiumBy.androidUIAutomator("new UiSelector().text(\"Login\")"));
- Android Data Matcher (AppiumBy.androidDataMatcher)
- Description: It is android specific locator and is used with Espresso driver to find elements based on data inside adapters like ListView, RecyclerView etc. It works using Hamcrest matchers (Android testing library)
- Usage: Use this locator when elements are inside RecyclerView, ListView etc. When normal locators id/xpath don't work or you want to match data instead of UI.
- Example: driver.findElement(AppiumBy.androidDataMatcher("{'name': 'hasEntry', 'args': ['title', 'My Item']}"));
- Android View Matcher (AppiumBy.androidViewMatcher)
- Description: It is android specific locator and is used to find elements based on view properties using Espresso matchers. It directly matches UI view attributes
- Usage: Use this locator when you want to match text, content description, visibility etc.
- Example: driver.findElement(AppiumBy.androidViewMatcher("{'name': 'withText', 'args': ['Login']}"));
- Android View Tag (AppiumBy.androidViewTag)
- Description: It is android specific locator and is used to locate elements using view tag, the tag set by developer in Android code.
- Usage: Use this locator when dev team has added setTag() or when no ID or accessibility ID exists.
- Example: driver.findElement(AppiumBy.ANDROID_VIEWTAG("login_button_tag"));
- Image Locator (AppiumBy.image)
- Description: This locator is used to finds elements using image recognition instead of UI properties. Appium compares screenshot with given image.
- Usage: Use this locator when there is no ID, element is inside canvas, if it is a game UI. You can also use it for visual validation.
- Example: driver.findElement(AppiumBy.image("path/to/image.png"));
- By iOS Predicate String (AppiumBy.iOSNsPredicateString)
- Description: Specific to iOS, this strategy uses NSPredicate to locate elements based on their attributes.
- Usage: Best for complex queries on iOS apps.
- Example: driver.findElement(AppiumBy.iOSNsPredicateString("label == 'Login'"));
- By iOS Class Chain (AppiumBy.iOSClassChain)
- Description: Another iOS-specific strategy that allows you to chain elements based on their class hierarchy.
- Usage: Helps in navigating through deeply nested elements in iOS apps.
- Example: driver.findElement(AppiumBy.iOSClassChain("**/XCUIElementTypeButton[`label == 'Login'`]"));
How to Use Locators in Appium Tests
To use locators in your Appium test script, you first need to locate the element and then perform an action, such as clicking a button or sending input to a text field.
Here's an example of how to use different locators:
// Selenium locators. These are used when working with webview driver.findElement(By.id("id")); driver.findElement(By.name("submit")); driver.findElement(By.className("smallButton")); driver.findElement(By.tagName("div")); driver.findElement(By.linkText("click here to register")); driver.findElement(By.partialLinkText("click here")); driver.findElement(By.cssSelector("#submitButton")); driver.findElement(By.xpath("//a[text()='click here to register']")); // Appium Locators. These are used on native applications. driver.findElement(AppiumBy.id("id")); driver.findElement(AppiumBy.accessibilityId("accessibilityId")); driver.findElement(AppiumBy.androidUIAutomator("new UiScrollable(new UiSelector()).scrollIntoView(text(\"Submit\"))")); driver.findElement(AppiumBy.androidDataMatcher("{\"name\": \"hasEntry\", \"args\": [\"title\", \"My Item\"]}")); driver.findElement(AppiumBy.androidViewMatcher("{\"name\": \"withText\", \"args\": [\"Login\"]}")); driver.findElement(AppiumBy.androidViewTag("loginButtonTag")); driver.findElement(AppiumBy.image("path/to/image.png")); driver.findElement(AppiumBy.iOSNsPredicateString("label == 'Login'")); driver.findElement(AppiumBy.iOSClassChain("**/XCUIElementTypeButton[`label == 'Login'`]"));