Android unit testing basics 

Joined:
07/27/2010
Posts:
128

September 07, 2011 16:46:14    Last update: September 07, 2011 19:23:00
The Android unit test framework is based on JUnit 3, not JUnit 4. Test cases have to extend junit.framework.TestCase or a subclass (such as android.test.InstrumentationTestCase). Tests are identified by public methods whose name starts with test, not methods annotated with @Test (as in JUnit 4).

An Android test suite is packaged as an APK, just like the application being tested. To create a test package, first you need to identify the application package it is testing. Google suggests to put the test package source in a directory named tests/ alongside the src/ directory of the main application.

At runtime, Android instrumentation loads both the test package and the application under test into the same process. Therefore, the tests can invoke methods on the application components directly.

There are two ways to start a unit test package:
  1. With Eclipse ADT:
    Select File/New/Project/Android/Android Test Project
    Fill in the required fields.

  2. With command line utility:
    android create test-project -m <main_path> -n <project_name> -p <test_path>
    


    It seems like the utility does not take relative paths as main_path:
    [freyo@fred HelloWorld]$ ~/android-sdk-linux_86/tools/android create test-project -m . -n HelloWorldTest -p tests
    Error: Main project's directory does not exist: .
    [freyo@fred HelloWorld]$ pwd
    /home/freyo/work/HelloWorld
    [freyo@fred HelloWorld]$ ~/android-sdk-linux_86/tools/android create test-project -m ../HelloWorld -n \
    HelloWorldTest -p tests
    Error: Main project's directory does not exist: ../HelloWorld
    
    [freyo@fred HelloWorld]$ ~/android-sdk-linux_86/tools/android create test-project \
    -m /home/freyo/work/HelloWorld -n HelloWorldTest -p tests
    
    Found main project package: com.android.helloworld2
    Found main project activity: HelloWorld
    Found main project target: Google APIs (Google Inc.)
    Created project directory: tests
    Created directory /home/freyo/work/HelloWorld/tests/src/com/android/helloworld2
    Added file tests/src/com/android/helloworld2/HelloWorldTest.java
    Created directory /home/freyo/work/HelloWorld/tests/res
    Created directory /home/freyo/work/HelloWorld/tests/bin
    Created directory /home/freyo/work/HelloWorld/tests/libs
    Added file tests/AndroidManifest.xml
    Added file tests/build.xml
    Added file tests/proguard.cfg
    



However, there are differences between the files generated by the ADT and command line utility:
  1. ADT generates the directory structures and AndroidManifest.xml. It doesn't generate stub code for the actual test.
  2. Command line utility generates a stub test class as well as the directory structures and AndroidManifest.xml.
  3. ADT puts the test project alongside the application being tested, not inside the project in a tests/ directory.
  4. ADT can generate test projects for existing applications or for the test project itself. Command line utility cannot generate self-testing projects.
  5. Package names are different: for ADT, the test package name and Java package name for the test classes are the same; for command line generated code, the Java package name for the test classes are the same as the application being tested while the test APK has a different package name.


AndroidManifest.xml and test stub generated by the command line utility:
  1. AndroidManifest.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
              package="com.android.helloworld2.tests"
              android:versionCode="1"
              android:versionName="1.0">
        <!-- We add an application tag here just so that we can indicate that
             this package needs to link against the android.test library,
             which is needed when building test cases. -->
        <application>
            <uses-library android:name="android.test.runner" />
        </application>
        <!--
        This declares that this application uses the instrumentation test runner targeting
        the package of com.android.helloworld2.  To run the tests use the command:
        "adb shell am instrument -w com.android.helloworld2.tests/android.test.InstrumentationTestRunner"
        -->
        <instrumentation android:name="android.test.InstrumentationTestRunner"
                         android:targetPackage="com.android.helloworld2"
                         android:label="Tests for com.android.helloworld2"/>
    </manifest>
    

  2. Test stub:
    package com.android.helloworld2;
    
    import android.test.ActivityInstrumentationTestCase2;
    
    /**
     * This is a simple framework for a test of an Application.  See
     * {@link android.test.ApplicationTestCase ApplicationTestCase} for more information on
     * how to write and extend Application tests.
     * <p/>
     * To run this test, you can type:
     * adb shell am instrument -w \
     * -e class com.android.helloworld2.HelloWorldTest \
     * com.android.helloworld2.tests/android.test.InstrumentationTestRunner
     */
    public class HelloWorldTest extends ActivityInstrumentationTestCase2<HelloWorld> {
    
        public HelloWorldTest() {
            super("com.android.helloworld2", HelloWorld.class);
        }
    
    }
    



To run tests:
  1. From Ecplise: Right click test project and select RunAs/Android JUnit Test
  2. From command line:
    $ adb shell am instrument -w com.android.helloworld2.tests/android.test.InstrumentationTestRunner
    

Share |
| Comment  | Tags