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.”

As it turns out, rspec-0.8 has done a much better job of isolating components. It’s not quite ideal yet, but it is sufficient to support using RSpec’s expectations right in your Test::Unit::TestCases.

To make this happen, you need to require a few things:

require 'test/unit'
require 'rubygems'
gem 'rspec'
require 'spec/expectations'
require 'spec/matchers'

‘spec/expectations’ adds #should and #should_not to your objects. ‘spec/matchers’ provides RSpec’s Expression Matchers, which you then need to explicitly include in the TestCase:

class ThingTest < Test::Unit::TestCase
  include Spec::Matchers

Here’s an example with one passing and one failing test.

require 'test/unit'
require 'rubygems'
gem 'rspec'
require 'spec/expectations'
require 'spec/matchers'

class ThingTest < Test::Unit::TestCase
  include Spec::Matchers

  def setup
    @thing = Thing.new
  end

  def test_should_have_4_subthings #should fail
    @thing.should have(4).sub_things
  end

  def test_should_have_3_subthings #should pass
    @thing.should have(3).sub_things
  end
end

class Thing
  def sub_things
    [1,2,3]
  end
end

Assuming that you have rspec-0.8.0 or better, this should produce the following output:

$ ruby thing_test.rb 
Loaded suite thing_test
Started
.E
Finished in 0.000642 seconds.

  1) Error:
test_should_have_4_subthings(ThingTest):
Spec::Expectations::ExpectationNotMetError: expected 4 sub_things, got 3
    /usr/local/lib/ruby/gems/1.8/gems/rspec-0.8.1/lib/spec/expectations.rb:55:in `fail_with'
    /usr/local/lib/ruby/gems/1.8/gems/rspec-0.8.1/lib/spec/expectations/handler.rb:17:in `handle_matcher'
    /usr/local/lib/ruby/gems/1.8/gems/rspec-0.8.1/lib/spec/expectations/extensions/object.rb:28:in `should'
    thing_test.rb:15:in `test_should_have_4_subthings'

2 tests, 0 assertions, 0 failures, 1 errors

So now, although we’d like to see people who want to use RSpec using RSpec, this should lower the barrier to those who wish to migrate existing systems gradually.

2 Responses to “Spec::Expectations and Test::Unit::TestCase, together again at last”

  1. Rob Sanheim
    Rob Sanheim Says:

    Thanks for writing about this, David. Its nice to see that rspec is becoming friendlier for “legacy” rails projects. We have enough code using test/spec now that I’m definitely not going to rewrite existing projects using it, but I’ll certainly consider rspec for new projects. Now, if only mocha would place nice with rspec… =)

  2. David Chelimsky
    David Chelimsky Says:

    FYI – I’ve added an easier way to do this to the soon-to-be-released rspec-0.9

    require 'test/unit'
    require 'spec/test_case_adapter'
    
    class MyTest < Test::Unit::TestCase
      #...
    end
    

Leave a Reply (Textile Enabled)