Writing tests is virtuous. It's the wholemeal bread of programming. Do it, and you'll be so much fitter. Except it tastes like cardboard and gets in the way of consuming the yummy treacle sponge of programming.

But now I've got the testing religion. I view the lack of tests with the disapprobation of a reformed smoker tutting and huffing at the merest suggestion of a Marlboro Light.

How did this happen and how can I be sure I won't backslide?

The moment of transition was the first time that a test saved me from releasing software with a bad bug in it. The theoretical knowledge of virtue was translated into the palpitating relief of not disgracing myself in public.

After that happened a few more times, I found myself desperately uncomfortable with the idea of releasing anything that didn't have decent test coverage. And so a virtuous habit is formed.

It's not just driven by fear. With the right tools to hand, writing tests can be a lot of fun. You don't always need to be "in the zone". If you've got a spare half hour here and there, you can use it to increase the coverage of your tests.

Getting better at testing is one of the ways I've become a much more proficient Rails developer over the last year of work on Expectnation. In case it helps anybody else, I thought I'd share some of the tools and techniques that are part of making Rails testing fun and effective.

Continuous testing

Whenever a checkin is made to our source repository, tests are run and the results emailed to everybody working on the project. As with the "you broke the build" disincentive, you need to be kept honest by frequent running of the tests.

There are a variety of tools around to help you do continuous integration with Rails, most of which have some dependence on you using Subversion for source control. In the event, I just created my own script to do what we required.

Coverage reports

One of the big mental hurdles with testing is knowing how many tests you should aim for. You can't prove a negative: even if your tests are all passing it still doesn't tell you much about the tests you haven't written that might fail!

We use rcov as part of the continuous integration process, and post the results to our project web site. The pretty red and green bars give you some idea of when you're starting to get adequate test coverage, and the line-by-line breakdown is invaluable.

Tainting strings

One of the easiest errors to make in Rails templates is to miss the call to h(), to escape any HTML in an output string. The only real way to catch these errors is through automation. The wonderful safe_erb plugin helps you do just that. By using Ruby's tainting mechanism for strings, it throws an exception if you render any external data unescaped.

One of the beneficial side effects of safe_erb is that you then become very particular about ensuring your functional tests properly cover every action in your application. Tests such as get 'index', which before seemed mundane and redundant, are now essential, as you want to test for tainted strings.

In addition to the above techniques, there are a lot of fun shiny gadgets to help you write tests, such as ZenTest, but the three things above are the ones I've found to be of significant value.

I ought to conclude with words of praise for Rails. It goes out of its way to make testing an important part of the development lifecycle, and the availability of the of unit, functional and integration test functionality makes it easy to get started. Every time I teach somebody about Rails' testing features, they end up finding it very enjoyable.



Don't forget, testing can be fun!