generatingcharacterizationtestsforlegacycode

18
Generating Characterization Tests for Legacy Code Slides via Jonas Follesø (@follesoe)

Upload: carl-schrammel

Post on 11-May-2015

76 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Generatingcharacterizationtestsforlegacycode

Generating Characterization Tests for Legacy Code

Slides via Jonas Follesø (@follesoe)

Page 2: Generatingcharacterizationtestsforlegacycode

Huge methods (~3000+ lines)

Page 3: Generatingcharacterizationtestsforlegacycode

Dav

e &

Kar

in h

ttp:

//w

ww

.flic

kr.c

om/p

hoto

s/dn

k_uk

/352

5103

502/

~50 slow integration tests

Page 4: Generatingcharacterizationtestsforlegacycode

How the development team felt...

Page 5: Generatingcharacterizationtestsforlegacycode

What they needed

Page 6: Generatingcharacterizationtestsforlegacycode

What you should read

Page 7: Generatingcharacterizationtestsforlegacycode

Fras

er S

peirs

htt

p://

ww

w.fl

ickr

.com

/pho

tos/

fras

ersp

eirs

/339

5595

360/

Legacy code is code without tests.  Code without tests is bad code. 

-Michael C. Feathers

Page 8: Generatingcharacterizationtestsforlegacycode

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

Page 9: Generatingcharacterizationtestsforlegacycode

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;}

Page 10: Generatingcharacterizationtestsforlegacycode

[TestMethod]public void Calc_characterization(){ var calc = new CalcUtil(); double result = calc.Calc(10000, 10, 10);

Assert.AreEqual(42.0, result); }

Page 11: Generatingcharacterizationtestsforlegacycode

Assert.AreEqual failed. Expected:<42>.

Actual:<25937.424601>.

Page 12: Generatingcharacterizationtestsforlegacycode

[TestMethod]public void Calc_characterization(){ var calc = new CalcUtil(); double result = calc.Calc(10000, 10, 10);

Assert.AreEqual(25937.424601, result); }

Page 13: Generatingcharacterizationtestsforlegacycode

Test run completed. Results 1/1 passed.

Page 14: Generatingcharacterizationtestsforlegacycode

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;}

Page 15: Generatingcharacterizationtestsforlegacycode

Fras

er S

peirs

htt

p://

ww

w.fl

ickr

.com

/pho

tos/

fras

ersp

eirs

/339

5599

536/

…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

Page 16: Generatingcharacterizationtestsforlegacycode

fast characterization tests

Page 17: Generatingcharacterizationtestsforlegacycode

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.

Page 18: Generatingcharacterizationtestsforlegacycode

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.