Writing Unit Test for Legacy Code

Sandro Mancuso recently published a video on “Testing and Refactoring Legacy Code.” One of the key benefits for writing test for legacy code is it allows you to understand the existing code while reducing risk in changing it.

It is a great video but a bit long so here are some of his suggestions.

  • Do not change production code unless it is covered by a test.
  • Start testing from shortest to deepest branch. The Shortest branch will require less understanding of the code base.
  • Start refactoring from deepest to shortest branch. 
  • Do not execute another class from the unit test. The test should only care about the class it is testing. Otherwise you may be testing components (database, external systems, etc…) that you don’t want to test right now. Refactor the Singleton, Static call, or object to a protected method (Seam) and overwrite it.
  • Feature envy is when one class/method has functionality that probably belongs in another class.
  • Guard clause is a parameter check and should be moved earlier.
  • Bring declaration of variables and the code that uses the variable closer together.



Documenting the past

My team is currently in the process of documenting a project we inherited. The project was a skunkworks effort and documentation wasn’t as important as proving that it works. The developer who wrote it is no longer on the project and isn’t the most pleasant person to interact worth so we are on our own. The interesting thing about this exercise is we are realizing how much lack of documentation cost a project.

The number one reason for documentation is so another developer can step in and keep the project running if you are hit by a bus, falling piano, or UFO. The big motivator for us is code refactoring and removing dead code becomes very hard without proper documentation.

I was watching a presentation by Jack Diederich on code reduction and one of the reasons he often hears against removing dead code is “It might be used…somewhere.”

As he points out when using a dynamic language it can be very hard to identify if code is called or not. He recommends adding a comment to indicate where code is called from. Using code coverage tools does help identify dead code but you need to have a full understanding of the use-cases or else you may accidentally remove code that addresses an edge case.

Documenting legacy components can be seen as an expensive part of a project but will ultimately reduce technical debt and save time later on.