A couple of weeks ago, I happened to be in the right place at the right time (the first ORD Session) when Google hooked a bunch of developers up with an Android Dev Phone 1.
I’d been interested in Android for awhile because it’s a more open platform than the iPhone, and the code is Java (I’ve never worked in Objective-C), so I was excited.
After my initial excitement of hacking around and getting things to work, I decided to regain my discipline and figure out a workflow for TDD. The good news is that JUnit is built right into the Java framework that Android app have available.
The less-good news is that writing and running tests on Android isn’t as well-documented as many other facets of the application framework. I’d like to share my setup, which doesn’t depend on any specific IDE or text editor.
I’m assuming Mac or Linux here, but I’m sure Windows would only require minimal changes. Other assumptions:
- The Android SDK is installed
- Android tools directory is on the
Ant is on the machine and on the
tools directory is the main one, not the one below
platforms. In my case:
Let’s get started by creating a project with the command-line utility, which will give you the test directory structure and build files that you need (you won’t get these with the Eclipse or IntelliJ plugins, for instance).
Of course, you can read documentation for the android command to see more details, but here’s what we’re doing:
All of these options are required (
-n, the project name, is optional,
and I’ve left it out above)
-tis the build target platform
-pis the path of the new project to create
-ais the first Activity that you want to create
-kis your package name
Next, we want to create an AVD if one doesn’t already exist—it’s an emulator for the phone operating system. We can check to see if one exists already first:
If you don’t have an AVD already, create one:
You’ll be asked if you want a custom hardware profile (if you don’t, just hit Return).
-nis the name of the new device
-tis the target platform, as before
At this point, let’s go ahead and fire up the emulator, making sure to match the name to the one you created. It’s good to make sure that our state at this early point is a good one.
Here I’m launching the emulator (AVD) in
the background so I don’t need to open up a new Terminal window. You’ll get some output
in your terminal window; if it bothers you,
Ctrl-L will freshen it up.
Now we’ll build and install both of your apps (the test package is really a separate application, which is a good idea to keep the tests out of the eventual deployment package anyway):
The debug target isn’t actually defined in either buildfile
but is available nonetheless (see
$ ant help for other targets you might not
otherwise find). This takes care of bundling resources, compiling, converting classfiles
.dex format, and packaging.
adb is not
ant—it’s the Android Debug
Bridge, and it’s invaluable for working with the emulator. The
adb install reinstalls the package if necessary. Now, this is pretty
redundant-looking, but just remember that the tests directory is a sort of parallel
structure with your project directory, and you need both.
It’s time to run the default test suite that the
android create project call has
given us (this can be run either from tests directory or from the root of the project):
Of course, you’ll want to substitute your package and activity names for the ones in my examples. It’s very important to realize that you’ve just compiled and installed your software on the emulator and are running tests on it there.
In order to do TDD, you’ll need to recompile changed code and reinstall on the emulator. I hope that one day there will be a way to avoid going through the emulator each time, but this is the only method I’ve been able to get working so far.
Now we need to actually add a real test to
tests/src/com/colinwjones/TicTacToeTest.java. Here, an
IDE like IntelliJ or Eclipse comes
in handy, especially if you’re just starting with Android and aren’t sure of the methods
you might want to use.
Building our test package at this point will fail, since no resource with the
new_button id exists yet. Let’s do it anyway to see the first failure and
guide us to our implementation code (running this from the tests directory):
The error tells us where to go next: we’ll implement the button in
/layout/main.xml (making sure to set the right ID on the button).
Since we changed the main layout, the implementation package needs to be built first, then the test package:
Now run the tests again:
Great! Now we have a proper failure:
We just need to add the right text in the XML layout:
Let’s rid of the default “Hello, World” TextView in
while we’re at it. Now rebuild, reinstall, and re-run tests:
This is getting annoying typing all these commands: we’re going to want to write a shell script or Ant task to do this for us. But for the time being, we’ll plod through (that was the last time, though). Now we’re passing:
It’s a bit strange that the test runner claims we have 2 tests: each test class will add one of its own.
Now that we’ve seen how to get the tests running, let’s automate it by
adding Ant tasks to the
build.xml in the main project directory.
You’ll need to set the environment variable
for this exact task to work, or you can provide the full path to
Now we can just run:
from the project directory (assuming the emulator is already up and running
emulator -avd ColinPhone &), and we’ll be good to go.
Honestly, it’s a pretty simple process: the key for me was in using the Android command-line tools rather than IDE plugins. It helped me to understand the build process and get beyond the initial frustration of not having the IDE do the work for me.
I imagine things will change a bit for Windows users, so please leave comments if there’s anything drastically different, or if things change for Mac/Linux users as the framework develops.
I do hope this will help someone else to get set up and save the headache I had when first discovering Android.