by Mihal Celovski

A few months ago we started to work with the Android platform, which was something completely new for us. Although Android applications are developed in Java, the approach is somehow different. The architecture of Android applications and way of execution differ from the standard Java applications. Quality is one of key factors in our Agile Software Factory and when I say that I think of reliable, well-tested applications. Thanks to Android testing API and test framework called Robotium there is more than enough tools for testing.

Since we are using Eclipse, content of this post will be limited to that IDE. This post is intended to be a brief description of Android app testing and I hope it will serve well for beginners. My next post will be about Robotium.



1. Create test project.

Tests, like Android applications, are organized into projects. To set up a test environment for your Android application, you must first create a separate project that holds the test code. For example, imagine that we have Android project called MyAndroidApplication. To be able to test it you have to create new Android project, called, for example, MyAndroidApplicationTest. New project follows the directory structure used for any Android application.

These are the steps to create new Android test project in Eclipse:

go to: File -> New -> Other -> Android -> Android Test Project – new dialog opens

give project a name

choose location for your new project

choose API level (Android platform your application runs on)

give your application a name

choose package name

choose main activity name (optional)

specify minimal API level your application will require

You can do all this steps automatically if you choose in new Android test project dialog an existing Android project (field “An existing Android project”). Then all things like: project name, location, API level, package name etc., will be set automatically and the result directory and package structure will be like this:

The interesting thing here is that if you want to test plain-old java code you should make new source folder in your application project and place tests there, not in android test project.

2. Write your test

Android testing framework

Android has a built-in testing framework that includes a subset of JUnit. All of its test-case classes are directly or indirectly derived from JUnit’s TestCase and extended to use in Android specific way. If you’re already familiar with JUnit, it’s not that difficult to use the Android Testing Framework. The basic architecture is shown on picture .

InstrumentationTestRunner is the test case runner, and you must use it to run JUnit tests.

Instrumentation is a set of control methods in the Android system. It controls an Android component independently of its normal lifecycle. Instrumentation invokes lifecycle methods directly.

Test case classes

The most commonly used test case classes are:

TestCase – plain old JUnit test case. It can be extended to test different things that are not related strictly to Android like utility classes.

AndroidTestCase is used when we need injected context of activity, for example to get UI objects and test their behavior, or to test data access objects. It extends JUnit’s TestCase. If you run this test case on emulator nothing will happen.

ActivityInstrumentationTestCase2 is the version of older ActivityInstrumentationTestCase that is deprecated in Android SDK 1.5. It provides UI and functional testing for a single activity. Since the activity is launched for each test, you can see how the UI is being tested in the emulator. The activity being tested is launched and finished before and after each test.

ActivityUnitTestCase test case class tests a single activity in isolation. Before you start the activity, you can inject a mock Context or Application, or both. You use it to run activity tests in isolation, and to do unit testing of methods that do not interact with Android.

ApplicationTestCase provides testing for Application classes. It can be used to test the lifecycle of an application.

The MonkeyRunner and UI/Application Exerciser Monkey are tools called from command line. The first one is using for test programs written in Python, the second one is used for functional testing by sending pseudo-random streams of keystrokes, touches, gestures to a device.

Example:

We want to test if MyAndroidActivity displays TextView with predefined resource string.

public class MyAndroidActivityTest extends ActivityInstrumentationTestCase2 { private MyAndroidActivity mActivity ; // the activity under test private TextView mView ; // the activity's TextView (the only view) private String resourceString ; public MyAndroidActivityTest ( ) { super ( "com.example" , MyAndroidActivity. class ) ; } @Override protected void setUp ( ) throws Exception { super . setUp ( ) ; mActivity = this . getActivity ( ) ; mView = ( TextView ) mActivity. findViewById ( com. example . R . id . textView ) ; resourceString = mActivity. getString ( com. example . R . string . hello ) ; } /** * Test if activity has TextView with predefined id displayed. */ public void testPreconditions ( ) { assertNotNull ( mView ) ; } /** * Test if activity's TextView displays text from resource. */ public void testText ( ) { assertEquals ( resourceString, ( String ) mView. getText ( ) ) ; } } public class MyAndroidActivityTest extends ActivityInstrumentationTestCase2 { private MyAndroidActivity mActivity; // the activity under test private TextView mView; // the activity's TextView (the only view) private String resourceString; public MyAndroidActivityTest() { super("com.example", MyAndroidActivity.class); } @Override protected void setUp() throws Exception { super.setUp(); mActivity = this.getActivity(); mView = (TextView) mActivity.findViewById(com.example.R.id.textView); resourceString = mActivity.getString(com.example.R.string.hello); } /** * Test if activity has TextView with predefined id displayed. */ public void testPreconditions() { assertNotNull(mView); } /** * Test if activity's TextView displays text from resource. */ public void testText() { assertEquals(resourceString,(String)mView.getText()); } }

3. Run tests in Eclipse

To run a test in Eclipse, you have two choices: Run a test just as you run an application, by selecting Run As… > Android JUnitTest, or to create an Eclipse run configuration for your test project. You must either attach a device to your computer or use the Android emulator to run test. If you use the emulator, you must have an Android Virtual Device (AVD) that uses the same target as the test package.

Important thing to say is that, if it is possible, it is better to run tests on actual device. The Android Emulator with Android Virtual Devices configured for the hardware, screens, and versions you want to test is also good option but in situations when we need to test camera emulator is not sufficient.

WHAT TO TEST?

This is good question because it is as important as to know how to test. The most unit testing is specific to the Android component you are testing: activity testing, content provider testing, service testing etc.

If you test activity the most common things to test are: input validation and response to invalid input, lifecycle events, runtime configuration changes: change of default language, screen orientation, screen size and resolution.

The usually tested things for content providers are: standard provider interactions, business logic, public provider as contract.

Android services have the lifecycle like activities. One way to indicate if service lifecycle methods were successful is to set some global variable just for testing purpose.

The most common runtime situations you want to test are:

Change in orientation: what should happen when screen orientation is changed?

Change in configuration: change in configuration also triggers the default behavior of destroying and then restarting the foreground Activity.

Battery life: you should test do your application minimize battery usage.

Dependence on external resources: network access, SMS, Bluetooth, or GPS. You should test what happens when the resource or resources are not available.

CONCLUSION

Since we are relatively short time in Android application development, we have not experienced all good and bad aspects of testing. Certainly we can agree with that it is better to test the application on a physical device rather than on an emulator because the emulator has a limited capacity.

The great thing is possibility to handle Android projects and tests with project management tools like Maven and use it with CI tools like Jenkins. There is one nice blog about Android-Maven-Jenkins integration.