Generating Characterization Tests for Legacy Code<br />Jonas Follesø (@follesoe)<br />JavaZone 2010, 09. September<br />
Huge methods (~3000+ lines)<br />
Dave & Karin http://www.flickr.com/photos/dnk_uk/3525103502/<br />~50 slow integration tests<br />
How the development team felt...<br />
What they needed<br />
What I read<br />
Legacy code is code without tests.  Code without tests is bad code. <br />-Michael C. Feathers <br />Fraser Speirs http://...
A characterization test is test that characterizes the actual behavior of a piece of code. <br />It acts as a change detec...
publicdoubleCalc(doubleinv, doublert, inty)<br />{<br />doubleret=0;<br />for (inti=1; i<=y; i++)<br />    {<br />ret=inv*...
[TestMethod]<br />publicvoidCalc_characterization()<br />{<br />varcalc=newCalcUtil();<br />doubleresult=calc.Calc(10000, ...
Assert.AreEqual failed. <br />Expected:<42>. Actual:<25937.424601>.<br />
[TestMethod]<br />publicvoidCalc_characterization()<br />{<br />varcalc=newCalcUtil();<br />doubleresult=calc.Calc(10000, ...
Test run completed. Results 1/1 passed. <br />
publicdoubleCalculateCompoundInterest(doubleinvestment, doubleinterest, intyears)<br />{<br />doubleprojectedValue=0.0;<br...
…A pinch point is a natural encapsulation boundary. When you find a pinch point, you’ve found a narrow funnel for all the ...
~85% code coverage<br />http://www.flickr.com/photos/shuttercat7/713186211/<br />
// This method is the "pinch point" we want to test...<br />publicobjectCalculateSomething(objectsomeParameter)<br />{<br ...
[TestMethod]<br />publicvoidCalculateSomething_test1()<br />{<br />Run("Recordings/CalculateSomething1.xml");<br />}<br />...
~300 fast characterization tests<br />
How can we reuse this?<br />
http://follesoe.github.com/BlackBoxRecorder<br />
[Recording]<br />
[Dependency]<br />
[Recording]<br />publicList<EmployeeEntity>GetMakingMoreThan(doublesalary)<br />{<br />vardal=newEmployeeDAL();<br />varem...
[Dependency]<br />publicclassEmployeeDAL<br />{<br />publicList<EmployeeEntity>GetAllEmployees()<br />    {<br />// Calls ...
<Recording><br />  <Name>GetEmployeesMakingMoreThan_salary</Name><br />  <Method>GetEmployeesMakingMoreThan</Method><br />...
[TestMethod]<br />publicvoid GetEmployeesMakingMoreThan_salary()<br />{<br />    Run(@"GetEmployeesMakingMoreThan_salary.x...
http://github.com/oc/jackbox<br />
@Recording<br />publicintexampleMethod(intparameter, intparameter2) {<br />returnparameter+parameter2;<br />}<br />@Depend...
Jonas Follesø<br />Senior Consultant<br />+47 977 06660<br />Jonas.folleso@bekk.no / jonas@follesoe.no<br />
Upcoming SlideShare
Loading in …5
×

Generating characterization tests for legacy code

1,975 views
1,826 views

Published on

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

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,975
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
20
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • Johannes BroadwallOle Christian RynningMarius B.KotsbakGeir Amdal
  • Generating characterization tests for legacy code

    1. 1. Generating Characterization Tests for Legacy Code<br />Jonas Follesø (@follesoe)<br />JavaZone 2010, 09. September<br />
    2. 2. Huge methods (~3000+ lines)<br />
    3. 3. Dave & Karin http://www.flickr.com/photos/dnk_uk/3525103502/<br />~50 slow integration tests<br />
    4. 4. How the development team felt...<br />
    5. 5. What they needed<br />
    6. 6. What I read<br />
    7. 7. Legacy code is code without tests.  Code without tests is bad code. <br />-Michael C. Feathers <br />Fraser Speirs http://www.flickr.com/photos/fraserspeirs/3395595360/<br />
    8. 8. A characterization test is test that characterizes the actual behavior of a piece of code. <br />It acts as a change detector, protecting legacy code form unintended changes<br />
    9. 9. publicdoubleCalc(doubleinv, doublert, inty)<br />{<br />doubleret=0;<br />for (inti=1; i<=y; i++)<br /> {<br />ret=inv*Math.Pow(1.0+rt/100.0, i);<br /> }<br />returnret;<br />}<br />
    10. 10. [TestMethod]<br />publicvoidCalc_characterization()<br />{<br />varcalc=newCalcUtil();<br />doubleresult=calc.Calc(10000, 10, 10);<br />Assert.AreEqual(42.0, result); <br />}<br />
    11. 11. Assert.AreEqual failed. <br />Expected:<42>. Actual:<25937.424601>.<br />
    12. 12. [TestMethod]<br />publicvoidCalc_characterization()<br />{<br />varcalc=newCalcUtil();<br />doubleresult=calc.Calc(10000, 10, 10);<br /> Assert.AreEqual(42, result); <br /> Assert.AreEqual(25937.424601, result); <br />}<br />
    13. 13. Test run completed. Results 1/1 passed. <br />
    14. 14. publicdoubleCalculateCompoundInterest(doubleinvestment, doubleinterest, intyears)<br />{<br />doubleprojectedValue=0.0;<br />for (intyear=1; year<=years; year++)<br /> {<br />projectedValue=investment*<br />Math.Pow(1.0+interest/100.0, year);<br /> }<br />returnprojectedValue;<br />}<br />
    15. 15. …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…<br />-Michael C. Feathers <br />Fraser Speirs http://www.flickr.com/photos/fraserspeirs/3395599536/<br />
    16. 16. ~85% code coverage<br />http://www.flickr.com/photos/shuttercat7/713186211/<br />
    17. 17. // This method is the "pinch point" we want to test...<br />publicobjectCalculateSomething(objectsomeParameter)<br />{<br />// 1) Record input parameters...<br />// 2) Do the work...<br />// 3) Write parameters and return value to XML file.<br />}<br />
    18. 18. [TestMethod]<br />publicvoidCalculateSomething_test1()<br />{<br />Run("Recordings/CalculateSomething1.xml");<br />}<br />[TestMethod]<br />publicvoidCalculateSomething_test2()<br />{<br />Run("Recordings/CalculateSomething2.xml");<br />}<br />publicvoidRun(stringfilename)<br />{<br />// Load input parameters from XML file<br />// Load return value from XML file<br />// Call method under test<br />// Use reflection to compare actual vs. recorded<br />}<br />
    19. 19. ~300 fast characterization tests<br />
    20. 20. How can we reuse this?<br />
    21. 21. http://follesoe.github.com/BlackBoxRecorder<br />
    22. 22. [Recording]<br />
    23. 23. [Dependency]<br />
    24. 24. [Recording]<br />publicList<EmployeeEntity>GetMakingMoreThan(doublesalary)<br />{<br />vardal=newEmployeeDAL();<br />varemployees=dal.GetAllEmployees();<br />returnemployees.Where(e=>e.Salary>salary).ToList();<br />}<br />
    25. 25. [Dependency]<br />publicclassEmployeeDAL<br />{<br />publicList<EmployeeEntity>GetAllEmployees()<br /> {<br />// Calls to database...<br /> }<br />}<br />
    26. 26. <Recording><br /> <Name>GetEmployeesMakingMoreThan_salary</Name><br /> <Method>GetEmployeesMakingMoreThan</Method><br /> <Type><![CDATA[BlackBox.Demo.App.SimpleAnemic.EmployeeBL]]></Type><br /><InputParameters><br /> <Parameter><br /> <Name>salary</Name><br /> <Type><![CDATA[System.Double]]></Type><br /> <Value><![CDATA[5000]]></Value><br /> </Parameter><br /> </InputParameters><br /> <Return><br /> <Type><![CDATA[List<BlackBox.Demo.App.SimpleAnemic.EmployeeEntity>]]></Type><br /> <Value><![CDATA[XML representation of employees retruned from method]]></Value><br /> </Return><br /> <Dependencies><br /> <Dependency><br /> <Type><![CDATA[BlackBox.Demo.App.SimpleAnemic.EmployeeDAL]]></Type><br /><Method><br /> <Name>GetAllEmployees</Name><br /> <ReturnValues><br /> <ReturnValue><br /><Value><![CDATA[XML representation of all employees returned from db]]><Value><br /> </ReturnValue><br /> </ReturnValues><br /> </Method><br /> </Dependency><br /></Dependencies><br /></Recording><br />
    27. 27. [TestMethod]<br />publicvoid GetEmployeesMakingMoreThan_salary()<br />{<br /> Run(@"GetEmployeesMakingMoreThan_salary.xml");<br />}<br />
    28. 28. http://github.com/oc/jackbox<br />
    29. 29. @Recording<br />publicintexampleMethod(intparameter, intparameter2) {<br />returnparameter+parameter2;<br />}<br />@Dependency<br />publicStringinvokedMethodOnDependency(Stringargument) {<br />returnargument.toUpperCase();<br />}<br />
    30. 30. Jonas Follesø<br />Senior Consultant<br />+47 977 06660<br />Jonas.folleso@bekk.no / jonas@follesoe.no<br />

    ×