I’m going to step up onto a crowded soapbox here for a minute.
If you’re not testing while you’re coding a Rails app, you’re doing yourself, your users, and your clients a disservice. I’ve been on Rails for the past year or so, but only recently really buckled down and got serious about testing. Oh, I’ve done some testing here and there, but it was “feel good” testing. You know, just to alleviate the guilt of not doing it at all.
Nowadays, I won’t add a feature without adding tests for it. I should’ve taken this approach all along. All it takes is discipline. The “I don’t have time” excuse, which I’ve used myself, just doesn’t make sense. The time you put into testing is made up for down the line. In the app I’m working on now, a couple things have really convinced me of this.
I’m catching bugs I wasn’t even testing for. For example, I’ve caught myself on a couple of occasions writing code that depended on empty strings evaluating to false. This is an ingrained habit from other languages. In Ruby, one checks String.empty? for an empty string. In Ruby, one checks String.empty? for an empty string. In Ruby, one checks String.empty? for an empty string. I’ve typed it three times now, maybe I’ll remember it.
UPDATE: You should actually be calling String.blank? It’s another nifty Rails add-on. More info here.
The only thing that caught these mistakes were tests. And most of the time, when I catch bugs like this, they are an unintended (but welcome!) side-effect of what I was actually testing for.
When I test, I also identify areas of complexity. I question why this or that has to be so complicated. Sometimes it doesn’t have to be. By making a feature simpler to test, I make the feature itself simpler. Simple is good.
I haven’t quite gotten to the point of test-first development with Rails. I’m not even convinced that that’s the Holy Grail. As long as I’m testing things as I go, whether I do it before or after I start to write the real code doesn’t seem terribly relevant. I know, I know, testing is about design. But, I still feel like I’m getting design benefits without always writing the tests first.
The other thing I’ve only dabbled in is integration tests, and only then out of the necessity to test across multiple controllers. So far, I’m really liking them, if only because they remove the single-controller limitation of functional test. I’m looking forward to diving into integration tests a bit more. The way you can write stories, devise a DSL, and wrap that all up into integration tests is definitely intriguing.