Thursday, November 23, 2006

Running with Scissors: Are you still coding without automated tests?

Do you run with scissors? Play football without a helmet? Drive while drunk? Do you still create software without scripted tests? For quite some time, I was a test driven development hypocrite. I had read the books, read the magazine articles, dabbled with various testing tools, and believed test driven development was the way to go. But for various reasons, I never quite had the gumption to push test driven development into our organization (or even into my own work habits).

Switching to Ruby on Rails finally kicked me into shape. Creating and running scripted tests within Rails is almost too easy not to do - the framework draws you into testing with it's excellent capabilities for Unit Tests, Functional Tests, and Integration Tests. I was initially hooked by using unit tests to do initial model testing (reaction: "cool.... this is much nicer than monkey testing various boundary behaviors"), then got the full testing religion after doing some significant code refactoring on code that was fully covered by tests ("Carrumba! I'll never write an application without fully automated tests again!").

One of the common complaints and FUD mentioned about Ruby and Rails is non-existent or weak support for debugging (although reportly Radrails, and possibly other tools, does have a decent level of debugging capabilities). Interestingly enough, I have found this to be an almost irrelevant issue, as my debugging is almost always done through the tests, not by stepping through code. I don't always follow the exact sequence of "write a test, see it fail, write some code to make it pass", but do make sure that my code is covered by tests, and do use the tests to exercise boundary conditions, failure cases, and so on.

Two additional tools we have found to be particularly useful for testing Rails code:
  • rcov: code coverage for ruby - provides coverage analysis with excellent web reporting of the results.
  • Watir - Web Applicatoin Testing in Ruby - The Rails tests can give your application and database servers a good beating. But they do run on the application server, only exercising a subset of your hardware and software. When you are ready to test your entire infrastructure from a browser (exercising your ISP, front-end web servers, SSL, etc.) , consider Watir. It's not really a load testing tool, but it does let you create browser-based tests scripted in Ruby, is quick and easy to install and use, and is handy if don't read (or are not ready for) incurring the full effort of a full blown load testing solution.
In our company, we are convinced that the tradeoff of creating more code up front (often the test code is larger than the code being tested) easily pays for itself in a shortened development schedule. More importantly, we are also convinced that over the lifespan of our application, having a fully automated test suite will give us a huge advantage in long-term agility, will hugely reduce our maintenance costs, and ultimately will have a significant impact on the profitability and valuation of our business.

If you're not using Rails, there is almost certainly a tool available for your programming language. There are innumerable references on this subject, a good place to start looking is here.

1 comment:

Anonymous said...

Some great thoughts. I know I have been pushing test driven development in my organization for some time and am now seeing progress.

My shop is a Java shop and I personally am a huge rails fan. One of the biggest things I have noticed as people adopt test-driven development is that it changes the way we think about writing code.

When you start really testing your code up front I have noticed that the developers on my team have started breaking dependencies between objects and making their methods smaller and smaller.

The unit tests have started forcing them to think more like OO guys rather then functional coders.

If you get a chance check out my comments on thoughtmechanix.blogspot.com.

Cheers,
John Carnell