Mobile Software Test Automation: Interacting with objects for Android

Last week we went over some advanced query syntax to help in locating a specific element.  The great news now is that any element you can locate via query, you can also interact with via all the touch methods we will discuss today.  Before we get started, I do want to point out that today we will only be discussing swipe and touch methods for android.  The reason for this is because the UX between iOS and Android is a bit different, and so the methods to perform those gestures are different as well.  For example, current material design for Android puts some actions on a titlebar menu with an icon, where iOS requires a gesture to expose those options.  Now, with a cross-platform test suite, this doesn't really cause an issue since our page object pattern has allowed us to separate out these two platforms.  So let's dive in.

Touch Methods

Back when we wrote the page support for android, you saw that we could tap on an element using the touch method:

touch("* marked:'9'")

Although this may get you through a simple calculator app, anyone who uses a more complex app knows there are more ways to interact with your phone.

Double Tap

One touch method that may be useful is a double tap.  The great news is you can use the same query strings we learned last week, but inside this method it will double tap that object.  Here is how it's used:

double_tap("android.widget.Button marked:'Save'")

Long Press

Another useful method is the long press method.  Here is an example:

long_press("* marked:'tvMessage' {text CONTAINS[c] 'sample message'}")

Tap When Element Exists

Depending on the way you wrote your .feature file, and how you handle assertions as you move through the test, this method may prove useful for you.  Instead of using the touch method, this will wait for the specific element to appear before attempting to touch it:

tap_when_element_exists("android.widget.Button text:'Help'")

There are a host of other touch methods that you can use, and I only mentioned a few that you will use most often.  But if you are looking for a more complete list, you can find it via the calabash android API here.


Now, it's great that we can touch, double_tap, and long_press on objects, but there is one caveat with can only interact with an element that is in view.  If the center of the object is not in view, the object won't be  able to be interacted with.

Basic Swiping

This is where swiping comes in.  There are a few different ways this can be accomplished.  First, there are predefined steps in calabash that will allow you to swipe up, down, left, and right.  All they require is the following in your .feature file:

When I scroll up
Then I scroll down
And I swipe right
Then I swipe left

These work great if you are trying to navigate through a scrollable view, so long as it is the only one on the page.  If that is not the case, we will have to make a custom step.  

Advanced Swiping

An example of when you would need a custom step build is when you have a screen where the scroll view you want to interact with is on the bottom third of the screen, as is most calendar pages.  We can do this a few ways.  The best option here would be to find the view in a query string and use a built in method to scroll.  This is done using the scroll method:

scroll(query_string, direction)
scroll("android.widget.ScrollView index:1", :up)

This should work for the majority of your cases, but as of now, only accepts 2 directions: up and down.  If you want to scroll left or right, we will have to do this by coordinates.  There is a predefined step definition to handle dragging by coordinate percentages, which looks like this:

Then I drag from fromX:fromY to toX:toY moving with Z steps
And I drag from 25:85 to 75:85 moving with 1 steps

This will swipe from left to right on the bottom of the screen in 1 step.  If you wanted to make your own custom step, it looks like this:


Note that all these coordinates are percentages of the screen width and height, which helps them to work on a wider array of devices.  If for some reason you want to use actual coordinates, you could use this:

perform_action('drag_coordinates', fromX, fromY, toX, toY)
perform_action('drag_coordinates', 214, 1150, 214, 400)

Wrapping up

This was intended to be a guide for the more commonly used touch methods, and is by no means an exclusive list of available methods.  However, if you need to find something to work with your app and it isn't included here, let me know in the comments and I will be glad to help you out.  And stay tuned next week as we go through interacting with object on iOS!