rspec-1.1.12 is released
January 13th, 2009
We just released rspec-1.1.12. You can read the changelogs for rspec and rspec-rails for all the details, but are some changes that you should definitely know about.
Cucumber is the new Story Runner
rspec-1.1.12 is the last release that will ship with the Story Runner bundled. With the next release, we will do the one and only gem release of repo so you won’t be forced to upgrade to Cucumber Thanks to Chad Humphries for stepping in and extracting the Story Runner to a separate repo.
The Story Runner is deprecated, however, and we will not be maintaining it. If anybody wants to maintain it, you’re welcome to. Just fork the repo and have at it.
Why are we deprecating the Story Runner? Because Aslak Hellesøy’s Cucumber library kicks its ass. Easier setup means lower barrier to entry, building on treetop means great feedback with backtraces plus support for an ever-growing list of written languages. And migrating from RSpec Stories is a snap. So what are you waiting for?
### Rails 1.2.6 will no longer be supported by new versions of rspec
rspec-rails-1.1.12 is the last rspec release that will support pre-2.0 releases of Rails. For anybody interested in maintaining rspec-rails for rails-1.2.6, I’ve created a 1.1-maintenance branch, which you are welcome to fork and go nuts. There is also a 1.1-maintenance branch for rspec, so you’d be working from a matched pair.
So that’s what’s going away. Here’s what’s new!
it { should provide_an_implicit_subject }
Ever write a code example like this?
1 2 3 4 5 6 7 | describe Person do it "should validate presence of email" do person = Person.new(:email =>; nil) person.should_not be_valid person.should have(1).error_on(:email) end end |
That comes up pretty often in rails apps when spec’ing out models. There are a few matcher libraries out there like rspec-on-rails-matchers that provide matchers like this validate_presence_of(:email), which let you reduce the previous example to this:
1 2 3 4 5 | describe Person do it "should validate presence email" do Person.new.should validate_presence_of(:email) end end |
Of course, the next step is to want to get rid of the redundancy between the docstring passed to #it and the matcher, so you end up with this:
1 2 3 4 5 | describe Person do it do Person.new.should validate_presence_of(:email) end end |
Do it? Ugh! This has always driven me nuts when I see it do, so I’d make that this:
1 2 3 | describe Person do it { Person.new.should validate_presence_of(:email) } end |
Well, thanks to a contribution from Joe Ferris from thoughtbot, we now have an implicit subject in our specs, so you can do this:
1 2 3 | describe Person do it { should validate_presence_of(:email) } end |
w00t! Now that is concise. Brandon Keepers wrote about this a while back, but this feature hadn’t actually been released until rspec-1.1.12.
it { should handle_slightly_more_complex_conditions }
The implicit subject feature works by creating a new instance of the class passed to describe for each example. In the last example above, when the example receives the #should message, it delegates it to a new instance of Person. That’s fine for a lot of cases, but sometimes we’ll need a bit more context than simply calling new. For those situations, you can create your own subject for an example group like this:
1 2 3 4 5 6 7 8 | describe Person do describe "born 19 years ago" do subject { Person.new(:birthdate => 19.years.ago } it { should be_eligible_to_vote } it { should be_eligible_to_enlist } it { should_not be_eligible_to_drink } end end |
Happy Spec’ing, and Happy New Year!


January 13th, 2009 at 3:55 am
I like this implicit subject feature quite a bit. Is there any easy way to specify results of methods called on the object using this syntax? i.e. any way to translate:
it "should have a default name" do @foo.name.should eql("bar") endinto the new syntax? In going through the existing specs for my current project, I find a number of situations like this.
January 13th, 2009 at 3:55 am
@Greg: you could write custom matchers to support:
describe Thing do it { should have_default_name_of("bar") } end… or perhaps:
describe Thing do it { should default_to(:name => "bar") } endThe first one would look like this:
def have_default_name_of(name) simple_matcher do |actual, matcher| matcher.failure_message = "expected default name of #{name}" actual.name == name end endJanuary 13th, 2009 at 3:55 am
Thanks. I ended up writing something more generic (using method_missing) to test the value of any attribute (or any method with no arguments, really).
January 13th, 2009 at 3:55 am
How about:
it { should be_named("bar") }You should be able to define be_xxx or have_xxx without interfering with the Be or Has matchers – those are only invoked via method_missing.
January 13th, 2009 at 3:55 am
Mine uses method_missing too, though – so return_the_sym(arg) verifies that subject.send(sym) == arg. That seemed more expedient than writing a custom matcher for every attribute I wanted to test in this manner, although there are always tradeoffs to using method_missing, of course.
January 13th, 2009 at 3:55 am
David,
is deprecated and will be removed in the rspec-rails release that follows the rails-2.3.0 release.
January 13th, 2009 at 3:55 am
David,
My relevant ticket is here: http://rspec.lighthouseapp.com/projects/5645/tickets/646-feature-request-test-named-routes-in-rails-controller-examples#ticket-646-1
January 13th, 2009 at 3:55 am
+1 for Jim Gay’s suggestion.
January 13th, 2009 at 3:55 am
Nevermind David, found your commit message at GitHub and fixed my specs. Thanks!
January 13th, 2009 at 3:55 am
Hi,
Thanks for making testing more enjoyable.
This actually comes from http://github.com/joshknowles/rspec-on-rails-matchers/tree/master ’s validate_uniqueness_of
January 13th, 2009 at 3:55 am
Jim, Craig – I’d be adverse to adding another keyword like “the”, but we’ve seen requests for other keywords before. Maybe what we need is a way to declare your own keywords for creating examples and/or example groups. Then you’d be able to do something like this:
Spec::Example.keywords_for :example { :the }WDYT?
January 13th, 2009 at 3:55 am
Sébastien, obj.stub(:msg) is not deprecated. Where did you get the idea that it is?
January 13th, 2009 at 3:55 am
David, I understood that from http://rspec.info/documentation/changes-rspec.html but as not natural English speakers I might just have understood wrong.
Warm regards,
January 13th, 2009 at 3:55 am
Something like
keywords_forsounds like a good idea. I agree that another keyword could be unnecessary bloat.January 13th, 2009 at 3:55 am
Sébastien – none of that is deprecated. There was a bug that allowed you to write passing examples that should fail. Please take a look at the bug report and see if the information there clarifies things for you.
January 13th, 2009 at 3:55 am
David, Ok got it, thanks a lot for the details, that makes all clear now.
January 13th, 2009 at 3:55 am
On all examples with an implicit subject, I now get a huge failure message essentially saying that the matcher doesn’t have a defined #description. I originally thought this was an issue with only my custom matchers (it wasn’t, they had it defined), but then I found that it also prints that for failures on builtins like “it { should be_blank }”.
January 13th, 2009 at 3:55 am
Also, with regard to testing an implicit object’s accessors, what about:
January 13th, 2009 at 3:55 am
[code] def self.its(attribute, &block) describe(@attribute) do define_method(:subject) { super.send(attribute) } it(&block) end end [/code]
January 13th, 2009 at 3:55 am
Dammit.
def self.its(attribute, &block) describe(@attribute) do define_method(:subject) { super.send(attribute) } it(&block) end endJanuary 13th, 2009 at 3:55 am
For god’s sake.
January 13th, 2009 at 3:55 am
The implicit subjects are certainly sexy but I don’t think I’ll be using them.
January 13th, 2009 at 3:55 am
For better or for worse, if you’re using RSpec you’re already neck-deep in magic-land. It’s kind of a forgone conclusion that people unfamiliar with it are going to confused.
January 13th, 2009 at 3:55 am
Stephen, I like your idea. I think you mean describe(attribute), instead of describe(@attribute) though so that the attribute is put into the output of the spec.
January 13th, 2009 at 3:55 am
Stephen Touset’s implementation of its() looks like it’ll do in place of Jim Gay’s suggestion of implementing the(). It doesn’t read quite as nicely, but it’s close. And it has the advantage of putting the attribute name more in focus.