30
Generating Characterization Tests for Legacy Code Jonas Follesø (@follesoe) JavaZone 2010, 09. September

Generating characterization tests for legacy code

Embed Size (px)

DESCRIPTION

Lightning talk from JavaZone 2010 on generating characterization tests for legacy code.

Citation preview

Page 1: Generating characterization tests for legacy code

Generating Characterization Tests for Legacy Code

Jonas Follesø (@follesoe)

JavaZone 2010, 09. September

Page 2: Generating characterization tests for legacy code

Huge methods (~3000+ lines)

Page 3: Generating characterization tests for legacy code

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: Generating characterization tests for legacy code

How the development team felt...

Page 5: Generating characterization tests for legacy code

What they needed

Page 6: Generating characterization tests for legacy code

What I read

Page 7: Generating characterization tests for legacy code

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: Generating characterization tests for legacy code

A characterization test is test that characterizes the actual behavior of a piece of code.

It acts as a change detector, protecting legacy code form unintended changes

Page 9: Generating characterization tests for legacy code

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: Generating characterization tests for legacy code

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

Assert.AreEqual(42.0, result); }

Page 11: Generating characterization tests for legacy code

Assert.AreEqual failed. Expected:<42>.

Actual:<25937.424601>.

Page 12: Generating characterization tests for legacy code

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

Assert.AreEqual(42, result); Assert.AreEqual(25937.424601, result); }

Page 13: Generating characterization tests for legacy code

Test run completed. Results 1/1 passed.

Page 14: Generating characterization tests for legacy code

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: Generating characterization tests for legacy code

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: Generating characterization tests for legacy code

~85% code coverage

http:

//w

ww

.flic

kr.c

om/p

hoto

s/sh

utter

cat7

/713

1862

11/

Page 17: Generating characterization tests for legacy code

// This method is the "pinch point" we want to test...public object CalculateSomething(object someParameter){ // 1) Record input parameters... // 2) Do the work... // 3) Write parameters and return value to XML file.}

Page 18: Generating characterization tests for legacy code

[TestMethod]public void CalculateSomething_test1(){ Run("Recordings/CalculateSomething1.xml");}

[TestMethod]public void CalculateSomething_test2(){ Run("Recordings/CalculateSomething2.xml");}

public void Run(string filename){ // Load input parameters from XML file // Load return value from XML file // Call method under test // Use reflection to compare actual vs. recorded}

Page 19: Generating characterization tests for legacy code

~300 fast characterization tests

Page 20: Generating characterization tests for legacy code

How can we reuse this?

Page 21: Generating characterization tests for legacy code

http://follesoe.github.com/BlackBoxRecorder

Page 22: Generating characterization tests for legacy code

[Recording]

Page 23: Generating characterization tests for legacy code

[Dependency]

Page 24: Generating characterization tests for legacy code

[Recording]public List<EmployeeEntity> GetMakingMoreThan(double salary){ var dal = new EmployeeDAL();

var employees = dal.GetAllEmployees();

return employees.Where(e => e.Salary > salary).ToList();}

Page 25: Generating characterization tests for legacy code

[Dependency]public class EmployeeDAL{ public List<EmployeeEntity> GetAllEmployees() { // Calls to database... }}

Page 26: Generating characterization tests for legacy code

<Recording> <Name>GetEmployeesMakingMoreThan_salary</Name> <Method>GetEmployeesMakingMoreThan</Method> <Type><![CDATA[BlackBox.Demo.App.SimpleAnemic.EmployeeBL]]></Type> <InputParameters> <Parameter> <Name>salary</Name> <Type><![CDATA[System.Double]]></Type> <Value><![CDATA[5000]]></Value> </Parameter> </InputParameters>

<Return> <Type><![CDATA[List<BlackBox.Demo.App.SimpleAnemic.EmployeeEntity>]]></Type> <Value><![CDATA[XML representation of employees retruned from method]]></Value> </Return>

<Dependencies> <Dependency> <Type><![CDATA[BlackBox.Demo.App.SimpleAnemic.EmployeeDAL]]></Type> <Method> <Name>GetAllEmployees</Name> <ReturnValues> <ReturnValue> <Value><![CDATA[XML representation of all employees returned from db]]><Value> </ReturnValue> </ReturnValues> </Method> </Dependency> </Dependencies>

</Recording>

Page 27: Generating characterization tests for legacy code

[TestMethod]public void GetEmployeesMakingMoreThan_salary(){ Run(@"GetEmployeesMakingMoreThan_salary.xml");}

Page 28: Generating characterization tests for legacy code

http://github.com/oc/jackbox

Page 29: Generating characterization tests for legacy code

@Recordingpublic int exampleMethod(int parameter, int parameter2) { return parameter + parameter2;}

@Dependencypublic String invokedMethodOnDependency(String argument) { return argument.toUpperCase();}

Page 30: Generating characterization tests for legacy code

BEKK CONSULTING ASSKUR 39, VIPPETANGEN. P.O. BOX 134 SENTRUM, 0102 OSLO, NORWAY.

WWW.BEKK.NO

Jonas FollesøSenior Consultant

+47 977 [email protected] /

[email protected]