Mobile Test Automation with Selendroid

Dominik Dary, @dominikdary, Michael Palotas, @michael_palotas

Web Site: http://selendroid.io

Version: 0.11.0

System Requirements: Java and Android SDK installed

License & Pricing: Selendroid project is licensed under the Apache 2.0 License.

Support: Google Group http://groups.google.com/group/selendroid

Selendroid is a test automation framework which drives off the UI of Android native and hybrid applications (apps) and the mobile web. Tests are written using the Selenium 2 client API - that's it!

1. Borderless transactions and the impact on test automation or why we started Selendroid

The web has seen a dramatic change over the past few years with mobile becoming a big part of the overall experience. Test automation is a key enabler for Agile software development and subsequently for continuous integration and delivery. Many software companies are suddenly challenged with having to provide solid test automation not only for the web but also for mobile with its two flavors of mobile web and native apps.

Especially with the onset of mobile commerce and more and more transactions being made on mobile devices, the topic of test automation in the mobile space has gained huge significance. While in the past customers started and finished a transaction either on the web or on mobile, now there is an increasing trend to "move" between platforms. This means that users may start a transaction on the web and finish on mobile or vice versa.

This calls for the same robust and scalable test automation approach for mobile as for the web. Ideally the solution for mobile integrates seamlessly with the web solution so that the movement of users between platforms and devices can easily be recreated as part of an automated test. Due to the great success and experience with using Selenium for web automation, companies like eBay decided to develop "Selenium for mobile" solutions which namely resulted in the creation of two open source projects: Selendroid and ios-driver [1].

The high level requirements that went into the creation of Selendroid and ios-driver were

reuse of the existing Selenium infrastructure for the web

implementation of the Selenium protocol (JSON wire protocol)

the application under test (AUT) should not need to be modified

support for emulators/simulators as well as real devices

parallel execution of tests in a Selenium Grid

management of multiple applications, versions, languages

support for runtime inspection for the app

hybrid app support

no jailbreaking of device required

2. Background: What is Selenium?

In case you are not familiar with Selenium, here's a very brief introduction to it. Selenium originally is a tool to automate web browsers. The JSON Wire Protocol [2] describes user interactions with a browser. Each browser has a specific driver which is a native implementation for that specific browser. Selenium is a classic client/server architecture. The client side is decoupled from the driver (server). From a client perspective, the commands to interact with the browser are the same, regardless which browser is used.

Figure 1. High-level Selenium architecture

Selenium supports many different programming languages (client bindings) like Java, Python, Ruby and JavaScript.

What is different about mobile automation?

While there are of course differences between web and mobile automation, the core job of a mobile automation tool is the same as for the web:

find an element (i.e. button)

interact with the element (i.e. click the button)

Therefore the JSON Wire protocol which was initially created for the web, also applies to the mobile space, except special gestures like swipe.

3. Selendroid

Now after setting the stage, let's focus on introducing you to Selendroid. The project fulfills the requirements mentioned above and is used by many companies. The main features of Selendroid are:

Full compatibility with the JSON Wire Protocol.

No modification of app under test required in order to automate it

Testing the mobile web using built in Android driver webview app

Same concept for automating native or hybrid apps

UI elements can be found by different locator types

Gestures are supported: Advanced User Interactions API

Selendroid can interact with multiple Android devices (emulators or hardware devices) at the same time

Existing emulators are started automatically

Selendroid supports hot plugging of hardware devices

Full integration as a node into Selenium Grid for scaling and parallel testing

Multiple Android target API support (10 to 19)

Built in Inspector to simplify test case development.

3.1. In Action

Before Selendroid can be used, the system requirements must be met. There is a detailed page with instructions about how to get started.

In order to keep this example as simple as possible, there is a small demo project in which the Selendroid-test-app is used. This is the same app that the project is using to verify that Selendroid itself is working fine. The project demoproject-selendroid [3] is using maven, JUnit and Java to write the tests.

To import Selendroid and JUnit the following dependencies declaration is used:

<dependencies > <dependency > <groupId >io.selendroid </groupId > <version >0.11.0 </version > <artifactId >Selendroid-standalone </artifactId > </dependency > <dependency > <groupId >io.selendroid </groupId > <version >0.11.0 </version > <artifactId >Selendroid-client </artifactId > </dependency > <dependency > <groupId >junit </groupId > <artifactId >junit </artifactId > <version >4.8.2 </version > </dependency > </dependencies >

The app under test is located in the folder src/main/resources/.

3.1.1. Starting Selendroid-standalone

Before the client driver can be instantiated, the Selendroid-standalone component must be started.

This can be done via a shell by running the following command:

java -jar selendroid-standalone-0.11.0-with-dependencies.jar -app selendroid-test-app-0.11.0.apk

Another option is to start the Selendroid-standalone component directly from the test code:

SelendroidConfiguration config = new SelendroidConfiguration(); config.addSupportedApp("src/main/resources/selendroid-test-app-0.11.0.apk"); selendroidServer = new SelendroidLauncher(config); selendroidServer.launchSelendroid();

You can check that the application(s) and the devices are recognized by opening a browser and navigating to http://localhost:4444/wd/hub/status.

You should see a result similar to this:

{ status: 0, value: { "os": { "name": "Android" }, "build": { "browserName": "Selendroid", "version": "0.11.0" }, "supportedApps": [{ "appId": "io.selendroid.testapp:0.11.0", "mainActivity": "io.selendroid.testapp.HomeScreenActivity", "basePackage": "io.selendroid.testapp" }], "supportedDevices": [{ "screenSize": "320x480", "targetPlatform": "ANDROID17", "emulator": true, "avdName": "latest" }] }

3.1.2. The first Test

Tests are written using the Selenium 2 client API. For Java, we provide Selendroid-client libraries that are used in this example:

SelendroidCapabilities capa = new SelendroidCapabilities("io.selendroid.testapp:0.11.0"); SelendroidDriver selendroidDriver = new SelendroidDriver(capa); WebElement inputField = selendroidDriver.findElement(By.id("my_text_field")); Assert.assertEquals("true", inputField.getAttribute("enabled")); inputField.sendKeys("Selendroid"); Assert.assertEquals("Selendroid", inputField.getText()); selendroidDriver.quit();

In order to create a new test session in the desired capabilities, the id of the app under test must be provided in the format: io.selendroid.testapp:0.11.0. Based on that information, a matching Android device will be identified, otherwise the test session will throw an error and not start.

After the found device has been initialized, a customized Selendroid-server will be created and automatically installed on the device. The app under test will also be installed and the Selendroid-server on the device will then be automatically started.

After the test session has been successfully initialized, the test commands such as find an element and element interactions are routed to this device. If the test session has ended, the emulator will stop automatically.

3.1.3. Switching Context

As described above, Selendroid can automate native and hybrid apps and the mobile web. When a Selendroid test session is started, the native mode is activated by default.

Available contexts can be retrieved via:

selendroidDriver.getContextHandles();

When a webview is available, above method will return a "WEBVIEW" context handle.

String contextHandleName="WEBVIEW"; selendroidDriver.context(contextHandleName);

When a context switch is done, all WebDriver commands are redirected to the corresponding context.

3.1.4. Interacting with Elements

Before interacting with elements, first the elements need to be found. Multiple Element locator strategies are supported, look at the Selendroid's documentation for details.

This is the list of supported element interactions:

Get Text

Click

Send Keys

Get Attribute of Element

Clear

Submit

Is Selected

Is Displayed

Is Enabled

Get Size

Get Location

The biggest advantage of using Selendroid is the smooth switch between native and web contexts.

3.2. Selendroid Inspector

Selendroid comes with a useful little tool called Selendroid Inspector. It's a little web app which is embedded inside your Selendroid test server. Its purpose is to let you inspect the current state of your app's UI.

The main features are:

View hierarchy

View UI element properties

UI screenshot with view locator

Record the click actions

Display the source html of a web view

XPath helper

Figure 2. Selendroid Inspector

3.3. Selendroid Architecture

Selendroid is based on the Android instrumentation framework and therefore supports only testing one app. Selendroid contains four major components:

Selendroid-Client - the java client library (based on the selenium java client).

Selendroid-Server - that is running beside your app on the Android device.

AndroidDriver-App - a built in Android driver webview app to test the mobile web.

Selendroid-Standalone - manages different Android devices by installing the Selendroid-server and the app under test.

Below you can see an overview about the architecture:

Figure 3. Selendroid Architecture

3.3.1. Selendroid-Standalone

This components acts as a proxy between the Selendroid-client and the Selendroid-server and starts for instance an Android emulator, creates for the app under test a customized Selendroid-server and installs everything on the device. After the session is initialized on the device, subsequent requests are directly forwarded to the server on the device and the response routed back to the client.

3.3.2. Selendroid-Server

This server component runs on the device and is implementing the JSON Wire protocol for Android native and hybrid contexts. The base framework to interact with the app under test is the Android Instrumentation framework [4].

Internally the web view related driver class is SelendroidWebDriver and the native class is SelendroidNativeDriver. SelendroidWebDriver is using Automation Atoms of the Selenium project to interact with the elements in the web view.

4. Selenium Grid

End-to-end tests are very expensive in terms of execution time and computing resources. Besides starting a browser, the whole flow of a user needs to be tested (i.e. sign in, search for something, buy it, pay). This can take 2-3 minutes, even in an automated fashion. Considering that larger web applications may require hundreds, if not thousands of end-to-end tests, the execution time of the test suite can easily take hours or days if the tests are executed sequentially. Parallel execution allows to fit more tests into the same timeslot and thereby drastically reducing execution time of the entire test suite. Selenium Grid allows to run tests in parallel

Figure 4. Visualization of parallel test execution.

Selenium Grid has two main tasks:

act as a load balancer for incoming requests from the client(s) and distribute the tests to the registered nodes

act as a resource manager to match incoming capability requests with the available capabilities in the Grid (a capability could be a platform, version, browser etc.)

Figure 5. Example architecture for a Selenium Grid.

The nodes (on the right side) send a registration request to the Selenium Grid Hub, telling it their capability. This typically consists of OS, browser, browser version. The client (left side) sends all tests along with so called Desired Capabilities to the Selenium Grid Hub as a central entry point. The Selenium Grid Hub now tries to match the desired capabilities to the actually available capabilities. If there is a match, it forwards the test to the node that matches the capabilities. In addition, it has the ability to run tests in parallel by distributing them to all matched nodes.

Using Selendroid in a grid requires multiple steps that are described in detail in the documentation

5. State of the project

Selendroid open source project is in active development and has already multiple contributions from different contributors and companies like eBay, Salesforce, Red Hat and Facebook.

References

1. http://ios-driver.github.io/ios-driver

2. https://code.google.com/p/selenium/wiki/JsonWireProtocol

3. https://github.com/selendroid/demoproject-selendroid

4. http://developer.android.com/tools/testing/testing_android.html

More Software Testing Knowledge

Functional Testing Tools

Software Testing Magazine

Software Testing Books

Growing Object-Oriented Software, Guided by Tests

Implementing Automated Testing

Click here to view the complete list of tools reviews

This article was originally published in the Fall 2014 issue of Methods & Tools