Why No Love For RSpec?
Posted by Adam Wiggins on April 22, 2008 at 08:11 PM
It's no secret that I'm a big RSpec fan. Test::Unit feels pretty outdated these days, and none of the other frameworks can yet match the level of BDD goodness you get from RSpec. Throw in that it's now a mature and stable library, and it seems like a sure bet for all your Ruby specing (or testing, if you like) needs.
It's thus surprising to me that some Rubyists seem reluctant to use RSpec. Certainly, some of this comes from the fact that it's not a standard include with Ruby or Rails, unlike Test::Unit. In this way it faces the same battle that Haml, DataMapper, Thin, or any other add-on library that swaps out a substantial component of the framework stack: the user must actively make the choice. Defaults are the status quo, the incumbent; they win, well, by default.
But I sense that people's mistrust of RSpec extends further than what these other components face. My guess is that the reasons for this are: too big, too complicated, and too much magic.
The first concern is a reasonable one - the plugins are pretty large, and especially since it's common to install it as a plugin rather than a gem, this can seem to bog down your source repo. The too big issue is a bit of an illusion, as Rick DeNatale explains.
The too complicated and too much magic problems can somewhat be addressed by using a subsest of the matcher library, as I suggested with minimalist RSpec matchers. It occurs to me that all of these problems could be solved with a lightweight implementation of RSpec which implements just the core syntax. That is:
describe MyClass do before do @my_obj = MyClass.new end it "sums two numbers" do MyClass.sum(1, 2).should == 3 end it "raises an error when arguments are not integers" do lambda { MyClass.sum(1, 'x') }.should raise_error(ArgumentError) end end
If someone wrote an leaner RSpec-alike library which ran the above spec correctly, I'd probably switch. (The example excludes RSpec's built-in specs and mocks, but I'd be ok using Mocha instead, which is very similar.) Maybe mSpec is such a thing, though I'm still kind of confused as to what it is exactly, since the readme claims you should still run the specs using RSpec.
A final reason why many people don't understand the importance of RSpec is simply not fully drinking the BDD koolaid. If you find yourself thinking things like "Well, yeah, BDD is a good idea, I hope to find the time to do it more often...", then I count you in that category.
I was in that position not too long ago, so don't feel bad. But it was using RSpec that caused the lightbulb to turn on above my head. Pat Maddox put it well in a mailing list post:
"I would say that TDD is a tool to help you solve the problem of designing and implementing behavior. Test::Unit works fine in that regard, but RSpec reduces the semantic distance between the developer and the problem domain."
The good news is, despite the sense of reluctance many display toward RSpec, it actually is catching on - even becoming the standard. Merb uses it by default out of the box. A recent Rails Envy podcast mentioned that their informal poll showed RSpec as the most popular testing/specing framework with 62% of the vote. (Test::Unit got around 25%, Shoulda around 12%.) The hosts expressed surprise at this. I was surprised too - pleasantly so.
But perhaps most important is that the Rubinius project uses RSpec, and has spawned a spinoff project for an executable specification of the Ruby language, which is being adopted most of the the major Ruby VM implementors (MRI/Yarv, JRuby, IronRuby, Rubinius). This means that soon the most important spec in the Ruby world - the spec for the very language itself - will use RSpec.
Comments
There are 3 comments on this post. Post yours →
From a lot of discussion I've had with folks on RSpec vs. others, one of the things folks dislike about RSpec is the syntax. For many folks (myself included) it actually reads worse than test unit or Shoulda.
That's why Shoulda really hits the sweet spot for me. It seems to combine the parts of RSpec I like (contexts and the "should" naming of tests), but avoid the rest of the syntax that I don't like.
Further, I've run into a fair bit of problems with RSpec, especially in moving between versions (we use it fairly heavily on one of my main projects). It's just been a pain to upgrade and the interaction with other Rails things and the rest of the code has soured my feelings for it beyond just the syntax bits.
I have to say that about the only thing keeping my mind open to it is that Rubinius standardized on it. So, who knows, maybe I'll revisit it again sometime, but for now Shoulda has become my goto testing system.
Hey Adam — if you're looking for a solid, tiny RSpec, Christian Neukirchen's Bacon fits the bill:
http://www.ruby-forum.com/topic/137928
It looks like it does pretty much exactly what you're asking for, and weighs in at a featherweight ~300 lines of Ruby.
I'm a big fan of Bacon. It lets you do RSpec-style BDD tests, but with more familiar, less-magic syntax. It also works on ruby 1.9!
lambda { ... }.should raise_error(ArgumentError)
becomes:
lambda { ... }.should.raise(ArgumentError).message.should == "wrong args"
Post a comment
Required fields in bold.