Generating characterization tests for legacy code
Upcoming SlideShare
Loading in...5
×
 

Generating characterization tests for legacy code

on

  • 1,716 views

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

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

Statistics

Views

Total Views
1,716
Views on SlideShare
1,716
Embed Views
0

Actions

Likes
1
Downloads
14
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • Johannes BroadwallOle Christian RynningMarius B.KotsbakGeir Amdal

Generating characterization tests for legacy code Generating characterization tests for legacy code Presentation Transcript

  • Generating Characterization Tests for Legacy Code
    Jonas Follesø (@follesoe)
    JavaZone 2010, 09. September
  • Huge methods (~3000+ lines)
  • Dave & Karin http://www.flickr.com/photos/dnk_uk/3525103502/
    ~50 slow integration tests
  • How the development team felt...
  • What they needed
  • What I read
  • Legacy code is code without tests.  Code without tests is bad code. 
    -Michael C. Feathers
    Fraser Speirs http://www.flickr.com/photos/fraserspeirs/3395595360/
  • 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
  • publicdoubleCalc(doubleinv, doublert, inty)
    {
    doubleret=0;
    for (inti=1; i<=y; i++)
    {
    ret=inv*Math.Pow(1.0+rt/100.0, i);
    }
    returnret;
    }
  • [TestMethod]
    publicvoidCalc_characterization()
    {
    varcalc=newCalcUtil();
    doubleresult=calc.Calc(10000, 10, 10);
    Assert.AreEqual(42.0, result);
    }
  • Assert.AreEqual failed.
    Expected:<42>. Actual:<25937.424601>.
  • [TestMethod]
    publicvoidCalc_characterization()
    {
    varcalc=newCalcUtil();
    doubleresult=calc.Calc(10000, 10, 10);
    Assert.AreEqual(42, result);
    Assert.AreEqual(25937.424601, result);
    }
  • Test run completed. Results 1/1 passed.
  • publicdoubleCalculateCompoundInterest(doubleinvestment, doubleinterest, intyears)
    {
    doubleprojectedValue=0.0;
    for (intyear=1; year<=years; year++)
    {
    projectedValue=investment*
    Math.Pow(1.0+interest/100.0, year);
    }
    returnprojectedValue;
    }
  • …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
    Fraser Speirs http://www.flickr.com/photos/fraserspeirs/3395599536/
  • ~85% code coverage
    http://www.flickr.com/photos/shuttercat7/713186211/
  • // This method is the "pinch point" we want to test...
    publicobjectCalculateSomething(objectsomeParameter)
    {
    // 1) Record input parameters...
    // 2) Do the work...
    // 3) Write parameters and return value to XML file.
    }
  • [TestMethod]
    publicvoidCalculateSomething_test1()
    {
    Run("Recordings/CalculateSomething1.xml");
    }
    [TestMethod]
    publicvoidCalculateSomething_test2()
    {
    Run("Recordings/CalculateSomething2.xml");
    }
    publicvoidRun(stringfilename)
    {
    // Load input parameters from XML file
    // Load return value from XML file
    // Call method under test
    // Use reflection to compare actual vs. recorded
    }
  • ~300 fast characterization tests
  • How can we reuse this?
  • http://follesoe.github.com/BlackBoxRecorder
  • [Recording]
  • [Dependency]
  • [Recording]
    publicList<EmployeeEntity>GetMakingMoreThan(doublesalary)
    {
    vardal=newEmployeeDAL();
    varemployees=dal.GetAllEmployees();
    returnemployees.Where(e=>e.Salary>salary).ToList();
    }
  • [Dependency]
    publicclassEmployeeDAL
    {
    publicList<EmployeeEntity>GetAllEmployees()
    {
    // Calls to database...
    }
    }
  • <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>
  • [TestMethod]
    publicvoid GetEmployeesMakingMoreThan_salary()
    {
    Run(@"GetEmployeesMakingMoreThan_salary.xml");
    }
  • http://github.com/oc/jackbox
  • @Recording
    publicintexampleMethod(intparameter, intparameter2) {
    returnparameter+parameter2;
    }
    @Dependency
    publicStringinvokedMethodOnDependency(Stringargument) {
    returnargument.toUpperCase();
    }
  • Jonas Follesø
    Senior Consultant
    +47 977 06660
    Jonas.folleso@bekk.no / jonas@follesoe.no