Thursday, July 02, 2009

Android: Testing on the Android platform - Creating tests











This document can be read in Google Docs (http://docs.google.com/View?id=ddwc44gs_186chdgdwdj), cut and paste link if you have problems accessing it.







In a previous post we analyzed the alternatives we have to run our tests on the Android platform and we suggested that the best way to create our tests is into a separate parallel project. As a convention this project will be named as the original project plus the Tests suffix.



For example if we have the MyAndroidProject project tests will be in MyAndroidProjectTests.

Create the project using this name, the same Build Target as the original project, Application name can be empty, for package name use the original project's package name appending the suffix .tests, and you can opt not to create an Activity as it's not needed in most cases.


As usual we will be using a variation of our AndroidTemperatureConverter project and consequently our tests will be in a parallel project named AndroidTemperatureConverterTests.

AndroidManifest.xml

Some changes must be introduced to the default AndroidManifest.xml to run our tests.

First, under Instrumentation, select the Name of the class implementing Instrumentation, usually android.test.InstrumentationTestRunner, the Target package and optionally a Label which is the one that will be displayed in the Instrumentation list as described in Running tests.

Target package is the package containing the code you are testing not your tests.


If you try to run the tests just now, you'll receive

ERROR: Application does not specify a android.test.InstrumentationTestRunner instrumentation or does not declare uses-library android.test.runner
To solve this, let's add android.test.runner as an uses library Application node.

Creating the TestSuite

We need a TestSuite, a Composite of Tests, to simply run all of our tests. Let's name this class AllTests.
Using TestSuiteBuilder we can automatically include all of the tests under the specified package. Obviously, we still don't have any test yet and the TestSuite will be initally empty.

/**
 * Test suite
 */
package com.example.tests;

import android.test.suitebuilder.TestSuiteBuilder;

import junit.framework.Test;
import junit.framework.TestSuite;


public class AllTests extends TestSuite {

    public static Test suite() {
        return new TestSuiteBuilder(AllTests.class)
        .includeAllPackagesUnderHere()
        .build();
    }

}


Running the tests

Using Run as... -> Android JUnit Test will run our, still empty, list of tests.



Conclusion



Organizing the tests into a seprate project gives you the advantage of isolating them and its dependencies in a different APK. Shortly we will be introducing mock objects for our tests, using libraries like EasyMock, and in such case we will be adding it to the build path of the tests project only keeping the tidiness of the target untouched.



 

3 comments:

chromeragnarok said...

hey diego, i'm trying to create a unit test by following your tutorial. I've arrived in which i created a test method for one of my class (called MyClass for example) which resides in my main package (say, com.package.main). And yes, I've put my main project in the test build path configuration.

And then, I tried to create the class in one of my test case in a usual manner of:

MyClass myClass = new MyClass()

And then I tried to run the test project and it always gives Test run failed messages. This happens eveytime I wanted to instantiate any class that resides in my main project. Can you help me on this? Thanks in advance :).

Diego Torres Milano said...

Usually the test is created by:


public class TemperatureConverterUnitTests extends ActivityUnitTestCase<TemperatureConverterActivity> {

private static final String TAG = "TemperatureConverterUnitTests";
private Intent startIntent;

public TemperatureConverterUnitTests() {
super(TemperatureConverterActivity.class);
}
...


where you specify the Activity class these tests are for.

siancu said...

I have the same problem as chromeragnarok, and I don't know how to solve it. I've added the main project to the build path and still it can't find my classes.

I will follow-up tomorrow with a more detailed comment with the actual errors, as now I am too tired and frustrated.

S.