Android Browser Testing with Selenium

In the current "Mobile Web Revolution" it is increasingly important to test webapps not just for traditional desktop web browsers, but for phone web browsers too.

The Android SDK (unlike e.g. the iPhone one) is available for free and runs on multiple platforms (Linux, Mac, Windows), so its emulator is an ideal tool to start testing on at least one mobile browser.

In this post I'll share my experiments with Selenium Remote-Control and the Android Browser running in an emulator. In theory Selenium should work with any modern JavaScript-enabled browser, but the Android Browser is not one of the explicitly supported browsers yet, so we'll have to start it using the *custom specifier.

The key point is that typically you'd pass a browser executable path to *custom, e.g. *custom /usr/bin/firefox, but in our case we need to start the Browser inside the emulator, not on our workstation. Luckily we can use the adb tool to send commands to the emulator (or an actual device). After some investigation, the magic incantation to start the browser inside the emulator (assuming it's already running) at a given URL turns out to be:

$ANDROID_HOME/tools/adb shell am start -a android.intent.action.VIEW -d http://www.google.com

I found I had to wrap this command in a simple shell script, otherwise it wouldn't work when invoked by Selenium because of an issue with escaping the URL for shell execution, so I created the following android-browser script:

#!/bin/sh
ANDROID_HOME="$HOME/tools/android-sdk-linux"
exec $ANDROID_HOME/tools/adb shell \
  am start -a android.intent.action.VIEW -d \"$1\"

and we can pass the path to this script to *custom when starting Selenium.

I then stumbled into a bug in the current stable version of Selenium RC v1.0.1, causing a NullPointerException when starting a *custom browser. Now I'm on Linux, so maybe you're not affected if you're on Mac or Windows, but I had to check out and build selenium-server from the latest trunk where that bug has now been fixed.

The next step is to use Selenium in proxy injection mode, to be able to test arbitrary domains. This can be achieved by starting the RC server with

java -jar selenium-server-1.0.2-SNAPSHOT-standalone.jar -proxyInjectionMode

and the Android emulator with

$ANDROID_HOME/tools/emulator -http-proxy 'localhost:4444' -avd android-2.0.1

so that any requests made by the Android Browser will be proxied through the Selenium server.

With all these bits in place, I was finally able to have Selenium start the Android browser and run some tests. Here's a simple example (in Java, but you could use any of the languages supported by Selenium):

   @Test
   public void register() {
      String executable = System.getProperty("user.home") + "/bin/android-browser";
      Selenium selenium = new DefaultSelenium("localhost", 4444, "*custom " + executable, "http://www.mysite.com");
      selenium.start();
      selenium.open("http://www.mysite.com/register");
      assertEquals("My Site - Register", selenium.getTitle());
      selenium.type("emailField", "joe.bloggs@example.com");
      selenium.click("registerButton");
      selenium.waitForPageToLoad("30000");
   }

In summary, with a little bit of fiddling it's already possible to run Selenium tests in the Android browser. However this should be considered somewhat experimental at this stage.