This document discusses principles and practices for unit testing legacy code. It covers background on large, old software projects with complex code. The motivation is to facilitate changes, not find bugs. Principles include keeping tests simple, not adding tests to bad code, avoiding assumptions, stopping legacy code creation, and educating others. Practices include setting up a framework, domain modeling, identifying hot areas to start, using a bottom-up approach, learning functions through tests, and making code testable by refactoring dependencies. The document advocates bringing order to chaos and finding fun in learning features and deleting code.
4. Large scale software
Telecommunication device
10+ years old
1,000 people
10,000,000 lines of code in one build
C, SDL
Some very complicated
Thousands LOCs functions
Cyclomatic complexity > 50.
Duplicate rate > 100%!
12. PRINCIPLE 1
KEEP IT VERY SIMPLE, VERY STUPID
It is not that the more test cases the better
Actually, it is on the contrary, the less the better.
The purpose of UT is to facilitate change
It can only facilitate change if it survive
Therefore, it needs maintainability
So, it needs to be simple
"The only way for humans to deal with complexity is to
avoid it ..."
15. PRINCIPLE 4
STOP MAKING 'LEGACY CODE'
Test drive new code
Add tests to legacy code before modification
Test drive changes to legacy code
Boy Scout Principle
16. PRINCIPLE 5
EDUCATE THE PEOPLE
Do NOT let just one or two people do it.
NEVER let interns do it!
18. Setup the framework
To setup the framework for legacy
code can be very challenging.
Choose the test framework
We use CppUTest
Ask for performance
19. Domain Modeling
Reverse engineering to clarify the
concepts used in the legacy code
And their relationships
Use the terms consistently in your
unit testing.
It will also give your refactoring
a road-map.
20. Identify the hot area
Start from the hot area will be most
cost-efficient
Example
Through SVN log
Along with the new work and bug fixing
21. Bottom-up?
Have some integration test first
Then,
One practical approach is bottom-up
Get a higher level of abstraction
22. Learn the function by testing it
Characterization Test
Start from the 1st (failing) exit
Write your plan on a piece of paper
23. Make the legacy code testable
Use safe refactoring techniques to
change the legacy code without unit
testing.
Extract function
If you are using C
Data injection to break the dependency on
globals.