Test-Driven Development Myths

tdd

Our projects tend to run 85%-95% test coverage (using Cobertura integrated with Maven as our default reporting system). Once in a while we will run into teams that say that they do TDD, but also are running closer to 15%-20% coverage.  There are a couple of myths at work here:

  • We don't test getters & setters (aka properties)
  • We'll add tests later
  • We don't write tests for prototypes

Let's take a quick look at all three of these...

We don't test getters & setters (aka properties)

This one cracks me up - it's just silly.  The argument goes that writing tests for all your JavaBean-styled objects (aka properties) is time-consuming and pointless.

First, it's not time-consuming. Use a project like openpojo and you just need to add each object to a single test case (it's in Maven Central already, so you just need to add the dependency). You will spend more time talking about doing it with another developer than implementing it.

Second, it's absolutely not pointless. Aside from the fact that it gets you closer to a nice, high coverage number, it actually does catch a lot of bugs. I've found several problems with POJOs where an enterprising developer hand-coded one or two properties to handle some odd business logic edge-case. If you are doing any kind of serialization (traditional Java, XML, or JSON, for example) and your POJOs break the JavaBean spec, you'll have problems.  Same thing if you are sticking your POJOs in an HttpServlet Session (a bad idea, but that's another topic...).

We'll add tests later

You won't.

Aside from that, this is the most obvious sign that you aren't doing real TDD. Real TDD is actually pretty simple - when you sit down to do work (add a feature or fix a bug), the first thing you do is create a test case. You then use the test case to generate the needed code as you go along.

Sticking with this strategy does several things. It keeps you focused on the task. It ensures that you only build what you need. It's a heck of a lot faster to run (and debug) a test case in your IDE than to create a dummy UI shim and tab back and forth. When you are done, not only do you have a nice implementation but you already have the matching test cases.

The nicest part is that it naturally pushes you toward good design. Stateless systems. Keep the business logic in nice, easy to test modules. Keep the UI thin and lean.

We don't write tests for prototypes

As discussed in the previous section, you'll actually build your prototypes a LOT faster if you are writing code driven by your test cases.

Secondly, the tests become the body of work representing your requirements. As the test suite grows, you'll find that you want to go back and refactor stuff - you're learning, working on the prototype, right?  It's a lot easier to refactor with confidence if you have a nice test suite backing you up.

Several times now, I've actually thrown away the prototype implementation but kept the test suite - it's the valuable bit, the requirements.

TDD FTW

There are a LOT of resources available on TDD - countless books, articles, tutorials... and this isn't new stuff. Here's a nice TDD overview to get you started, and every major IDE includes documentation on how to get started.