Never miss one of my articles: Readers of my newsletter get my articles before anyone else. Subscribe here!

Do you write //FIXME or //TODO comments? I surely do. At least I did- I am trying to get rid of them right now. I am trying to get rid of them by replacing them with a failing unit test - A test that is ignored. Now I want to tell you how and why I do it.

Why Do We Write Those Comments?

When you work on a feature, you should concentrate on the happy path first. You should try to get some running code before thinking about all the gory little details. So you write:

//TODO handle invalid date range before marking the feature as complete

Sometimes you are gradually automating some manual process. In your MVP, you’ll have to do some manual steps when there is a credit card charge-back. You leave this as a manual step, because it is a rare event, but you’ll add a comment:

//TODO here we could extend the code to process charge-backs automatically

Sometimes some error handling is not even part of the current release. Yes, the app crashes when Google is down. No, we don’t want to fix this right now - Google being down is a very rare event, we can live with this right now. Just add a FIXME comment:

//FIXME the app crashes when Google is down. We can live with that for 
//      now, but should fix it in a subsequent release.

One Step Back

Those comments are a TODO-List, scattered across the code. There are tools available to collect them, but you’ll have to actively use those tools, so those comments are often forgotten.

We want those comments to be short-lived (for some definition of short). We should come back to the code in the future, fix it, and remove the comments. The second part is crucial - I have seen several examples where somebody fixed the code, but forgot to delete the comment. This is really confusing.

A Better Way

So, instead of writing a //TODO or //FIXME, try to formulate the TODO as a failing test next time. Also, tell the test system to ignore the test for now, because you are not planning to fix it right now - And you don’t want to have failing tests in your test suite!

//TODO handle invalid date range before marking the feature as complete

becomes

@Test @Ignore("TODO - Before marking feature 1234 as complete")
public void doesNotAllowTheUserToProceedWhenInvalidDateRangeWasEntered() {
    fail("Implement me!");
}
//FIXME the app crashes when Google is down. We can live with that for
//      now, but should fix it in a subsequent release.

becomes

@Test @Ignore("FIXME")
public void degradesGracefullyWhenGoogleIsDown() {
    fail("Implement me - And also add more tests to describe exactly " +
         "how we should degrade gracefully");
}

Activate the test before you start to fix the problem. Then you can work in the normal TDD cycle while fixing it - Adding more tests as you need them. Add anything that has to be deleted when the problem was fixed to the @Ignore annotation - This way you’ll have to delete it once you activate the test.

Sometimes It's Hard To Come Up With A Test

What about this comment:

//TODO This code is a mess. Clean up later.

You cannot really come up with a good test name from this description. But you could either refactor the code right away, or think about what exactly is wrong with the code, and derive a test name from that:

@Test @Ignore("TODO - Class has too many responsibilities, "+
              "should delegate some stuff to collaborators")
public void delegatesCalculatingCurrentInterestRateToTheGivenInterestRateCalculator() {
    fail("Implement me");
}

Conclusion

Most of the time, you can replace your //FIXME and //TODO comments with failing tests that are ignored (for now). The two main advantages of the latter approach are:

The test system will remind you about them. You don’t have to actively extract the TODOs from your source code. The test system will report which tests were ignored.

You cannot forget to delete the comment. The tests remain in the system. First, they were a reminder of some work to do. And after you fixed the problem, they are a documentation of how the system works now.

And when you can’t think of a way to replace a //FIXME or //TODO with a failing test, fix the problem right away.

Do you have any questions? Or Comments? Please contact me

Do you want to get articles like this on a regular basis, in your mail? Subscribe here!

You might be also interested in:

  • Cheap plastic drills: Most people think construction workers should have great tools. A lot of people think paying more than 1000 Euros for an office chair is a waste of money, even for a software developer who uses it 8 hours a day. Good tools are expensive.
  • Mocks or Intermediate Results: What I Would Do: An answer to Kent Beck's article, where he wrote about how he uses intermediate results instead of mocks. I show an alternative approach.