Yesterday’s Thoughts

September 21, 2005

Test Based Specifications in Ruby on Rails

I am starting to experiment with writing unit and funtional tests for factscollector. I haven’t ever worked with consistent automated testing.

I probably waited too long to start, both in general, and in this particular Ruby on Rails project. The general reasons are well known in the Agile Programing literature. Tthe existance of the test is a safety net. Having the test I can feel free to change to code and I don’t have to worry that I have broken something elsewhere in the code. The tests document what the code does, not what it ought to do. It occurs to me that tests are better than comments in this sense. Also, automatic tests are like double entry bookkeeping. It is easy to make a mistake. It is much harder to make two mistakes that exactly cancel each other out.

On factscollector, I waited too long because I found a couple of bugs in Rails. One was a documentation bug in ActionMailer and the other was in an interaction between controllers. Both that took me a while to track down, particularly because I was more suspicious of my own code than of the framework. (Why is that? Whenever I learn a new language, or a new tool, I am more suspicious of myself than I am of this completely unknown tool? That’s not my default in most areas of life.) Both of these bugs would have been easier to track down if I had had functioning tests earlier, if only because the domain of the problem would have been radcally circumscribed.

While researching these issues, I came across this post from Ben Griffiths, CTO of Reevoo.

He advocates a template for creating and naming tests that serves as documentation for what the application actually does. Examples are worth many words, here is one of my tests:

def test_should_return_user_to_login_template_on_incorrect_password login "bob", "not_correct" assert_template_has "login" end

The test is very short. It tests exactly one thing. The name says that thing. It says it in an obvious pattern and Ben offers up a Rake task that outputs these as a pass at documenting what the application does. Here is a segment of mine from my user controller.

user_controller should: - allow creation of new user on valid password - send mail on successful user creation - not send mail on bad password - not send mail on bad email - display flash on successful login - not allow existing user to login on incorrect password - return user to login on incorrect password - store logged in user in session

These are discrete areas of functionality. All of these are very small. The collection of all of the tests (that pass, anyway) is a concrete expression of what the application can do right now.

This has been a huge productivity boon for me. As I’m visualizing what the application will do, I’m writing the test names. The names of the tests are the specification. This is actually fun, so I do it and then the excitement drives me to fill in the test and since the tests fail, I have to write the code to make the tests pass.

Looking at the actions documented here, I think I could improve the specificity of these names and improve the clarity of my thinking and my design. Ben recommends the template “test_should_***_on_***”. If the all the tests are short and sweet, like my example, then the possibilities for creating a test that don’t test what they purport to test are minimal. If the tests fail, it is immediately obvious what the application isn’t doing correctly, without going into the code.

1 Comment(s)

  1. little lamb | Apr 7, 2006 | Reply

    I think author know this theme.

Sorry, comments for this entry are closed at this time.