Abandoning test-first programming


Ever since I started java programming, I’ve been using JUnit for unit testing my code, and it wasn’t long before I found myself practicing test-first programming. I’ve always enjoyed working in this fashion: I like the way it makes you think about your design when creating tests, and I love the feeling of control you get when you have an extensive set of unit tests. However, I’ve been wondering if all this was actually saving me time. I would often spend a considerable amount of work setting up an environment for my unit tests, only to find that after implementing the production code, the tests worked first time. I started having doubts: if the unit tests don’t help me find massive amounts of bugs, then why bother writing them? Sure, I like writing tests, but it should be more than just a way to have more fun programming to be a really worthwhile activity (at least it should for the projects I do professionally…).

So, when I was assigned the task of adding some functionality for a fairly big legacy system, I decided to abandon test-first programming. The system was built without much regard to testability, so creating a test harness would have been a major task anyway, and test-first programming wasn’t practiced by the other team members (as was unit testing altogether, for that matter), so I figured I could get away with it. I started programming old-skool: sketching a design in my notebook, programming a chunk of functionality, manually testing the new code, and doing a manual regression test of the functions that I thought may have been affected by the new code.

As I suspected, working without writing unit tests didn’t seem to have so much impact on the number of bugs in my code. Because I couldn’t rely on unit tests, I would be more careful when writing the code, which probably created the same effect as writing unit tests. But the longer I spent working on the system, the more I resented the long build – test cycle that was starting to emerge. Whenever I had completed a piece of coding, I had to do a full build, deploy, and restart of the appserver. Then I had to manually navigate through the web UI, and test the new functionality by hand. The whole cycle would take me 5 to 10 minutes, for even the most basic change in the code.

Another thing I started to notice was a growing feeling of anxiety when I had to refactor some existing code to accommodate for a new feature. I needed to have a clear picture of the system in my head at all times, and constantly be aware of the effects that the change could have on other parts of the system. I managed, because my changes were localized to a fairly isolated part of the system, but it increasingly felt like juggling with ever more balls.

I then realized that test-first programming isn’t about finding bugs, or even preventing bugs. It’s about creating a fluid build-test cycle, by being able to test your changes in a matter of seconds. It’s about freeing your mind of always having to think about the impact your change may have on the other parts, so you can concentrate on the change itself. It’s also about helping you create loosely coupled, testable designs, although years of doing test-first programming may have taught me to do that even without unit tests. But the actual unit testing, in the sense of finding bugs in your own code, is just a nice extra.

For my next project, I wil be doing test-first programming again. And now, I’ll never go back.

  1. Nog geen reacties.
(wordt niet gepubliceerd)
  1. Nog geen trackbacks.