PHP in Action Rotating Header Image

Don’t refactor without unit tests

Google "Testing on the Toilet"
Image by niallkennedy via Flickr

Brandon Savage is writing a series on code improvement using a code example (starting with Peer Review: Taking Code And Making It Better). In other words, it’s about refactoring, which is practically my favorite subject. Although I don’t agree with all of it, it’s mostly good advice. I recommend it.

That said, I do have something important to add. The series is missing the first, most basic rule: Don’t refactor unless you have good automated test coverage (typically with unit tests). And if there are no test, write them before you start refactoring. If you don’t, you’ll make mistakes and get lost in a frustrating bug search, unless you’re very stingy and don’t refactor too much. With test coverage, you have freedom to experiment, to change something and change it back if you don’t like the result. This, above all, is what makes refactoring such a great learning experience.

Some of those who have commented on the post Peer Review: Looking Into Abstraction (Greg Beaver, Jeff Carouth) mention testing and point out the need to inject objects so that they can be replaced with mock objects for testing. This is a wise move, and practically unavoidable in this case. To support refactoring, unit tests need to be run frequently, without accessing outside services (twitter or email in this case) that take time to process.

This means that in this case, it’s actually necessary to refactor a bit before proper unit tests can be implemented. This is what Michael Feathers calls the Legacy Code Dilemma in his book Working Effectively with Legacy Code. Certainly building this dilemma into new code is not a good idea. Make the code unit-testable before it’s too late.

Reblog this post [with Zemanta]

Share/Save/Bookmark

2 Comments

  1. Thanks for your words about the series. I’m glad you’re enjoying it.

    I think you’re right about testing, and it reflects a test-first approach. Most applications are considerably larger than the one we’re working on, and I totally believe that the unit tests should be written first.

    I’ll make sure and link to your post in the testing entry, which will be forthcoming one week from Monday.

  2. Albo says:

    I totally agree. The Legacy Code Dilemma paralyze me the first time. But once you start to write at least one Unit Test (just before you refactor a little bit of code), you’re able to start with the add unit test-refactoring cycle.

Leave a Reply