After almost a year of using test driven development, I am now a total convert. I now feel it is so vital to good development practice that, across the board, I think I can label my previous applications as bad just because they don’t have rigorously tested tests. I was a sinner, but I have seen the light.
I’ve just had a good example of why test driven development is so important.
I have created a dynamic test method system that allows me write functional tests a little quicker. For example, one of the methods is “assert_item_passed_to_template”. I use method_missing to catch methods that match the method name pattern but replace ‘item’ with the name of the item they want tested. So assert_user_passed_to_template looks for a variable @user and matches it to the contents of assigns(:user), returning true if they match, and an error that describes the mismatch if they don’t.
One of the methods I use a lot was called assert_populated_item_passed_to_template. This didn’t match @user against assigns(:user) but instead matched assigns(:user) to @user_params (which is in effect params[:user]). So useful to make sure that the object returned to a failed save still contains the entered data.
However, I’ve been working on another part of the application for a week or two and have now returned to add some more edit functions. And I found the key world ‘populated’ confused me. I tried to use assert_populated_user_passed_to_template where I should have been using assert_user_passed_to_template. It took me a few minutes to work out why my my tests were failing. Populated is the wrong word. A @user object generated from the database is ‘populated’. I realised that if I was confused by populated (and I created the method name) so would anyone else reading my code.
However, every new and edit method in my application was tested with an assert_populated_item_passed_to_template call. What’s worse, because of the dynamic use of this method, I could not just rename the method; I had to rename all the methods with that pattern.
In the past that would have been a no, no. Just too much work to make sure the change hadn’t broken other parts of the application.
However, with this application I have tested from the start, so it was a straight forward task. I simply did a cross project replace of ‘assert_populated_’ with ‘assert_params_loaded_’ so that the method became ‘assert_params_loaded_item_passed_to_template’. Then ran all my tests. As they all passed, I could be sure the change hadn’t had any adverse knock on effects.
This means when I identify a way of improving my application, I feel much safer implementing that change than I did before I unit tested. So my application gets better as I work on it.
If you don’t test as you code, you don’t get a reliable set of tests that you know work, and you don’t get this vital safety net. Test driven development is up there with having source control, as vital prerequisites to good coding practice in my opinion. You don’t have to do it, but if you don’t you’ll regret it later.