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.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. 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 is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Test Driven Development. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Yves Goergen
  • http://bensdeveloperblog.blogspot.com Ben

    I just recently started trying to code using TDD and this post was extremely relevant to what I’m experiencing lately.

    You wrote this in 2005 and I’m just now reading this in 2009. I guess it’s better late than never for me!

  • http://haacked.com/ Haacked

    I LOVE your first rule! What’s your second? 😉

  • Carlton

    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.

  • http://www.jeffreypalermo.com Jeffrey Palermo

    Good points.