Generating Characterization Tests
for Legacy Code
Slides via Jonas Follesø (@follesoe)
Huge methods (~3000+ lines)
Dave&Karinhttp://www.flickr.com/photos/dnk_uk/3525103502/
~50 slow
integration tests
How the
development
team felt...
What they
needed
What you
should read
FraserSpeirshttp://www.flickr.com/photos/fraserspeirs/3395595360/
Legacy code is code without tests.
Code without tests is bad code.
-Michael C. Feathers
A characterization test is test that
characterizes the actual behavior of a piece of
code.
It acts as a change detector, protecting legacy
code from unintended changes
public double Calc(double inv, double rt, int y)
{
double ret = 0;
for (int i = 1; i <= y; i++)
{
ret = inv * Math.Pow(1.0 + rt / 100.0, i);
}
return ret;
}
[TestMethod]
public void Calc_characterization()
{
var calc = new CalcUtil();
double result = calc.Calc(10000, 10, 10);
Assert.AreEqual(42.0, result);
}
Assert.AreEqual failed.
Expected:<42>. Actual:<25937.424601>.
[TestMethod]
public void Calc_characterization()
{
var calc = new CalcUtil();
double result = calc.Calc(10000, 10, 10);
Assert.AreEqual(25937.424601, result);
}
Test run completed. Results 1/1 passed.
public double CalculateCompoundInterest(
double investment, double interest, int years)
{
double projectedValue = 0.0;
for (int year = 1; year <= years; year++)
{
projectedValue = investment *
Math.Pow(1.0 + interest / 100.0, year);
}
return projectedValue;
}
FraserSpeirshttp://www.flickr.com/photos/fraserspeirs/3395599536/
…A pinch point is a natural encapsulation
boundary. When you find a pinch point, you’ve
found a narrow funnel for all the effects of a large
piece of code…
-Michael C. Feathers
fast characterization tests
The Golden Master Approach
Before making any change to production code, do the following:
1) Create X number of random inputs, always using the same random seed, so
you can always generate the same set over and over again. You will probably
want LOTS of inputs for good coverage.
2) Bombard the class or system under test with these random inputs.
3) Capture the outputs for each individual random input.
A picture's worth a 1000 tests.
Unit testing asserts can be difficult to use.
Approval tests simplify this by taking a
snapshot of the results, and confirming that
they have not changed.

Generatingcharacterizationtestsforlegacycode