Thursday, February 16, 2012

Testing Android User Interfaces with Robotium


Overview

Android provides a 'test project' framework and various tools for testing apps.  Robotium is an opensource project which enhances these facilities.  Robotium provides convenience and utility methods which simplify clicking buttons, accessing text fields, etc.  Robotium hides the underlying syntax and procedures.

Tests can be run on emulators as well as real devices.

Tests can be started within eclipse as well as from a command-line.

Testcase methods can access localized message strings.

Setup

- Create the Android app to be tested (aka app-under-test).

- Create a basic Android Test Project associated with your app-under-test.  Follow basic Android instructions:
http://developer.android.com/resources/tutorials/testing/helloandroid_test.html

- Verify it runs.
From Eclipse package explorer, right-click the test project-> Run As-> Android JUnit Test.

- Fetch the Robotium jar file:
http://code.google.com/p/robotium/ -> Downloads -> robotium-solo-3.1.jar (or later)
  Optional: Fetch the javadoc.

- Add the Robotium jar file to the test project 'libs' directory
From Eclipse-> right click test project-> Properties-> Java build path-> Add external jars-> point to jar.

- In your testcase class, import the Robotium Solo class and define a reference to a Solo object:

    import com.jayway.android.robotium.solo.Solo;

    private Solo mSolo;

  Fix your dependencies and get your testcase class to compile.

- Instantiate a Solo object in one of your testcase methods:

        // Instantiate a new Solo object.
        mSolo = new Solo(getInstrumentation(), getActivity());

  Verify it runs.  You are now ready to make use of Robotium...

Using Robotium

Study the methods available in class Solo.  Either read the javadoc or browse the source:
https://github.com/jayway/robotium/tree/master/robotium-solo/src/main/java/com/jayway/android/robotium/solo

- Access widgets in your app-under-test using Solo.  Examples:

-- My app-under-test contains one ToggleButton.  Since there is only one, I can use the index '0' to query this ToggleButton:

    // Query whether the button is checked.
    boolean checked = mSolo.isToggleButtonChecked(0)

-- My ToggleButton text is defined as 'OFF' and 'ON'.  To click the ToggleButton, I use the name:

    // Click the OFF button to ON.
    mSolo.clickOnToggleButton("OFF");

    Note that the 'name' of a ToggleButton changes from 'OFF' to 'ON' depending upon its state.  To click it again when it is on, issue the following:

    // Click the ON button to OFF.
    mSolo.clickOnToggleButton("ON");

-- My app also has one TextView which displays various messages.  I can use Robotium Solo to query if a message is visible:

        // Query whether the message is displayed.
        boolean found = mSolo.searchText("green apples");

-- Robotium also has a set of methods named 'waitForText' with various parameters.  I look forward to using these.

Internationalization

Rich apps display text messages in various languages.  Testcases which search for text strings must be able to access the localized string.   The basic Android test project supports this, and it works with Robotium as well.

I added several strings to be translated in my app-under-test.  From res/values/strings.xml:
    <string name="on">ON</string>
    <string name="off">OFF</string>
    <string name="green_apples">green apples</string>

I internationalized my toggle button to use these values:
    <ToggleButton
        ...
        android:textOn="@string/on"
        android:textOff="@string/off"  >
    </ToggleButton>

Then within the test project...

    // Get localized strings.
    int idOff = com.example.app-under-test-package-name.R.string.off;
    String off = getActivity().getResources().getString(idOff);

    // Click the OFF button to ON.
    mSolo.clickOnToggleButton(off);

Similarly for text fields...

    int idGreenApples = com.example.app-under-test-package-name.R.string.green_apples;
    String greenApples = getActivity().getResources().getString(idGreenApples);

        // Query whether the message is displayed.
        boolean found = mSolo.searchText(greenApples);

Execution

There are two ways to invoke tests...

From eclipse package explorer, right-click the test project-> Run As-> Android JUnit Test.  Eclipse first installs the app-under-test APK and the testcase APK.  Then it switches to the familiar JUnit view which shows a list of tests as they run, along with a progress bar.

From a command-line, issue ADB commands to install both APKs, then issue an ADB command to start the testcase app (specifying your testcase package name and the Android InstrumentationTestRunner).  Example:

    # Install the app-under-test.
    adb install -r app-under-test.apk

    # Install the test app.
    adb install -r testcases.apk

    # Start the test app:
    adb shell am instrument -w  com.example.test-package-name/android.test.InstrumentationTestRunner

In both cases, you can watch the tests run on your emulator or real device.

Execution on multiple devices

If you have several real devices attached to your computer via USB cable, you can run all the tests in parallel, from different command-line windows (or through fancy scripting).  To do this, you must specify the device ID. First query the list of devices (obfuscated results):

    adb devices
    List of devices attached
    S84KD9G0D0F4    device
    P40D9GKKRKD8    device

Then target each ADB command to a specific device.  Example:

    adb -s S84KD9G0D0F4 install -r app-under-test.apk

Summary

Robotium provides a large set of convenience methods for accessing widgets and text fields, which makes your testcases smaller, simpler, and easier to understand.  Very nice.  Study the methods and make use of them.

References:  

Android Test Guide:  http://developer.android.com/guide/topics/testing/testing_android.html
Robotium:  http://robotium.org
Tutorials:  http://lmgtfy.com/?q=robotium+tutorial

1 comment:

  1. Did the method/code you specified under 'Internationalization' para will work in case when we doesn't have the sopurce code of the app??? As we doesn't have the source code of apk.

    ReplyDelete

Note: Only a member of this blog may post a comment.