Writing unit tests for legacy code – an open letter to developers I work with
This is an email I sent today to developers who work with me, it is exactly as I wrote it except for project and developer names which I’ve redacted.
S asked me a difficult question today, and I think the answer (which took me a few minutes to arrive at) is worth sharing with all developers, mainly because many of you will surely face the exact same problem especially in [maintenance and enhancement] projects.
By now I think it is crystal clear that one of our non-negotiable requirements for coding is that we write unit tests.
For new projects it is easy – in fact for new projects you can write the tests before you write the actual code (ie TDD).
For legacy projects, by which I mean all the [maintenance and enhancement] projects, it is often a different story…
S had an offshore developer fix a bug in the xyz user interface. It was incorrectly prompting the user to save details when they hadn’t changed anything. (The details are a bit more complicated).
The fix was to add two lines of code.
Unfortunately these two lines were added in the middle of a method that was already 266 lines long. This method also had a large number of dependencies, meaning that to test the method it would be necessary to spend much, much more time writing the test than it took to find and make the fix in the first place.
S’s question was “should we insist on writing a test for this simple fix, when writing the test is going to take much longer?”
It was tempting to answer “no, don’t bother, it will be covered by system testing anyway”, but I am convinced this is absolutely the wrong answer.
I think the answer I gave S will apply to many situations you will encounter in [enhancement and maintenance] projects, S&M etc, perhaps even in new code for stories previously written in “new” projects
The answer is
Always assume you should write the unit tests, and that you might need to re-factor the code to make it possible to write the unit test.
If you cannot write the test in a reasonable amount of time, you need to estimate how long it might take, and escalate the problem to your scrum team.
If the scrum team can’t help, keep escalating (eg to L, me, R etc) until you’ve exhausted possibilities.
If after that you still can’t do it in a reasonable time, it becomes a problem for the project – a scheduling, perhaps a resource problem.
It should never be a question of whether you (the developer) should sacrifice quality for the sake of expediency, because the answer is always that you shouldn’t.
The business (by which I mean the senior management team) can make that kind of decision, but not you – your job is to produce quality code, and unit testing is a not-negotiable part of that obligation.
Hope I’ve been clear, please let me know if not. I’m especially interested to hear if you feel you have special circumstances that lead you to short-circuit the unit testing approach.
After changing one line of code, everything doesn't feel good.