7

I am participating on the development of the web application which has several years of history behind it and there never was enough value and effort put on refactoring, so considerable part of the code base of this application really deserves to be marked as legacy.

As the work with the code base becomes tedious and a lot of these problems are acknowledged but are not being dealt with, people start to push forward unit testing as a possible remedy that would enforce better maintainable code.

Only a few members of the development team have some actual understanding of unit tests let alone experience with unit testing. Nevertheless these people are starting with unit testing on parts of the new code which is being written. These unit tests should become an example for other members of the development team and also a proof of value of unit testing to management and stakeholders. This way we would like to present unit testing to our colleagues in the best possible light and avoid the fail, which would most probably mean an end to all the unit testing efforts.

Hence the question: Are there some well known nasty pitfalls to try to avoid at all costs when starting with unit testing on a "legacy" web application?

2 Answers 2

5

I'm not sure whether or not these qualify as "well known", but they certainly qualify as "nasty" (and apply to any kind of application):

  • Global gobs: heavy reliance on global values for information, making it difficult to tell what modifies which variable where.
  • Ball of spaghetti: everything is closely related to everything else, and when you change something in one place it does horrible and weird things to something you'd swear was completely unrelated.
  • Breakout blues: You want to take something and put it into a unit-testable framework, but to do it you've got to break a chunk of code out of where it is and put it into an object or some other test-friendly structure. Also occurs where you're trying to send information to your new code but there's no sensible way to get it there without rewriting the legacy work. Usually occurs with ball of spaghetti and global gobs.
  • We don't need no steenking objects!: Old code written and designed by people who had never heard of object-oriented design, and would have thought it was for wusses anyway.

On a more serious note, you actually will get your best results from unit tests around new code the next time anything needs to be done with that code: the tests will tell you immediately if there's a problem with the changes. The end result is that the unit-tested code becomes the most stable and bug-free code in the system, but it does take some time for this to become obvious.

I'd recommend you have a list of the problem areas of the application so you can point out that new problems aren't happening in the unit-tested code when you're trying to argue for increasing the amount of the application covered by unit tests.

The other big thing you're going to need to push for is first modularizing then adding unit tests to the old code. Effectively, you'll need a process where any time anyone needs to do anything to the legacy code, they are expected to refactor it in such a way that unit tests can be easily added to it, and add those tests. That will gradually clean up the problems with the old code with a relatively limited impact - but it will also take a long time (exactly how long depends on how big the application is, and how intertangled it is).

Good luck!

1

Kate already gave quite a good answer. From my experience I'd like to add

  • avoid heavy test/mock frameworks

There are some mighty frameworks out there that let you virtually break any restrictions that have been imposed by design or language on the legacy code. Though it's true that these are very useful to write characterization tests before moving legacy to more testable units, I think they must not be overused. If you use those you'll introduce a new dependency and not really improve the existing code.

Note: characterization tests are defined by Michael Feathers in Working Effectively with Legacy Code as a suite of automated tests that describe the current behaviour of your piece of code and that will have to pass still after refactoring your code. Though concentrating on Java I recommend you to read the book as it has great ideas about working with legacy code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.