Spurred by a series of tweets from DHH lamenting the use of Rspec and Cucumber over Test::Unit for testing today, the Ruby twitterverse erupted into a debate on the value of each versus the others, performance versus verbosity, and general preference of framework philosophy.
As DHH himself noted the most important thing is that you test. Regular readers of this blog will know the importance we place on testing in both client and internal projects, and speaking for my part, time after time I encounter projects with myriad problems, the one smell I know I will find before I even look at the codebase is a lack of tests. Testing won’t keep you from writing bad code, but it makes it painfully obvious when you’re doing so.
Use something you like
If you don’t like using the tool, you won’t keep testing. Everyone has a preferred testing style, and most people change their preference from time to time. But anyone who tells you that its impossible to create good tests using any of the tools above (or for that matter, most other testing frameworks like minitest, shoulda, etc) is simply displaying their ignorance. If you’ve never used a given framework successfully on a project, perhaps its easy to jump to this conclusion. But the bottom line is that hundreds or thousands of other people have already proven the idea wrong. For example, every time I have this conversation with someone who disparages the idea of testing in Cucumber, when I probe a bit deeper I commonly find that they’re using known antipatterns in their tests. Of course they are going to arrive at the conclusion that its an ill-suited tool. Likewise, the fact that I prefer Cucumber for my integration testing doesn’t mean I think Test::Unit is poorly suited to the task—to some degree it’s a perfectly valid matter of preference.
For me, Language Matters
All of the above notwithstanding, there’s a reason I choose Cucumber for most of my integration testing. I had trouble verbalizing it until this debate came up, but I was finally able to put my finger on it: I believe tests should be written in the language most natural for the problem. I typically work on web applications, and the “user” in this case is a person driving a web browser. I believe as developers we naturally jump to the conclusion that code is the most natural expression of a problem space, but here I think this is a false conclusion. I have never coded my way through a surfing session.
When I write an API, the “user” is client code—and here I think code is a natural language for the task, so I usually start with Rspec. But for the vast majority of interfaces I deal with—and that most web developers work on—its much more natural to use an approximation of English (or your native tongue) to drive the steps of your test. That makes Cucumber the decisive victor for me in my projects.
And that’s it. There’s plenty of other benefits to using Cucumber that have been discussed ad nauseum in other articles, but for me the killer feature is the ability to frame the problem in a natural language. Language shapes the way we think, and for me, framing thought in terms of code right off the bat is a sure way to overcomplicate a problem. That’s not to say I don’t drop down into Rspec (my other framework of choice) when the situation calls for it, but its not the first place I go.