TDD FizzBuzz on the Android

I’m starting Android development, but I want to work in a Test Driven development (TDD) way. I’ve looked at the Notepad Tutorial, but each step is too big, and it’s not at all TDD. This blog post describes the first step I took.

After doing Hello World, I went on to FizzBuzz. The problem description is to create an Android app that displays numbers from 1 to 100, but every number that’s divisible by three is replaced with “fizz”. Every number divisible by five is replaced by “buzz”. And if it’s divisible by both, it’s replaced with “fizzbuzz”. It’s pretty much the easiest app you can make that actually has some logic to it.

The issue with TDD is that it’s hard for UI apps. So we move as much logic as possible into the engine, and make the UI a very thin vaneer on top of the engine. (see The Humble Dialog Box.) The engine is developed with full TDD, but we don’t test the UI, except with manual visual inspection.

Creating the engine

I’ve been practicing with the FizzBuzz kata, so I knew this implementation well. I quickly made a pure Java project that defined a FizzBuzzer. It had one public method, to convert an int into a String:

    public class FizzBuzzer
    {
        public String convert(int num) {...}
    }

Once I got that working, it was time to work on the UI.

The UI

I’m working in Eclipse, with the Android plugin. I run directly on my Droid, but you could use the emulator instead. I didn’t use strict TDD for the UI, but I did try to evolve as much as I could. I started with an Android hello world project. I ran it and made sure it worked. Then I changed my Activity to a ListActivity, and added a ListAdapter:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ListAdapter adapter = new MyListAdapter(this,
                R.layout.fizzbuzz_row);
        setListAdapter(adapter);
    }

In TDD style, this gave me a compilation error, so I had to define MyListAdapter. Following The Simplest Thing That Could Possibly Work, I made it a private static class in FizzBuzzActivity. I extended SimpleAdapter because it seemed the simplest solution. This required an empty call to the superclass’s constructor:

    private static class MyListAdapter extends SimpleAdapter {

        private static List<Map<String, String>> data
            = new ArrayList<Map<String,String>>();

        public MyListAdapter(Context context,
                int resource)
        {
            super(context, data, resource,
                      new String[] {}, new int[] {});
        }

I also had to define the resources for the layout. I copied the examples from the Notepad Tutorial, Exercise 1.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <ListView android:id="@android:id/list"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
  <TextView android:id="@android:id/empty"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
</LinearLayout>

and fizzbuzz_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView android:id="@+id/text1"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

That ran, so I needed to fill data. First I used some dummy values.

        static {
            Map datum = new TreeMap();

            datum = new TreeMap();
            datum.put("num", "1");
            datum.put("string", "1");
            data.add(datum);
            datum = new TreeMap();
            datum.put("num", "2");
            datum.put("string", "2");
            data.add(datum);
        }
	...
            super(context, data, resource, new String[] {"string"}, new int[] {R.id.text1}); // in ctor

Then it was time to plug in the FizzBuzz project. The implementation was very easy (as it should be):

        static {
            FizzBuzzer buzzer = new FizzBuzzer();
            Map datum = new TreeMap();

            for (int i=0; i<100; ++i) {
                datum = new TreeMap();
                datum.put("num", Integer.toString(i));
                datum.put("string", buzzer.convert(i));
                data.add(datum);
            }
        }

Eclipse auto-correct linked in the FizzBuzzer project, then I ran and had a solution to the problem. Of course, it was not as easy or straight-forward as that. It involved many false starts and road blocks and looking up APIs in Google. But that describes the happy path thru the development.

It would probably be nice to refactor the logic in the static initializer into a data provider class and move it into the FizzBuzzer project (adding unit tests), but I’ll leave that step to the next app.

Tags: , , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s


%d bloggers like this: