In this article, I would like to share how to find off-screen elements in Android using Appium and also how ‘Android Data Matcher‘ Locator Strategy works better. One of the known limitations of finding elements on Android is that the Android UI renderer doesn’t actually build and render elements until they are about to appear on the screen. If we are looking for an element that is far down in a list, and not yet visible on the screen, the element just does not “exist”. You can prove this to yourself by generating a source snapshot of your app while there are lots of list elements present below the edge of the screen.
How do we handle a situation like this with Appium? Usually, say is to “think like a user”–how would a user find this item? By swiping to scroll the list and using their eyes to periodically check for the appropriate content. We could, therefore, implement a scroll-and-find helper method with built-in retry loops. If we’re using the Espresso driver, there’s a better way: the ‘Android Data Matcher‘ locator strategy.
This strategy takes advantage of the fact that Espresso runs in the app context, not on top of the Accessibility layer, so it has access to the data which backs a list, not just the elements which are displayed on the screen. We can use a part of the Espresso API to essentially target this data, and have Espresso automatically scroll to the element which represents that data for us. If we were using Espresso directly (not through Appium), we might accomplish this with the following code:
This Espresso code waits for some “data” according to the parameters we’ve given the onData command, namely that we want an entry that has a specific title, within the list that has a certain Android ID. The important bit here is the hasEntry function, which builds a hamcrest matcher. The matcher is used by Espresso to help find the desired data and turn it into a view we can interact with. All kinds of matcher explore and use with Expresso are available now in Appium. Basically, in Appium we need to use -android datamatcher locator strategy, in Java is accessed as MobileBy.androidDataMatcher. And for the selector, rather than a simple string, we construct a JSON object containing the Matcher information, stringify it, and pass it as the selector. Below we can how normally use in automation scripting,
// first, find the AdapterView (not necessary if there’s only one)
WebElement list = wait.until(ExpectedConditions.presenceOfElementLocated(
// Construct the Hamcrest Matcher spec
String selector = new Json().toJson(ImmutableMap.of(
“args”, ImmutableList.of(“title”, “Layout”)
// find and click on the element using the androidDataMatcher selector
In the above example, it will look for the title “Layout” in the list and perform the click action. When you see this work, it’s pretty awesome, the screen will jump very quickly to the expected item in the list view, without having to do a bunch of manual scrolling.
Reference: Appium Pro
make it perfect!