Why No Love For RSpec?

bdd rspec rubinius

Tue Apr 22 20:11:00 -0700 2008

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.