I think one of my biggest gripes with adopting that TDD life is that I feel I’m in the minority with my friends even though the concept appears to be quite mainstream these days. One of the common pushbacks I receive is that it’s hard to write unit tests for legacy code. I can totally agree with that, but that roadblock easily lends itself to developers not writing any tests for new code if it involves any legacy code whatsoever.
Most will agree, legacy code fucking sucks. Hell, there’s a whole subgenre of developer that will consider any code they did not write to be trash. Egos aside, that logic and mentality is not a good reason to avoid writing tests for new development. Sure, 99.99999% of the project may remain untested, but over time, as more new code is written, that number will drop. If you’re changing code on a legacy system, regardless of the complexity of the task, you should be writing tests to help things along.
This whole sitation can easily be avoided by diving in and taking the first step. You know how I know? I’ve been doing it quite a bit recently. My new workflow when contributing to open source projects that lack unit tests is to make that my first contribution. Before I hop in and hack together some bug fix or enhancement, I make sure the code I plan to work with has tests so I can tell if I borked anything. I’ve also been going through my own open source projects, some of which I haven’t actively worked on in years, and have been retrofitting them with test suites.
Is it hard? Definitely, especially when you don’t know the project well enough to write tests for edge cases that may never happen in the wild. The point is, when working with older code, some tests are better than no tests and a little bit of coverage is better than none at all. Now that I’ve been doing it regularly, my approach is a bit more streamlined and I’m feeling more confident about writing tests against code I didn’t write or am not overly familiar with.
The simple truth is, the reason a system lacks unit tests is because no one has taken the time to write them, legacy or otherwise. Writing tests can be time consuming but, at least for me, the value of that time investment is apparent. Lower the bar a bit with legacy code and start by writing tests for any new code that is written and when major subsystems are being refactored. Remember that 100% code coverage is going to be a far reaching goal and remember that writing more tests is the only way you will be able to get there.
Take the first step, write the first test, no matter how trivial it may be.