Testing in layers

When doing test-driven development, you can sometimes more easily test stuff by using a “layered” approach. Like today, we set out to make some changes to a fairly complex forecast calculation in one of our apps. The change was minor – basically, we should adjust two inputs to the calculation based on newly introduced user-settable system parameters. We knew that the calculation worked, and we could easily identify the spots to change. But we didn’t want to manually calculate the results of the calculation, in order to be able to change the assertEquals() calls with new values – that is, failing the tests. We felt that there must be an easier way to do this.

So, what we did was to Extract Method on the two values that were about to be adjusted, so that we had some “test points” that allowed us to test a part of the calculation and not the whole thing end-to-end. Then we wrote tests for what these values should be before the change, ran the tests and saw them pass. Then we expanded the tests by giving the calculator a mock database object, so that it could fetch the system parameters, and added asserts for the expected values after subtracting the fetched values. These, of course, failed.

After passing the tests, we felt that we wanted to test the bigger picture, too, to make the tests verify that these extracted methods were in fact used (which wasn’t covered by our new tests). We already had some tests that tested the thing end-to-end, so we just made sure the value was different when the object was set up with a mock database that returned zero values from the system parameters, from when the database contained non-zero values.

This bigger-picture test wasn’t very meaningful on its own, but it guaranteed that the extracted methods were in the execution path, so to speak. The other two tests guaranteed that the values were adjusted properly according to the system parameters. The three tests together covered the change, with much less work than if we had set out to write end-to-end tests to cover equally.

When you practice test-driven development, you should constantly seek to find the simplest way to test each change you make. I think that picking a small piece of the problem to start with is an essential strategy to achieve this. Don’t bother with the entire problem, just plunge ahead with what you feel confident about. You can always find later a way to cover everything – by applying additional layers of tests.

The above was posted to my personal weblog on May 23, 2002. My name is Peter Lindberg and I am a thirtysomething software developer and dad living in Stockholm, Sweden. Here, you’ll find posts in English and Swedish about whatever happens to interest me for the moment.

Posted around the same time:

The seven most recent posts:

  1. Tesugen Replaced (October 7)
  2. My Year of MacBook Troubles (May 16)
  3. Tesugen Turns Five (March 21)
  4. Gustaf Nordenskiöld om keramik kontra kläddesign (December 10, 2006)
  5. Se till att ha två buffertar för oförutsedda utgifter (October 30, 2006)
  6. Bra tips för den som vill börja fondspara (October 7, 2006)
  7. Light-Hearted Parenting Tips (September 16, 2006)