«« Positively Fifth Street Database Perf and Object Creation »»
blog header image
Unit Testing a Database Abstraction

In the AudioMan project there's a need for data storage: the metadata is cached so that it can be displayed quickly instead of read from files all of the time.

Right now this data storage is implemented using the Java collection framework. While it was easier than hooking up a database, it's limited because all of the "indexes" have to be set up manually to "query" the collections.

Expanding the functionality of AudioMan requires better access to this data, being able to have access to all of the "columns" in the "tables" without having to create specific "indexes" for them. This analogy to a database is the easiest way to describe how limited this Java collection-based repository actually is.

The database abstraction is an API that has methods for specific queries that return arrays of objects. This separates the database implementation from the rest of the code, reducing coupling. Sure, every time you want to make a new query you need to make a new method, but the abstraction is invaluable.

So I'm going to replace the collections repository with a real relational database. The good news is that the repository abstraction already has 171 regression tests against it. These tests will ensure that the new repository functions the same way as the old one, assuming the tests were comprehensive. That's a dangerous assumption to make of course, so an audit would be a good idea too.

So now we're at unit testing this repository. The best way is with a clean database on every unit test method so that data from previous tests doesn't contaminate future tests. Even worse, some people set up tests like dominoes so that if early tests fail, the later tests fail too because the database doesn't contain the right data. It's better to make the tests completely independent even though it takes more time to set up each test and typically it takes longer to run the whole suite.

But I won't have to clear the database completely between unit test methods, I can just blank the tables and the schemas can stick around. As well, since I'm not making a web application I don't have to worry about production and testing databases like Andrew has been -- they will be the same one, because the deployed application starts with a fresh database. Web apps sometimes don't have this luxury, the deployment being a sticky combination of production and development web servers and databases out of your jurisdiction.

Posted at June 25, 2004 at 05:13 AM EST
Last updated June 25, 2004 at 05:13 AM EST
Comments

With our fourth year project, I always found that testing the database was the most difficult thing to do correctly. In order to test that data is written correctly, you have to read it from the database, and make sure the same thing that went in, comes out. But when something fails, is it the writing, or the reading? it's kind of hard to tell. If you think you put A in, and B comes out, is it because you wrote it wrong, or because you read it wrong. And maybe your test pulls the right data out, but when you test the actual read methods, they don't work, possibly because the test wrote the wrong data, or because they actually don't work. It's all very confusing.

I just don't like that you can't really just do a check, with A==A, and be satisfied that the test worked. When you're writing as much code for the test as there is for the method, you're bound to make mistakes. You'll probably end up writing tests for the tests.

» Posted by: Kibbee at June 25, 2004 08:06 AM

Just a couple of thoughts. If you are testing your java reading, part of your test setup could be to put your db (with sql) in a known state and then you can check that the reading works.

And more testing code than program code isn't a bad thing. I'd think that more likely you're more likely to find problems.

Keeping things in sync with a db sucks, no doubt about it. But I think as sw continues to evolve, we'll see more (and better) ways to manage persistence automatically to let programmers work on the business logic and the not the boring part (IMO).

With things like container managed persistence (CMP) now, all you have to do is map the db structure to your entity objects and it does the rest for you. I think there's the same thing for .NET too, but I don't remember what it's called.

» Posted by: Jim at June 25, 2004 10:16 AM

You mention using a db. What db are you thinking of using? And have you done any homework on SQLUnit? (http://sqlunit.sourceforge.net)

Yeah I know...lots of questions and no answers for you :-P

» Posted by: roy at June 26, 2004 01:26 AM

I'm using the Java database hsqldb:

http://hsqldb.sourceforge.net

» Posted by: Ryan at June 26, 2004 02:33 AM

Some wisdom, I hope...

Check my blog :-)

http://www.beernut.ca/andrew/archives/000750.html#000750

» Posted by: aforward at July 2, 2004 03:25 PM
Google
 
Search scope: Web ryanlowe.ca