CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

Haacked on TDD and Jeremy's First Rule of TDD

Unit Testing Loves Beta Testing And Vice Versa

Phil Haack has a great post up in response to some folks unhappy with their unit testing experience.  I think he makes several good points, including:

  1. Unit testing is only one layer of testing (duh)
  2. Automated unit tests are much, much simpler to write when you're writing the tests upfront and purposely creating testability

Like many people in the blog trail is saying, there are some types of code that are just too difficult for automatic tests.  User interface code is often an example, both heavy clients and web applications.  Testing the actual presentation code is difficult (but certainly not impossible).  Before you throw the baby out with the bath water and abandon TDD altogether for UI projects to rush in new features, consider this:

Jeremy's First Rule of TDD - "Isolate the ugly stuff "

Take the things that are truly difficult to test automatically and wrap them behind abstracted interfaces and separate any other code and functionality away from the difficult to test code.  Typically I think this would be access to external systems, user interface windowing, or anything involving a web server.  A picture perfect vision of my Grandmother boiling turkey bones after Thanksgiving comes to mind.  The bones aren't very edible, but you can do something to get the rest of the meat off the bones for endless post-Thanksgiving sandwiches. 

Circling back to user interfaces, the Model View Presenter pattern is a perfect example.  Actual user presentation code (System.Web.UI and WinForms) is harder to test, so make that code smaller.  Slice the "ugly" View classes as thin as possible.  Move the user interface flow logic into "plain old object" classes (Presenter) where it's much easier to test.  It probably is more code, but it'll make the UI code much easier to test and therefore easier to make work.  Since UI flow control code can become very complex and scary to change, it's awfully nice to be backed up with the automated unit tests.  You might decide to forgo unit testing the actual UI view code and call it a tolerable risk, but at least the controller logic will be unit tested.

The other example that comes to mind is a system I did last year that had some custom Active Directory queries in the authorization code.  We punted pretty early on trying to write automated unit tests for the actual Active Directory access code.  Instead, we put the AD access code into a thin Gateway class and interface so we could test the rest of the authorization logic without stepping into the Active Directory queries.  The only place that had any actual interaction with AD was the Gateway class itself. 

I would say that a lot of doing TDD is learning how to divide the class responsibilities up in a way to make the code easier to test (3 years so far and counting).  The fact that you often write code differently just for easy unit testing doesn't bother me a whole lot because it contributes to finishing the code sooner.  You can't just write code without regard to testability and expect to be able to retrofit unit tests on later.  I made the classic newbie mistake of trying to just write the code, then write the unit tests later only to find that my code didn't allow for easy unit tests.  TDD goes a lot smoother as soon as you realize that you need to change the way you build and structure code to take advantage of TDD.  Learning to write the unit tests first helps a tremendous amount too.  I think the book on best TDD practices is still being written, but there's a lot of experience out there already.  Before you throw your hands up in frustration over TDD, take a look at how other people are writing code for testability. 

P.S. - I don't know about Swing, but you can efficiently TDD a great deal of WinForms client code.  Maybe not everything is worth an automated unit test, but anything you can do helps.  Even without using something like NUnitForms a lot of WinForms classes can be treated as just "POO" and tested in NUnit/MbUnit without too much hassle.



Comments

Jeffrey Palermo said:

Good points.
# October 21, 2005 5:47 AM

Carlton said:

Recently, I have been using a Mediator pattern to handle all the state changes in my UI and it has worked very well. How it works is I have all the UI controls registered with the Mediator at the Form\Page load event. Then when some event happens (or a state change), we talk to the Mediator NOT the actual UI controls. It is VERY testable and the tests are SUPER fast, as opposed to some NUnitAsp tests I have elsewhere in the app.

One thing I have noticed is that when you use Mediator is ALMOST leads you to a Command pattern. I would say the natural progression is a Command pattern, but I don't like forcing a pattern and the commands are not reusable with other UI controls.
# October 21, 2005 12:04 PM

Haacked said:

I LOVE your first rule! What's your second? ;)
# October 21, 2005 12:43 PM

Jeremy D. Miller -- The Shade Tree Developer said:

I’m in a dry spell for blogging, so here’s a rehash of a presentation I gave internally at work earlier...
# December 19, 2005 7:38 AM

Jeremy D. Miller -- The Shade Tree Developer said:

Author: <a href="blogs/jeremy.miller/">Jeremy D. Miller</a><br>You’ll frequently hear teams say they didn’t write unit tests for a particular area of the code because it was just too hard to test. I think one of the biggest challenges of using TDD is learning strategies for isolating the code that’s hard to test and writing code that is easy to test. One of the primary strategies to extend unit test coverage into those hard to reach places is to use mock objects, stubs, or other fake objects in place of the external resources so that your tests don’t involve the external resources at all.
# December 19, 2005 10:49 AM

Jeremy D. Miller -- The Shade Tree Developer said:

Author: <a href="blogs/jeremy.miller/">Jeremy D. Miller</a><br>You’ll frequently hear teams say they didn’t write unit tests for a particular area of the code because it was just too hard to test. I think one of the biggest challenges of using TDD is learning strategies for isolating the code that’s hard to test and writing code that is easy to test. One of the primary strategies to extend unit test coverage into those hard to reach places is to use mock objects, stubs, or other fake objects i
# December 20, 2005 5:24 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Author: <a href="blogs/jeremy.miller/">Jeremy D. Miller</a><br>You’ll frequently hear teams say they didn’t write unit tests for a particular area of the code because it was just too hard to test. I think one of the biggest challenges of using TDD is learning strategies for isolating the code that’s hard to test and writing code that is easy to test. One of the primary strategies to extend unit test coverage into those hard to reach places is to use mock objects, stubs, or other fake objects i
# January 14, 2006 10:24 AM

Jeremy D. Miller -- The Shade Tree Developer said:

Laws of TDD is probably something that should be written by someone with more authority in the community,...
# March 9, 2006 9:59 AM

Jeremy D. Miller -- The Shade Tree Developer said:

Author: <a href="blogs/jeremy.miller">Jeremy D. Miller</a><br />Laws of TDD is probably something that should be written by someone with more authority in the community, but I've got a blog and I thought of it first, so here goes. I'll expound on each of these at some point in the misty future, but just for fun here is Jeremy's Laws of Test Driven Development (I'm certainly not claiming any kind of originality here. Some of these rules predate TDD anyway).
# March 9, 2006 10:18 AM

Jeremy D. Miller -- The Shade Tree Developer said:

Laws of TDD is probably something that should be written by someone with more authority in the community, but I've got a blog and I thought of it first, so here goes.  I'll expound on each of these at some point in the misty future, but just for fun here
# March 19, 2006 7:16 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Getting back on track with TDD content.  One of the most important lessons learned the software...
# May 30, 2006 2:43 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Between being extremely short handed at work, tech' reviewing a new book, a
possible book proposal...
# August 7, 2006 4:51 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Between being extremely short handed at work, tech' reviewing a new book, a possible book proposal

# September 1, 2006 2:33 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Jay Kimble , CodeBetter's resident AJAX guru, issued a little challenge to us TDD bloggers about using

# March 7, 2007 2:05 PM

Dim Blog As New ThoughtStream(me) said:

Jeremy Miller has posted quite a response to a question asked by Jay Kimble on unit testing with the...

# March 7, 2007 5:05 PM

Ian Goodsell - Dev Emporium said:

Jeremy D. Miller has some really good articles on unit testing, design and TDD. Here are some gems: ...

# April 19, 2007 4:03 PM

Getting with it: Test-Driven Development — James Gregory said:

Pingback from  Getting with it: Test-Driven Development — James Gregory

# July 17, 2007 7:40 PM

Jeremy D. Miller -- The Shade Tree Developer said:

I'm awful at returning emails. It was even one of my new year's resolutions to reply to emails

# July 22, 2007 5:57 PM

Chad Myers' Blog said:

Starting a new set of projects, what to do?

# October 29, 2007 3:58 PM

Jeremy D. Miller -- The Shade Tree Developer said:

To everybody that attended one of my talks at DevTeach this week. All of the materials are now online

# November 29, 2007 12:03 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP