Showing posts with label unit test. Show all posts
Showing posts with label unit test. Show all posts

Wednesday, July 6, 2011

Book on Android testing

Oh, those were the days, when Android was pre-1.0! Documentation and training material was scarce, platform sources were not yet released, no device in sight. It was then when Diego Torres Milano first published a post about unit testing on Android. 3 short years later Android is the dominant smartphone platform but there has been no book dedicated to Android testing. Who else could have written that book than Diego?



Let's start with a disclaimer: I was a reviewer of this book. I almost met Diego once when we both presented at Droidcon London 2009 but I had to leave early and we didn't. Believe or not, at the end of 2009 Android enthusiasts could still fit into a medium-sized presentation hall.

The book starts with a general introduction on testing then it starts to focus on Android testing. Android has JUnit integrated but the Android-specific classes are not over-documented. The Android test case classes are explained one by one with examples then we learn, how the principles of Test Driven Development can be applied to our Android projects. The second half of the book deals with useful techniques like automatic test execution, ways of performance and coverage testing and different tools for Behaviour Driven Development and Continuous Integration.

All in all, there is plenty of information in this book that is difficult to find or figure out. I can warmly recommend this book to everyone who builds production-quality software for the Android platform.

Sunday, November 23, 2008

JUnit in Android

Now that we have the instrumentation framework in our basket and we are able to connect instrumentation objects with a test runner, it is time to put a bit of structure into out tests. The number of test cases grows quicky. If there is no way to organize them or they depend on each other in a subtle way, test case maintenance soon becomes a nightmare. Experience shows that in case of a resource-constrained project, test effort is the first to suffer cutbacks and if the test cases are not maintained properly, the team or the developer may soon feel that the test set is too much hassle compared to the value the tests provide. The result is a fallback to the default, "chaotic" way of development with the predictable drop of quality.

The popular JUnit test framework is integrated into Android. JUnit, if used properly, brings two major benefits to the test implementation.
  • JUnit enforces the hierarchical organization of the test cases
  • The pattern JUnit is based on guarantees the independence of the test cases and minimizes their interference.
Entire books have been written about JUnit and unit testing therefore I will restrict myself to the minimum in explaining the test framework. JUnit's main building block is the TestCase class. Actual test case classes are inherited from TestCase. One TestCase child class contains one or more test methods, these test methods are the real test cases and the TestCase descendants are really already test groups. By convention, the test method names are prefixed with "test" (like testThis(), testThat(), etc.). JUnit can discover the test methods by itself if this convention is respected, otherwise the test method names have to be declared one by one.

The most important impact of using JUnit is the way one test method is executed. For each test method, the TestCase descendant class is instantiated, its setUp() method is invoked, then the test method in question is invoked, then the tearDown() method is invoked then the instance becomes garbage. This is repeated for each test method. This guarantees that test methods are independent of each other, their interference is minimized. Of course, "clever" programmers can work around this pattern and implement test cases that depend on each other but this will bring us back to the mess that was to be eliminated in the first place. JUnit also provides ways to collect test classes into test suites and organize these suites hierarchically.

JUnit has been included into Android and Android-specific extensions were provided in the android.test package. Android test cases classes should inherit from android.test.AndroidTestCase instead of junit.framework.TestCase. The main difference between the two is that AndroidTestCase knows about the Context object and provides method to obtain the current Context. As many Android API methods need the Context object, this makes coding of Android test cases much easier. AndroidTestCase already contains one test method that tests the correct setup of the test case class, the testAndroidTestCaseSetupProperly method. This adds one test method to every AndroidTestCase descendant but this fact rarely disturbs the programmer.

Those familiar with the "big", PC-based JUnit implementations will miss a UI-oriented TestRunner. The android.test.AndroidTestRunner does not have any user interface (not even console-based UI). If you want to get any readable feedback out of it, you have to handle callbacks from the test runner.

You can download the example program from here.

Our example program contains a very simple test runner UI, implemented as an Activity. The UI provides just the main progress indicators, details are written into the log so this implementation is nowhere near to the flexible test runners of the "big" JUnit. The test suite contains two test case classes. One of them (the MathTest) is really trivial. It demonstrates, however, the hidden testAndroidTestCaseSetupProperly() test method that explains the two extra test cases (the test runner will display 5 test cases when we have really only 3). The main lesson from the other test case class (ContactTest) is that individual test cases must be made independent from each other. This test case class inserts and deletes the test contact for each test method execution, cleaning up its garbage after each test execution. This is the effort that must be made to minimize interference. ExampleSuite organizes these two test classes into a suite. As we respected the JUnit test method naming conventions, we can leave the discovery of test methods to JUnit.



At this point, we have everything to write structured, easy to maintain tests for Android, using the Android test instrumentation mechanism to drive the UI. This will be my next step.

Sunday, November 16, 2008

Test-driving Android GUI

It happened again that I received an e-mail from somebody asking whether there is a way to automate the testing of Android user interfaces. I did not know so I went after the issue and to my utter surprise, I discovered that an entire unit test framework has been developed into Android while I looked the other way. In this blog entry, I will describe my experiences with the Android instrumentation framework.

You can download the example program from here.

The idea behind Android instrumentation framework is that there are instrumentation components that resemble a lot the usual Activities. The purpose of these instrumentation components, however, is to test-drive other, normal Activities. Let's see the example program!

Install the package in the bin directory as usual:

adb install instrumentation-debug.apk

If the package has been installed before, you first have to uninstall it. This is new in the 1.0 version of the SDK, previously the new installation would simply overwrite the old one.

adb uninstall aexp.instrumentation

Two applications appear in the application folder. "Calculator" is a primitive calculator application used as test target. You can launch it independently and try it yourself. If you launch "Calculator instrumentation launcher", you will be confronted with a button to launch Calculator instrumentation. Once you push it, the calculator launches but its input keypresses will come from the instrumentation component. You will see the input fields filled up automatically, the addition button pushed and the result displayed. Then both the calculator instance and the launcher will disappear but if you check the logs (adb logcat), you will see that the test was successful.


The key instruction is in CalculatorInstrumentationLauncher.java where the instrumentation component is launched:

startInstrumentation(
new ComponentName(
CalculatorInstrumentationLauncher.this,
CalculatorInstrumentation.class ),
null,
null );

This launches CalculatorInstrumentation component which is a descendant of android.app.Instrumentation. The instrumentation component resembles a normal Activity, except that it is able to drive user input of other activities. This time we launch the Calculator, feed in keypresses (sendCharacterSync()) and invoke one of its method to obtain the result. Note the usage of runOnMainSync() method when we invoke Calculator's method to obtain the result.

It is definitely cool that Android has a user interface-oriented unit testing framework built into the platform. Maybe I am ignorant but I am not aware of any other platform that has this capability. In order to Test Driven Development (TDD), we need a proper unit testing framework and Android has even JUnit integrated. More about that later.