Tuesday, May 17, 2011

Completing the initialize

In this post, we'll (hopefully) complete the conversion of our initialize to read from the database instead of the XML files. The last remaining piece to be converted is this:


/* store question in the AppState question hash */
appState.questionHash.put(new Integer(question.number),
question);

This will be straightforward to replace - just comment it out in the existing one and place it in the new one. I'm going to hold off on a unit test for now because it's going to go away.

Ok, got no failure anywhere. Now, let's drop all calls to the original method.

And all test out to green, except one - the test of words, which has some kind of problem with coordination off the mock application object with the actual one and returns a null on the word map. Since I've got coverage on that one through a couple of other methods, as was revealed in the last post, I'll drop it with a TODO to check on why and forge on.

I'm hoping I actually no longer need the code inserted above. I'm going to check any references, and hopefully just delete the question hash from the program.

Well, first let's commit our changes.

Ok. It turns out that there are about 5 or 6 references. Most of them have to do with checking the size of the current level.

It should be easy and fast to code up a test that validates a method that pulls the number of rows in the current level from the database. I'm going to create a TestDataBaseHelper class. First I'll see if I can replicate an existing test in it, which I originally put in another test class. If that works, I'll move the rest over, then code the new test.

Yes, green. We can put all the current test database methods where they belong, in the new TestDataBaseHelper class.

I'm using the ActivityUnitTestCase because the database needs an activity, and I think it might be faster than ActivityInstrumentationTestCase2.

I'll move the rest of the tests over to the new class. Yes, it's significantly faster. I think because it relies on mocks instead of the real android api, it so doesn't need to go through the Dalvik jvm.

Ok. Now, let's code this method test first. The counts are 669 and 634 for levels 5 and 4, respectively. In fact, I can even use an existing method! Heres the test:

public void testRowCountLevel5() {

ArrayList rows = null;

try {

myDbHelper.openDataBase();
rows = myDbHelper.selectByLevel(5);
myDbHelper.close();


} catch (SQLException sqle) {

throw sqle;

}


Assert.assertEquals(rows.size(), 669);

}


Yes, it passes. Now, since I just need the count, I should add a method, probably to DataBaseHelp, return the count for a given level.

public int getLevelCount(int level) {

ArrayList rows = null;

try {

openDataBase();
rows = selectByLevel(level);
close();


} catch (SQLException sqle) {

throw sqle;

}
return rows.size();
}

And it passes. Let's check the log to see if any of those irksome "can't close database" message snuck in there. It seems ok.




It seems that we could confine the open/exception logic to within DatabaseHelper class, like so:

public int getLevelCount(int level) {

ArrayList rows = null;

openDataBase();
rows = selectByLevel(level);
close();

return rows.size();
}


And heres the shortened test.

public void testRowCountLevel5() {

int count = myDbHelper.getLevelCount(5);

Assert.assertEquals(count, 669);

}

And it passes. None of those nasty exceptions are showing up in the log, either. Let's convert the rest of the data methods and calls to do the open/close.

Good - still green. How about even bringing the create database into the the DataBaseHelper? The client of the DataBaseHelper still needs an instance, so it has to be returned, but I moved it from Utils to DataBaseHelper.

The tests do make you give you a greater level of confidence that your refactoring changes are working. However, that should be dependent on the level of coverage you have in your tests.

But, the ones I have are working, and they impact the area I'm modifiying.

Ok, all set with the database classes and tests.

Now, for my next trick - let's replace the references to the question hash with database calls.

Actually, selectByLevelAndNumber should return a single question, not an array with a single member. Let's fix that. It will involve changing a test and maybe one call.

Good. All green!

Keep on truckin', get rid of the rest of the references.

Well, I'm getting to some cases that aren't covered here. Specifically in settings, for example when the customer select a quiz range that's out of the normal range. Let's cover that in the next post.

No comments:

Post a Comment