Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
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

2,319 views

Published on

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

Published in: Technology
  • Be the first to comment

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 />

×