The geekier side of Riff Pie

Unit tests have all sorts of uses, y’know

Unit tests are marvelous things, I don’t believe it’s even necessary to make a case for them any more. But what is it that they do? Aside from “oh, test units” of course. Well, what they really do is they allow you as a developer, to test certain assumptions you’ve made. You might, for example, assume that certain values passed into a method will cause a certain value to come back, and use unit tests to check that. Or that invalid input will be gracefully handled, rather than bringing the entire app crashing to the ground. That sort of thing. But they can be used to test other assumptions, too. They can be used to test assumptions about, say, the environment in which they’re being run.

Something else unit tests are useful for is a means of communication. Want to know how to use a particular API? A good place to start might well be the documentation, but another good place is often the unit tests for that API. After all, what is a suite of tests, if not a (hopefully) comprehensive example of how to use particular pieces of code? Documentation might well explain that to call method doFoo, you have to construct both a Bar object and a Baz object, and pass them into doFoo, but seeing a unit test actually doing it speaks volumes. But unit tests can also be used to communicate other things. Like what your build environment should be.

See where I’m going with this?

How often have you tried to build some code on your machine, and failed, only to discover later that your box wasn’t set up right for the build? It happens to devs here all the time, and it’s a nuisance. Example: you check out a large project, run the build, and get a whole raft of test failures. The continuous integration build is working fine, no other dev is having similar problems, but you can’t build it. A bit of digging into test failures, and you find that, say, some database tests are dependent on a particular host name being pointed at your local machine. Or a bit of asking around reveals that you need a certain properties file in a certain location, with certain values present, in order to get it working. Now, it’s really questionable that such things need be true at all for a developer build to work, and if you’re in this situation, perhaps your local build is doing too much and it’s time to look at staged builds. However, that’s a different nut to crack.

If you are in a place where these not-really-unit-tests are being run on developer boxes, you can leverage unit tests to ascertain very quickly whether the build environment is correct, and report on what’s missing. Build dependent on a properties file? Write a test that checks for it, early:

@Test
public void testStoreIDPropertiesPresent() {
  String filename = "/etc/company/properties/store.properties";
  File propertiesFile = new File(filename);
  Assert.assertTrue("You don't seem to have the file '" + filename +" ' on your machine", propertiesFile.exists());
}

Likewise, if the database tests rely upon a host name, write a test that makes sure it can connect, and catches the appropriate exception. Or anything else you care to think of. Give it a meaningful name, because in a Maven build, you’ll spot that failing a mile off, without having to go trawling through Surefire reports to find the cause of the failure.

Of course, if there are such quirks of your build, you really ought to be documenting them – a README in the root of the project works wonders, but there’s no harm in checking the environment, rather than just assuming it’s been set up correctly. As a build increases in complexity, the likelihood of there being quirks like dependencies on the environment increases. The worst thing you can do is rely on word-of-mouth to communicate them. Documenting them is a good idea, of course. I’ve heard several different ideas floating around regarding exactly how. “Put them on a wiki page”, “create a ‘starter pack’ full of documents about these things”, “provide a README” etc. All well and good, but the thing about such documentation is, it’s used as a sort-of getout clause by the guy writing it. “I’ve put it all on the wiki, it’s not my fault if nobody bothers to read it”. Err, no. That’s a poor attitude to take. Documentation is a passive medium, we shouldn’t just assume everybody’s read it. Human nature being what it is, it’s folly to do so, and worse to hide behind such assumptions in order to absolve ourselves of responsibility. If “documenting things” was such an infallible medium, it’s unlikely we’d need unit testing in the first place.

I’ve talked specifically about leveraging unit tests to check that a build environment is in order, because it’s something I get bitten by frequently, and see others around me being similarly bitten. I’m sure it’s not the only side-usage of unit tests there is. I’d love to hear about how others are using them for things other than merely testing code.

Comments are closed.