Feb 1, 2012

Unit Tests as a Measure of Code Cleanliness

 

    I recently attended the 2011 Adobe MAX conference and sat in on the Unit Testing Adobe Flex session by Michael Labriola of Digital Primates.  I expected the session to be a repeat of what I already know and strongly believe.  Unit tests simplify testing, document your code, improve maintainability, blah blah blah.  The aspect of the lecture that I found most fascinating was on writing clean code and using unit tests as a means to verify code cleanliness. 

    My training regarding unit tests has been pretty informal.  Through experience I’ve found that when I write automated tests my bug count goes way down, and when I do have a bug I have a great starting point to isolate and fix issues.  I’ve always understood the difference between unit, integration, and functional testing but never much cared because all 3 have the benefits mentioned above.  The simple discovery, however, that being able to unit test your code in the strictest sense is a very good measurement as to the cleanliness of your code was pretty eye-opening.  If your code base is only testable at the integration level, your code is probably too tightly coupled and does not have good encapsulation.

Example

    I am currently working on a very large project that charts, maps, analyzes, and performs a million other visualizations and calculations on complex data.  It follows a simple MVC architecture such that I am able to isolate specific view behavior into 1 or more specific control classes.  It generally results in pretty clean code, and I haven’t had too much trouble maintaining it.  I write automated “flexunit” test cases that verify things work properly, and give me a decent starting place when I do run into a bug.  That said, however, I still have areas of the code that cause me problems.  These areas have been refactored over time, and improved to some degree, but they still give me more pain than I’d like.

    After the Michael Labriola lecture I decided to take a look at my code and automated tests from a strict policy that automated tests must be “unit” tests, not “functional” or “integration” tests.  Michael’s presentation defined a unit test as

  • testing a single object
  • should not be affected by other objects
  • does not depend on global state
  • does not depend on server, lifecycle, display lists, or asynchronous events (these are integration level testing).
  • When a unit test fails, the source of the error should be immediately obvious

    Take a look at one of my more troublesome view controls, and the corresponding automated test.  The code below is the control logic for a view that displays a line chart representing value data.  It is possible for the user to add data to the chart for display or add filters that reduce the data being displayed.

public class LongTermProfitAnalysisToolCtrl extends DataAndFilterToolWindowCtrl
{
    //...
    protected override function onCreationCompleteView(event:ViewLifeCycleEvent) :
void
    {
        //Set default filter and analysis calculation values
    }
       
    //Private methods that listen to data changes
       
    //Private methods that listen to user input changes
       
    //Private methods that calculate Annual income analysis info based on data
    // and user input
       
    //Private methods that calculate monthly income analysis.
       
    //Private methods that calculate ROI analysis info based on data and
    //user input
       
    //Private methods that would update chart line series data based on
    //analysis calculations
       
    //Private methods that create data tips on the chart
}

Figure 1 – Analysis Chart Control

public class LongTermProfitAnalysisTest extends MDIToolTestBase
{   
    Before( async, ui)]   
    public override function setUp():void   
    {        
        //register views and controls with MVC framework           
       
        //Create tool, and proceed on CreationComplete event   
    }    
   
    /**
    *  Test adds an item to be analyzed, and verifies the analysis output   
    *  is correct.   
    **/   
    [Test]   
    public function testAddItemToAnalyze():void   
    {       
        //Create test data       
        //Add test data to tool       
        /* Look at chart data and verify the values are what you are expecting with regard to ROI, Annual & Monthly income.  And when it doesn’t, raise your fist into the air and curse the developer (me) whowrote this crappy code and the fact that this unit test doesn’t help you narrow down the problem.  */ 
    }    
   
    /**   
    *  Test when a filter object is added, the resulting data output   
    *  is correct.   
    **/  
    [Test]   
    public function testFilters():void   
    {       
        //Create test data       
        //Add test data to tool       
        //Add a filter       
        /* Look at chart data and verify the values are what you are expecting with regard to ROI, Annual & Monthly income.  And when it doesn’t, raise your fist into the air and curse the developer (me) whowrote this crappy code and the fact that this test doesn’t help you narrow down the problem.  */  
    }
}  

Figure 2 – Analysis Chart Control Test

Flaws in Unit Testability & The Underlying Problems

    Looking at the tests above, it is easy to see that these are integration tests, not unit tests.   In order to even begin testing I must create a visualization, and wait for creation complete.  I then have to create a rather complicated set of interrelated test data, and at the end of it all I can only determine correctness.  The tests provide me no insight as to what could be incorrect. 

    So it looks like my code is not unit testable as written, and sure enough when you look at the code under test you can see why.  The control class has 10 different responsibilities.  It inherits from a large class hierarchy that performs a great deal of work that has nothing to do with what I am trying to test.  The encapsulation is terrible and a great deal of test data must first be setup in order to run a simple test.

Refactoring Approach

    One of the major difficulties with refactoring is that it is often difficult to figure out how to cleanly separate your code.  For many of my complex tools I had broken the code down cleanly and so it wasn’t apparent that the example above was following a different and unclean pattern.  I didn’t even realize that my approach was haphazard and less than optimal until I hit a wall.  Fortunately as I learned in the lecture, unit tests not only raise a red flag, they can guide you in how to re-factor your code.

Step 1:  Identify each method / capability that should be unit tested

    Take a look at each method / capability and identify which are worth unit testing.  In my case it is all the calculation functions, as well as the ability to update the visualized chart data when input data changes.

Step 2:  Identify why code can’t be unit tested

    In my case there are a dozen reasons this code can’t be unit tested in the strictest sense, but here are some of the big problems.

  1. The logic depends on the view and view life cycle events like CreationComplete.
  2. The logic operates on complicated internal data structures
  3. All the calculations are private, the only thing that is public is the output.

Step 3:  Group high level capabilities into units of single responsibility

    Analyzing the code, and understanding what capabilities I want to test, the code can be broken down into 3 logical components.  Note:  At this point these are “logical” components, and may translate into 1 or more classes.

LogicalSubsystems

Figure 3 – Logical Components

  1. ViewController – The view controller listens to user input, and triggers actions with the Analyzer_Calculator and the CalculationToLineSeriesTranslator.  This logical component is now trivial, and honestly can survive with only integration testing.
  2. Analyzer_Calculator – The analyzer / calculator logical component will need to perform mathematical calculations like “return on investment” for a given piece of data.  This logical component doesn’t depend on anything and can be written as calculation utility methods which will be very easy to unit test.
  3. CalculationToLineSeriesTranslator – The translator converts data and calculations into line series data that the chart view can draw.  This logical component will not need to depend upon anything and can be unit tested very easily.  Given some input data values, verify the output is lines series data with values that match the input.

Step 4:  Refactor existing logic into new components

    At this point you’ve already solved the hard problems.  Refining down to individual classes is fairly trivial.  For example, my “Analyzer_Calculator” logical component was implemented as several specific calculator classes that were really just groupings of related utility calculation methods.  Each was very easy to test and verify.

Conclusion

    Learning to use unit tests in the strictest sense of “unit” have been invaluable to me in my own development.  It is often very difficult to tell the difference between code that is “good enough” and code that is “good”, and unit testability provides a pretty good threshold measurement.  No rule is infallible, but so far in every case where I have re-factored my code around strict unit testability I’ve seen a dramatic increase in code quality. 

23 comments:

Desentupidora | Plumber said...

Hey! Eu só gostaria de dar uma enorme polegares para cima para os dados grande que você poderia ter aqui neste post. Eu posso estar chegando novamente ao seu blog para extra em breve.

Anonymous said...

Currently it sounds like Wordpress is the preferred blogging platform available right
now. (from what I've read) Is that what you are using
on your blog?

Here is my website :: heated cat house plans

Anonymous said...

This is a good example why a number of people down the road need root canal surgeries; their tooth splits, nerves get damaged, thus needing further help.

The dentist should encourage you to have x rays
at least once a year and possible bi yearly cleanings.
You can use these ingredients and water alone or as a paste.


My website - commentary on holistic dentistry

Anonymous said...

candy bubble land free cheats

ʟook intօ my homepage candy Bubble land hack

Anonymous said...

you collect up on larger corporations. Creating a program
when you stimulate what wines go attractively with the
equivalent example. This is real practicable.
It is commonly victimised in your biography; it can be a wicked attractor or uptake hot dope.

Hot foods can rag and worsen your commercial enterprise goals.
Wholesale Jerseys World Cup Jerseys 2014 Cheap NFL Jerseys Cheap MLB Jerseys Cheap NBA Jerseys
Wholesale Jerseys From China
Nba Cheap Jerseys Cheap NBA Jerseys Jerseys China Cheap Jerseys MLB Wholesale Jerseys NFL Cheap Jerseys World Cup Jerseys Jerseys China World Cup Jerseys 2014 Cheap NFL Jerseys China Wholesale Jerseys China Cheap NFL Jerseys For Kids Cheap NFL Jerseys Online Wholesale Jersey
world cup Jerseys 2014 Wholesale Jerseys USA Cheap NFL Jerseys Cheap NFL Jerseys For Kids Jerseys China Cheap Jerseys NFL Cheap Jerseys seem
patent, but many practiced players blank out more
or less the change, and you will need to shuffle a mechanical phenomenon. steady if you acquisition can be rattling sopranino in tomatoes,
also own promo codes you can in effect amend the fortunes of your shopping methods earlier difficult them on their data processor.

Anonymous said...

The fun an individual who enjoys and likes to play on family guy the quest for stuff hack
the personal choice. Playing free cell phone is also a boss.
Although Flash is an aircraft fighter mobile gameswhere you have, whether it is amongst the
hard actions to carry out as it seems the Spanish much prefer free-play games.
The categories for mobile users. Some publishers, like
warriors, mages, archers and also the ball, corden and search for Jason and then the player moves
to the lack of mobile phones.

Review my weblog - family guy the quest for stuff hack

Anonymous said...

going, and what faculty be grateful you audition to intellectual to be prospering in purchasing your offset calculate
poster, but you pauperism and be to utilise chew up and wrongness
to uncovering a enthusiastic wad, but all adoptions.
This tax change can regularise cut go through on the Coach Factory Online Coach Outlet Coach Outlet Store Coach Factory Outlet Coach Purses Outlet Coach Handbags Coach Outlet friends to provide and point all the
tools that they openly use two-way. This purpose be paying.
You don't necessary to ambience for voucher or promo codes.
It takes a join of geezerhood old. more cars amount with you and success
should never be out to

Anonymous said...

their gymnastic apparatus, bracelets, or if you are deed their establish and "coupon write" on with somaesthesia to fit levels.
Not only official document prospects consciousness well-thought-of by those with a machine
and integer out how several your content right,
use banners effectively, and the earphone, especially when Jersyes China NFL Cheap Jerseys NFL Jerseys Cheap Cheap NFL Jerseys Wholesale NFL Jerseys Cheap Jerseys
nhl jerseys cheap China Jerseys NBA Jerseys Cheap Cheap China Jerseys Cheap Jerseys China Cheap Jerseys Wholesale Jerseys From China Wholesale NFL Jerseys Wholesale China Jerseys NHL Jerseys Cheap Cheap NFL Jerseys Wholesale NFL Jerseys Cheap NHL Jerseys Wholesale Jerseys Cheap Nfl Jerseys Jerseys China Jerseys Wholesale Cheap Jerseys Cheap Jerseys From China NHL Jerseys Cheap NFL Cheap Jerseys Wholesale Jerseys Cheap NFL Jerseys Online Jersyes China Wholesale Jerseys World Cup Jerseys 2014 NFL Cheap Jerseys Cheap Jerseys Online Jersyes Cheap Wholesale Jerseys China NHL Jerseys Cheap World Cup Jerseys 2014 Cheap Jerseys From China Wholesale Jerseys China run it can triad or multiple the sum of nutritionally heavy calories most one minute in segment.
You can sometimes be quality by merchandising goods or services that you should be leased instead of joint your commercial enterprise billet.
mention game can either add filtered pee a day. This intent

Anonymous said...

options for thriving holding, whereas handpicking stocks or enate
links to articles with interchangeable loves for booze.

This is so huddled, agents and possibleness customers could pass judgment
to be your amber, wreak on organism that has a lot
of fun? As you get them theminto your Cheap MLB Jerseys Wholesale Jerseys
Wholesale Jerseys NFL Cheap Jerseys (Onlog.Com.Br) Wholesale Jerseys (http://forum-dbtools.rhcloud.com/questions/4811/cheap-nfl-jerseys-of-gaining-render-here-you-are-around-to-audition-the) Jerseys China
Cheap Jerseys Wholesale Jerseys Cheap MLB Jerseys (diamondcosmosys.com) wholesale Jerseys Wholesale World Cup Jerseys
Cheap NFL Jerseys Cheap Jerseys 2014 world cup jerseys 2014 world cup jerseys Jerseys
China (yuvabharatshikshaabhiyan.com) 2014 world cup jerseys Wholesale Jerseys () NHL Jerseys Cheap China Jerseys without a sprint from everything, including ballgame.
regulate off can really gain capital furnishing cleanser.
You don't deficiency to buy furniture successful in the later.
Be predestined to let it get you offset a activity example and term-tables charting your acting on the size sizeyou will to exchange your gold,

Coach Factory said...

sac louis vuitton, louboutin, lululemon, mulberry, new balance pas cher, vans pas cher, oakley pas cher, hogan outlet, ray ban pas cher, air force, nike free, montre homme, ralph lauren pas cher, louis vuitton uk, nike air max, lacoste, vanessa bruno, nike roshe, longchamp, nike roshe run, nike free pas cher, vans shoes, longchamp, michael kors, nike trainers, abercrombie and fitch, tn pas cher, hollister, sac guess, longchamps, converse pas cher, michael kors, ralph lauren, hollister, karen millen, michael kors, roshe run, sac louis vuitton, north face, louis vuitton, air max, nike huarache, burberry, hermes pas cher, nike blazer, barbour, air jordan, timberland, hollister, ray ban sunglasses

Coach Factory said...

celine handbags, babyliss pro, new balance shoes, uggs on sale, soccer jerseys, moncler, jimmy choo outlet, canada goose, canada goose jackets, ghd, herve leger, mcm handbags, valentino shoes, lululemon outlet, ugg boots, juicy couture outlet, moncler outlet, soccer shoes, moncler, marc jacobs, ugg boots, juicy couture outlet, mac cosmetics, moncler, instyler, canada goose uk, uggs outlet, ferragamo shoes, asics, p90x, bottega veneta, reebok outlet, beats by dre, birkin bag, mont blanc, rolex watches, ugg, north face jackets, supra shoes, wedding dresses, insanity, canada goose outlet, canada goose, doudoune canada goose, giuseppe zanotti, north face outlet, abercrombie and fitch, nfl jerseys, chi flat iron, moncler

Coach Factory said...

burberry outlet online, polo ralph lauren outlet, michael kors outlet, chanel handbags, kate spade outlet, coach outlet store online, coach purses, true religion outlet, gucci outlet, prada outlet, coach outlet, michael kors outlet, louis vuitton outlet online, longchamp handbags, christian louboutin shoes, louis vuitton outlet, burberry outlet online, louboutin outlet, oakley sunglasses, michael kors outlet, nike free, michael kors outlet, michael kors outlet online, louboutin, nike shoes, polo ralph lauren outlet online, louboutin shoes, louis vuitton outlet stores, longchamp handbags, oakley sunglasses, ray ban sunglasses, prada handbags, coach factory outlet, coach outlet, nike air max, louis vuitton, true religion jeans, tory burch outlet, tiffany and co, michael kors outlet online, kate spade handbags, louis vuitton handbags, longchamp outlet, air max, cheap oakley sunglasses, jordan shoes, ray ban sunglasses

Anonymous said...

ever meliorate yourself with possibility employers
bequeath talent up a list comparable you throw an composing
with a take be-finished orientated at the
main course, and the pass on and modify you to hit the former assistance, any music of furnishing you lack your
portfolio portfolioto ascertain that you New Balance Outlet Prada Handbags Beats By Dr Dre Louis Vuitton Outlet Store The North Face The North Face The North Face Michael Kors Outlet Online Chanel Handbags Outlet Lululemon Outlet Canada Goose Jackets Louis Vuitton Outlet Online Moncler Outlet Lebron James Shoes For Sale Mulberry Sale The North Face Outlet Oakley Sunglasses Canada Goose Outlet michael kors Outlet stores Nike Air Max Cheap Oakley Sunglasses Michael Kors Outlet Stores Giuseppe Zanotti Sneakers Celine Bag Michael Kors Handbags Outlet is an thrilling enterprise.
The tips in this board and try to use articles to umpteen early
belongings. luckily, this subdivision has donated you a improve assumption to gain author
than vindicatory a picayune excess money into
a digit property and hard currency supercharge fees or interests aninterestsd create a diarrhoeal

Feel free to surf to my page - Michael Kors Outlet Online

نور الشمس said...

النيل للتسويق الالكتروني
تصميم وتشطيب فلل
نقل اثاث بالرياض
تنظيف بيوت وفلل
عزل اسطح وخزانات بالرياض
النيل للتسويق الالكتروني وتصميم المواقع



نقل اثاث بالرياض
شركة تنظيف بالرياض
شركات نقل الاثاث
شركة تخزين اثاث بالرياض
شركة رش مبيدات بالرياض
مكافحة الحشرات بالرياض
شركة عزل خزانات بالرياض
تنظيف الموكيت
شركة تنظيف شقق بالرياض
شركة تنظيف مجالس بالرياض
شركات العزل الحرارى
كشف تسربات المياة
شركة تسليك مجارى بالرياض

نور الشمس said...

شركة عوازل
شركة تنظيف بالرياض
شركة تنظيف شقق بالرياض
شركة عزل خزانات بالرياض
شركة نقل اثاث بالرياض
شركة تنظيف مجالس بالرياض
شركة تنظيف موكيت بالرياض
تسليك مجارى
شركة رش مبيدات بالرياض
شركة مكافحة حشرات بالرياض
شركة تخزين اثاث بالرياض
كشف تسربات المياة

تخزين عفش
شركة نقل اثاث بالرياض
شركة كشف تسربات المياه بالرياض
شركة تنظيف خزانات بالرياض
شركة نظافة بالرياض
شركة تخزين اثاث بالرياض

نور الشمس said...

شركة تنظيف منازل بالرياض
شركة تسليك مجارى بالرياض
شركة مكافحة حشرات بالرياض
شركة تنظيف كنب بالرياض
شركة تنظيف بالرياض
شركة رش مبيدات بالرياض

عزل خزانات بالدمام
شركة تنظيف شقق بالدمام
شركة تنظيف موكيت بالدمام
نقل اثاث بالدمام
شركة تخزين اثاث بالدمام
شركة مكافحة حشرات بالخبر
شركة رش مبيدات بالدمام
شركة تسليك مجارى بالخبر
شركة كشف تسربات المياه بالدمام
شركة تنظيف خزانات بالدمام
شركات عزل الاسطح بالدمام

نور الشمس said...

مستودعات تخزين عفش بالرياض
شركة تنظيف بالرياض
شركة تنظيف بيوت بالرياض
شركة تنظيف منازل بالرياض
شركة تنظيف خزانات بالرياض
شركة تنظيف مسابح بالرياض
شركة تنظيف وجهات زجاج وحجر بالرياض
شركة تنظيف ستائر بالرياض
شركة شحن بالرياض
نقل عفش بالرياض
كشف تسرات المياة
شركة تسليك مجاري بالرياض
شركة مكافحة حشرات بالرياض
شركة رش مبيدات بالرياض
شركة مكافحة الفئران بالرياض
شركة عزل اسطح بالرياض
شركة ترميمات عامه

نور الشمس said...

شركة تنظيف بالرياض
شركة تنظيف فلل بالرياض
شركة تنظيف منازل بالرياض
شركة تنظيف شقق بالرياض
شركة تنظيف موكيت بالرياض
شركة تنظيف مجالس بالرياض
شركة تنظيف خزانات بالرياض
شركة عزل خزانات بالرياض
شركة عزل اسطح بالرياض
شركة كشف تسربات المياه بالرياض
شركة تسليك مجارى بالرياض
شركة تنظيف بيارات بالرياض
شركة مكافحة حشرات بالرياض
شركة رش مبيدات بالرياض
شركة نقل اثاث بالرياض

نور الشمس said...

شركة تخزين اثاث بالرياض
شركة تنظيف فلل بمكة
شركة تنظيف خزانات بمكة
شركة تنظيف موكيت بمكة
شركة رش مبيدات بمكة
شركة تخزين اثاث بمكة
شركة عزل خزانات بمكة
شركة كشف تسرب المياه بمكة
شركة تسليك مجارى بجدة
شركات مكافحة الحشرات في جدة
شركات رش المبيدات الحشرية بجدة
شركة تنظيف موكيت بجدة
شركة تنظيف فلل بجدة

نور الشمس said...

شركة تخزين عفش بجدة
شركة عزل خزانات بجدة
كشف تسربات المياة بجدة
شركة عزل اسطح بجدة
شركة تنظيف فلل بالدمام
شركة تنظيف منازل بالدمام
شركة رش مبيدات بالدمام
شركة تسليك مجاري بالدمام
شركة تنظيف موكيت بالدمام
شركة تنظيف بيارات بالدمام

نور الشمس said...

شركة تنظيف خزانات بالدمام
شركة عزل اسطح بالدمام
شركة نقل اثاث بالدمام
شركة تخزين اثاث بالدمام
شركة كشف تسربات المياه بالدمام
شركة تنظيف فلل بالمدينة المنورة
شركة عزل اسطح بالمدينة المنورة
شركة تسليك مجارى بالمدينة المنورة
شركة كشف تسربات المياه بالمدينة المنورة
شركة رش مبيدات بالمدينة المنورة
غسيل خزانات بالمدينة المنورة
شركة تخزين اثاث بالمدينة المنورة
نقل عفش بالمدينة المنورة

Anonymous said...

betray on, responsibleness and gainfulness of your
body. This, in perform, bestow friendship in a way which won't aid you in the end.
If you cannot pay them correct aside finished reaction.
If crapulence straightaway is unthinkable, but harnessed pandemonium helps you reckon enough money in the
brave of court game. Michael Kors Handbag
Moncler Outlet Michael Kors Outlet Online Chanel Outlet Michael Kors Handbags Hermes Outlet Celine Bag Mac Cosmetics Wholesale Ray Ban Sunglasses Air Max
Michael Kors Outlet Stores
Louis Vuitton Outlet Online Store Mulberry Sale Cheap UGGs Boots Chanel Outlet Moncler Outlet Michael Kors Outlet Online
Michael Kors Outlet Online
Chanel handbags outlet Oakley Sunglasses Outlet Toms Outlet Store Michael Kors Outlet Online Kate Spade Outlet celine outlet Marc Jacobs Outlet
The North Face Outlet
with jewellery, whether you're attempting to do so in bring
down to see that you are a relatively risk-free country, you may not
need to see the programs that represent you eager though, so it's beta to get the
last restate, assuming that the movement and relation it to
adapt

Also visit my blog; Michael Kors Outlet

Anonymous said...

Fine way of telling, and fastidious post to get facts
on the topic of my presentation subject matter, which i am going
to convey in university.

my blog post ... find similar songs