Posted on July 25, 2011 in Android by adam3 Comments »

As a tester and sometimes agile coach-ish I have some pretty strong opinions as to what makes a ‘good’ development culture. Respect, communication, and oh, Testing. While not an organization per se, I think the Android culture is terribly broken. At least from the perspective of its answer to testing. So here is what I would do were I tasked with improving the culture of Android Application development.

First, it has to come from Google. And not just from someone at Google, but someone with the full weight and blessing of the Android division behind it. I’m sure Google has evangelists; an Android Testing one would be fantastic.

Typically, evangelists spend a lot of time on airplanes going to conferences. If you look at pretty much any Mobile/Android focused conference there is, if you are lucky, one session on testing. And if there is, their descriptions imply that are entirely black-box, manual testing focused. But what about automation? What about below-the-covers? What about, gasp, TDD? Mobile apps are complex; testing them is too. Let’s not pretend that just futzing with them in a couple emulators is anything close to be sufficient.

Speaking of TDD, the platform seems designed to make it really hard to do. And what tidbits of information that you can sniff out do not come from inside Google. I would love to see TDD become part of all the tutorials.

To Google’s credit, the component specific testing pages are decent, but it would be nice if the examples that come with the ADK actually had examples of the things that that they say you should test. And while on the specific topic of documentation, if it is suggested in the docs that you should use IntentService more often than Service it would be nice to have some code that does it. (So its not just test specific docs that have issue.)

Actually, I would take the documentation effort even further. Clearly Google wouldn’t want to, or be able to, approve books on Android app development before publication, but they could reach out to publishers and say something like ‘we are trying to address the lack of testing in our culture and would appreciate it if you could ask your authors to include it in their manuscripts as well’. I suspect a lot of the test infection in the Ruby On Rails community is largely because of the test focus of most of the books that are available.

Sites like StackOverflow will also Google where their testing docs lack. So far every question I have come up with has also been there. And usually without an answer that didn’t seem quite right.

Its a bit of a rant after doing some Android development, but I really do believe that within a year Google could turn around the culture from one focused on just what the user interacts with to a mature, TDD-based one similar to the Rails one. (Feels odd calling Rails mature…) The thing that is going to decide [this round of] the phone platform wars is the applications they support. Improving the quality of those apps would be an excellent salvo in that battle.

Posted on July 22, 2011 in Android by adamNo Comments »

All Android applications are comprised of four major components: Activities, Content Providers, Services and Broadcast Receivers. What little testing and test automation that happens in this community is focused primarily on the Activity layer — if at all. A stroll down to your local tech bookstore all but confirms this fact.

But what if you wanted to have a suite of automated checks for something other than Activities? Or, shock!, you want to do something akin to TDD? Well then you would be into the great unknown. And is where I found myself even though I dislike Java, loathe Eclipse and am just learning Android. In this case things worked in my favour since I keep falling off the TDD wagon as I ‘know’ how to do something in Python or Ruby but with Java I’m using it as a learning crutch (stick?).

First, we have the test. Or at least what it ended up at as I understood the problem better. Kinda a Red/Refactor, Red/Refactor cycle.

public void testDatabaseCreated() {
    Cursor cursor;
    Uri url = Credentials.CredentialsColumns.CONTENT_URI;
    cursor = mResolver.query(url, null, null, null, null); 
    assertEquals(3, cursor.getColumnCount());
    cursor.close();
}

Essentially all this does is make sure that the [test] database was created and that it has 3 columns — they could be the wrong three, but at least there is three.

Of course along the way I had to make that file compile by fixing the constructor and understanding the not-really-documented-because-no-one-test-android-apps MockContentResolver. This class will make a backup of your application’s database and restore it when the run is done. Not quite Mocking, but close enough for what is necessary here.

Now to make it Green. Which wasn’t as straight forward as I had hoped. Showing my ignorance, I had thought there is ‘supposed’ to a 1:1 mapping of test classes to code classes. Not in the Android world there isn’t. In this case it is a 1:3 mapping which makes me think I’m not quite doing it ‘by the book’ but there is no book on doing TDD for Android. (Well, there is Android Application Testing Guide which is ok, but there is a definite market need here still.)

The first class I needed to make was the actual Content Provider class, which in typical Java style was a ‘right click and let the IDE to magic for you’. You end up with a class with six overridden methods. But naturally they don’t do anything.

Oh. And have I mentioned I decided to throw the additional twist of having my Content Provider interface with the build-in SQLite database?

Android is I guess what you would call an Event Driven environment where you override specific events to get your desired behaviours. So in my Content Provider I needed to override the onCreate method first.

@Override
public boolean onCreate() {
    dbHelper = new DatabaseHelper(getContext());
    return true;
}

Which creates our DAO for this particular Content Provider. DatabaseHelper is actually an inner class of the Content Provider.

public class DatabaseHelper extends SQLiteOpenHelper {
    public DatabaseHelper(Context context) {
       super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
 
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + CREDENTIALS_TABLE_NAME + " (" + CredentialsColumns.CREDENTIAL_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
                                 + CredentialsColumns.USERNAME + " VARCHAR(255),"
                                 + CredentialsColumns.PASSWORD + " VARCHAR(255)" + ");");
    }
 
    @Override
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
 
    }
 
}

As you can see, I haven’t worried about doing the onUpgrade scenario yet. (And that the new class wizard names arguments horribly.)

I had tried originally to create the DatabaseHelper class as a separate class so it cold be tested in isolation, but there is no information anywhere that I could find that describes how to do it. So I put it as an inner class as the examples I could understand all had it there.

The third class that I needed to create just so my simple test could pass is the one that represented the actual table. It is pretty boring, except for the CONTENT_URI line which is important.

public final class Credentials {
    private Credentials() {}
 
    public static final class CredentialsColumns implements BaseColumns {
        private CredentialsColumns() {}
 
        public static final Uri CONTENT_URI = Uri.parse("content://" + SauceLabsCredentialsProvider.AUTHORITY + "/credentials");
 
        public static final String CREDENTIAL_ID = "_id";
        public static final String USERNAME = "username";
        public static final String PASSWORD = "password";
    }
}

Access to/from a Content Provider is done through a URI. (If you are familiar with RoR RESTful URL’s you’ve got the concept.) In this case the CONTENT_URI is specific to a credentials table that the Content Provider has the ‘Authority’ to access. To be compliant with the spirit of Android development, you don’t do raw SQL against the database, but instead do queries against a URI.

This is enough code to create a database on the emulator/device and to allow my test to create the mocked one.

Or would have been if I had remembered to register it in the manifest and then didn’t totally screw up my environment with a package rename gone hopelessly wrong. (If you get a deployment claiming the Content Provider is already installed, check that your paths in terms of code match your manifest.)

Once I solved that I still had a null pointer on the query itself — because I hadn’t implemented it yet. (It was late and my brain was shutting off…)

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setTables(CREDENTIALS_TABLE_NAME);
 
    SQLiteDatabase db = dbHelper.getReadableDatabase();
 
    Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
    return c;
}

And then I was green.

Now what I have facing me is

public void testInsertCredentials() {
 
}
 
public void testQueryCredentials() {
 
}
 
public void testDeleteCredentials() {
 
}

which will force me to flesh out more of the overridden methods. Only when I have those all green will I actually wire it up to an Activity. So it is possible to do something like TDD for Android Content Providers — its just not straight forward nor documented well. Or at all.