Selenium on Android
Join the DZone community and get the full member experience.
Join For FreeTesting web applications is not only based on unit and functional tests for the server-side (PHP, Java) and client-side (JavaScript) components, but also on end-to-end tests like the ones performed with Selenium. Selenium is capable of driving a real browser like Firefox in the same way a user would do, letting you express a test with a series of page to load, element selections, clicks and typed characters.
Selenium 2 exposes a WebDriver API that can be implemented by many different servers: not only desktop browsers can be driven with it, but also browsers on mobile devices like the standard Android browser.
In this tutorial, we'll experiment with the Android Driver and set up a couple of tests to run inside an Android virtual device.
Android setup
The best choice for running tests is an emulator, as it is more versatile than a real mobile terminal and can be easily upgraded through various versions (while for example I do not have a real Android 4.x device, the highly recommended version.)
If you have already a virtual device setup, you can skip this step. If not, before running the emulator make sure you have installed all the required packages listed here along with the Android SDK.
You should have the commands android, emulator, and adb available on your path to continue.
$ android create avd -n my_android -t 12 -c 100M
will create a virtual device named my_android. To get a list of possible targets for the -t option, execute:
$ android list targets
You can now run the emulator with:
$ emulator -avd my_android
With android avd you can open the configuration window, and add the Gpu acceleration directive as a new hardware option (with the value yes). I didn't see any difference in the tests after adding the option, though.
Installation
$ adb devices List of devices attached emulator-5554 device
will list the available devices: you should wait until `device` is displayed instead of `offline`.
$ adb -s emulator-5554 -e install -r android-server.apk
will install the WebDriver application, which can be downloaded from Selenium's website.
Start the Android Driver with:
$ adb -s emulator-5554 shell am start -a android.intent.action.MAIN -n org.openqa.selenium.android.app/.MainActivity
and wait a couple of seconds for it to return the control to the shell.
Since the emulator does not have an IP address, we have to forward the host 4000 port to the device's 8080 (4000 is just an example) with:
adb -s emulator-5554 forward tcp:4000 tcp:8080
In case of any error, display the logs with:
adb logcat
Writing a test
Tests that want to run inside Android will use the Json Wire Protocol, that accepts requests from bindings written in any language. In fact, the tests will interface with localhost:4000, the REST-like API of WebDriver, which is in turn forwarded to the emulator's 8080 port.
The browser to request is 'android', of course. Even from Java code, which usually interfaces with WebDriver directly, a RemoteWebDriver class is available.
Example
In this example, I also setup a tiny web server on 192.168.0.2 (the local machine) to serve some HTML pages that the tests exercise. In a real scenario, you will serve your web application instead.
Since I target the application web server with its IP address, this test can work also with real phones that connect to the wireless local network.
<?php class AndroidTest extends PHPUnit_Extensions_Selenium2TestCase { public function setUp() { $this->setHost('localhost'); $this->setPort(4000); $this->setBrowser('android'); $this->setBrowserUrl('http://192.168.0.2:8080'); } public function testLoadsAnHtmlPage() { $this->url('html/test_open.html'); $this->assertEquals('Test open', $this->title()); } public function testTypingViaTheKeyboard() { $this->url('html/test_type_page1.html'); $usernameInput = $this->byName('username'); $usernameInput->value('giorgio'); $this->assertEquals('giorgio', $usernameInput->value()); $passwordInput = $this->byName('password'); $passwordInput->value('password'); $this->assertEquals('password', $passwordInput->value()); $this->clickOnElement('submitButton'); $h2 = $this->byCssSelector('h2'); $this->assertRegExp('/Welcome, giorgio!/', $h2->text()); } }
This is the result of the tests (the HTML pages are taken from PHPUnit_Selenium's test suite):
$ phpunit --colors AndroidTest.php PHPUnit 3.6.10 by Sebastian Bergmann. .. Time: 02:22, Memory: 3.75Mb OK (2 tests, 4 assertions)
Conclusions
These tests are slow, and we didn't perform any optimization. Not only running a browser through WebDriver is slower than executing unit tests, but we are also inside an emulator that translates instructions meant for another family of processors. These ordinary Selenium tests would take only seconds to run in a desktop browser.
As for all Selenium tests, you can actually see (if you keep the WebDriver app in the foreground) the tests being executed in an instance of the android browser. However, all commands are available from the shell and the automation of the emulator execution and the test run is only one step away.
Opinions expressed by DZone contributors are their own.
Comments