Panasonic Youth rob sanheim writes about software, business, ruby, music, stuff and things



Posted
29 December 2006 @ 4am

Tagged
Agile, BDD, Rails, Ruby

Discuss

BDD in Rails - test/spec and rspec

bdd survival

I've been playing a bit with test/spec lately in attempts to start doing more BDD. I've been following RSpec, the better known Ruby BDD library for awhile, but decided against it since it just doesn't look practical for use in an established project with around ~400 test cases. It also seems that development is very active to keep up with edge rails, but ultimately a sure path to frustration as little changes in edge break the rspec plugin where they dealing with Rails internals. There just isn't time to convert old style test cases to rspec, and there isn't time to track down bugs due to conflicts between rspec, the rspec rails plugin, and bleeding edge Rails. Also, why didn't Rspec just use Mocha/Stubba -- whats up with that?

So back to test/spec. Test/spec is small interface that sits on top of test/unit and adds "specify", "context", and "should" that just work inside normal test cases. So most of the specs I've written looked very similiar to rspec, except that they can freely mixed with legacy test cases without issue. Using the "context/specify" block format for specifications does break textmate integration for running specific test cases, and also trips up autotest a little bit, but those issues could probably be fixed easily. Test/spec doesn't attempt to tie into Rails at all, so you don't get nice Rails specific should assertions, but they are easy enough to add. Plus you don't have to worry about test/spec breaking when Rails 2.0 deprecates your favorite assertions.

I did have a minor annoyance where I had to declare fixtures (or other class level stuff) both in the normal top level and inside context blocks if mixing test cases and specs. Example:

class SearchControllerTest <Test::Unit::TestCase
  fixtures :users  # fixture here

  context "routing" do
    fixtures :users # and here
   
    specify "i am the walrus" do
    end
  end
 
  def test_should_go_to_bed_earlier
    my.bedtime.should.be.before.2.am
  end

Again, a minor thing, and I'm sure there is ruby magic that could be used to get around it.

Overall, I do find the specs read easier, which I think is the main thing and what really makes any of this stuff worth doing. Once you start saying "test_should" instead of "test_blah" you are already 80% of the way there in your head, so its really just a matter of getting the specs to read well. Lately I've just been using "foo.should.not.be.nil" inside normal test cases, so I can use the tools I like and still think "should" instead of "assert". I really dislike the.dot.notation and plan on hacking it to allow underscores, or maybe strings like Rick is doing.

So, yay on test/spec and doing BDD with less code, even for "legacy" Rails projects with a lot of test cases. Hopefully rspec will really be ready for Rails production work after 1.2 comes out and things settle down. For now, test/spec + mocha/stubba it is.


6 Comments

Posted by
John Nunemaker
29 December 2006 @ 8am

You don’t even need the outside class SearchControllerTest


Posted by
Rob
29 December 2006 @ 4pm

Hmm…I know thats true, but I think removing that would totally break the mapping that autotest does. I”ll give it a try, though.


Posted by
John Nunemaker
29 December 2006 @ 4pm

I’m actually using it with autotest and haven’t noticed any problems. But I’m not trying to do anything fancy. Maybe you are. Not sure what the mapping your are talking about is.



[…] In Rob Sanheim’s blog on comparing test/spec w/ rspec, Rob pointed out that he had “been following RSpec, the better known Ruby BDD library for awhile, but decided against it since it just doesn’t look practical for use in an established project with around ~400 test cases.” […]


Posted by
David Chelimsky
1 March 2007 @ 8am

“Also, why didn’t Rspec just use Mocha/Stubba — whats up with that?”

When RSpec’s mock framework was originally written, mocha/stubba was far less mature than it is now. Things are obviously different now, and we do plan to provide a means of choosing RSpec’s mock framework or any other framework you wish to use, provided that framework has decoupled itself sufficiently from test/unit, which is true of mocha/stubba.

“I really dislike the.dot.notation and plan on hacking it to allow underscores, or maybe strings like Rick is doing.”

Two things here - 0.8 uses expression matchers that look like this:

board.should have_at_least(3).pieces

You can now use these right in your test/unit test cases:

http://blog.davidchelimsky.net/articles/2007/03/01/spec-expectations-and-test-unit-testcase-together-again-at-last

As for Rails, the 0.8 release of Spec::Rails has much better Rails integration than before. You have access to all of the rails assertions (the contexts derive from Test::Unit::TestCase) plus a number of rspec-style expectations.

It is always tested against 1.1.6, 1.2.1 and 1.2.2. We also run tests against edge, but we do not let failures there prevent us from doing releases. That’s more for us to keep abreast of what issues lie in store when the next Rails version is released.

So give it a try! And please report on your experience, good or bad. It can only help improve things for the future.

Cheers,
David


Leave a Comment

Contegix is Amazing. Plus Thoughts on Rails Hosting One either blogs or one works