Up and running with TDD on Android

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.

Note: The tools directory is the main one, not the one below
platforms. In my case: /Users/colin/lib/android/tools.

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:

The debug target isn’t actually defined in either buildfile
(build.xml or tests/build.xml),
but is available nonetheless (see $ ant help for other targets you might not
otherwise find). This takes care of bundling resources, compiling, converting classfiles
to Android’s .dex format, and packaging.

Note that adb is notant—it’s the Android Debug
Bridge, and it’s invaluable for working with the emulator. The -r option
to 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):

1 $ ant debug

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).

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:

from the project directory (assuming the emulator is already up and running
with 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.