TL;DR

Myron Marston is taking over leadership of the RSpec project, and will be the lead maintainer of the rspec-core, rspec-expectations, and rspec-mocks gems.

Andy Lindeman is taking over as lead maintainer of the rspec-rails gem.

Myron Marston is RSpec’s new project lead

Myron Marston has been contributing to RSpec since the ramp up to the 2.0 release in 2010, and joined the core team in early 2011. In addition to solid contributions to the code base, Myron has taken responsibility for many bug reports, feature requests, pull requests, etc. He also makes a habit of answering RSpec-related questions on Stack Overflow and Twitter, and he does this all with thoughtfulness, patience, and wisdom.

I can’t think of a better choice to lead the RSpec project, so I invited him to do so. Thankfully, SEOmoz, Myron’s employer, is allowing him to work on RSpec during work hours, and so he accepted.

In addition to the overall project lead, Myron will be the lead maintainer of the rspec-core, rspec-expectations, and rspec-mocks gems. While Myron uses these core rspec libs every day for his work, he doesn’t do much with Rails, so we discussed and agreed that we’d ask somebody else to take care of the rspec-rails gem. Enter Andy Lindeman.

Andy Lindeman is the new lead maintainer of rspec-rails

Andy Lindeman is the newest addition to the rspec core team. Like Myron, Andy takes great care in shepherding pull requests and answering questions in addition to making his own rock solid contributions. Andy also writes Rails apps and does Rails training at Big Nerd Ranch, which puts him in a great position to ensure that rspec-rails keeps up with changes in Rails remains a great choice for developing Rails apps.

Thanks in part to Big Nerd Ranch for their support of Andy’s work on RSpec, Andy has agreed to take the lead on rspec-rails.

As for me …

When Dave Astels introduced Steven Baker’s new RSpec library to me back in 2005, I started submitting patches, Steven gave me commit rights and, a year later, he decided to move on to other work and offered me leadership of the project. I was overjoyed to accept.

In those days, I was teaching TDD/Refactoring courses for Object Mentor. I was encouraged to work on OSS in my bench time, and I was particularly interested in tools that helped to promote the documentation and design aspects of TDD. RSpec and some of the early definitions/discussions of BDD (”it’s all behavior!”) fit perfectly into my thinking and my world.

After I left Object Mentor, RSpec was part of my day to day work on Ruby applications, but most of my work on its maintenance moved to my spare time. This was fine at first, as I had the support of employers and family, but I found myself doing less and less of pretty much everything else that I enjoy and learn from.

Back in June, I joined a project team at DRW Trading that deals in a lot of Clojure and almost no Ruby. In the roughly 6 months since, I’ve been learning a new domain, a new language, new programming models, and even a new text editor. I consider myself extraordinarily fortunate to be able to learn all of these new things, but I’ve found myself less and less able to balance my work on RSpec with my job and with everything else I want to do.

And so, it is time.

Of course, I’ll continue to contribute to the project and surrounding conversation, and I look forward to seeing all my friends in the community at assorted conferences in the coming year(s). I’ll just be arriving without my RSpec Lead hat on.

Thank you to Steven Baker for handing me the wheel, and thank you to everybody who has participated in the project and all RSpec users for your support over these 6+ years. It’s been a great honor and a great pleasure.

TL;DR

Explicit use of the “subject” abstraction is a code smell, and should be refactored to use a more intention revealing name whenever possible.

One liners

rspec-core supports a one-liner syntax to reduce the noise of common requirements like validations:

Without support for this syntax, the same example might look like this:

The benefit of this more verbose example is that it we can read it and understand all the parts right away: an object is initialized and assigned to a local variable, then that variable is used for an expectation.

The benefit of the one-liner is that it’s terse and expressive, but that comes at a cost: you can’t see what the expectation is being evaluated against, so you have to understand some underlying mechanics in order to isolate/understand a failure.

The subject abstraction

Behind the scenes, the one-liner uses a “subject” abstraction supported by two methods named subject. One is a class method on ExampleGroup, used to declare the “subject” of all of the examples in the group:

The other is an instance method on ExampleGroup. The first time it is called within an example the block passed to the class’ subject method is evaluated and its result memoized, returning the same value from that and each subsequent subject call:

Here is what they look like together:

The problem with this example is that the word “subject” is not very intention revealing. That might not appear problematic in this small example because you can see the declaration on line 3 and the reference on line 6. But when this group grows to where you have to scroll up from the reference to find the declaration, the generic nature of the word “subject” becomes a hinderance to understanding and slows you down.

In this case, we’d be better served by using a method (or a let declaration) with an intention revealing name:

If we can do that, you might wonder why we have “subject” at all. Well, it was originally designed to never be seen:

Implicit subject

Note in the example with subject { Article.new }, that the subject declaration is initializing an Article with no args. Since RSpec knows that the first argument to describe is the Article class, it can store a similar block in the background as a default, implicit subject declaration, leaving us with:

That’s a little better, but now subject appears out of nowhere in the example, leaving the reader to wonder where it came from. To remove the need for explicitly referencing subject, the example delegates should and should_not to subject when it is, itself, the receiver:

Starting that line with “should” seems a bit odd though, so the final step is to do it all in one line:

Now we have a completely implicit subject, and the result reads quite nicely in both the code and the output when run with --format documentation:

Article
  should validate presence of :title

We still need to trust that something is doing some work for us but it’s all operating at the same level of abstraction, so we don’t have to try to interpret half of the functionality.

Avoid explicit use of subject

Intention revealing names are crucial if you want to be able to quickly scan and understand code as you navigate around different parts of a system. This is as true for specs as it is for implementation, and the generic nature of the word “subject” makes it a poor choice when a more intention revealing name can be used.

Is an explicit subject ever OK?

Guidelines are guidelines; YMMV. In general I would recommend that if there is a reasonable way to use an intention revealing name instead of “subject”, you should. The only use case I can think of in RSpec in which another name can’t be used is the one liner syntax:

Here we have to use subject because that’s the only way to tell RSpec where to send should and should_not. In my opinion, any other explicit appearance of subject can and should be refactored to use an intention revealing name.

Update 2012-05-15

Based on feedback on this post, I added support for a “named subject,” which lets you reference the declared subject implicitly in one-liners and with an intention revealing name in standard examples:

This will be released with rspec-core-2.11. Keep your eyes out for it!

These are patch releases recommended for anybody who has already upgraded to 2.10.

rspec-mocks-2.10.1

full changelog

Bug fixes

  • fix regression of edge case behavior
    • fixed failure of object.should_receive(:message).at_least(0).times.and_return value
    • fixed failure of object.should_not_receive(:message).and_return value

rspec-rails-2.10.1

full changelog

Bug fixes

rspec-2.10 is released!

May 3rd, 2012

API Docs (RDoc)

http://rubydoc.info/gems/rspec-core
http://rubydoc.info/gems/rspec-expectations
http://rubydoc.info/gems/rspec-mocks
http://rubydoc.info/gems/rspec-rails

Cucumber docs

http://relishapp.com/rspec/rspec-core
http://relishapp.com/rspec/rspec-expectations
http://relishapp.com/rspec/rspec-mocks
http://relishapp.com/rspec/rspec-rails

rspec-core-2.10.0

full changelog

Enhancements

  • Add prepend_before and append_after hooks (preethiramdev)
    • intended for extension libs
    • restores rspec-1 behavior
  • Reporting of profiled examples (moro)
    • Report the total amount of time taken for the top slowest examples.
    • Report what percentage the slowest examples took from the total runtime.

Bug fixes

  • Properly parse SPEC_OPTS options.
  • example.description returns the location of the example if there is no explicit description or matcher-generated description.
  • RDoc fixes (Grzegorz Świrski)
  • Do not modify example ancestry when dumping errors (Michael Grosser)

rspec-expectations-2.10.0

full changelog

Enhancements

  • Add new start_with and end_with matchers (Jeremy Wadsack)
  • Add new matchers for specifying yields (Myron Marson):
    • expect {...}.to yield_control
    • expect {...}.to yield_with_args(1, 2, 3)
    • expect {...}.to yield_with_no_args
    • expect {...}.to yield_successive_args(1, 2, 3)
  • match_unless_raises takes multiple exception args

Bug fixes

  • Fix be_within matcher to be inclusive of delta.
  • Fix message-specific specs to pass on Rubinius (John Firebaugh)

rspec-mocks-2.10.0

full changelog

Bug fixes

  • fail fast when an exactly or at_most expectation is exceeded

rspec-rails-2.10.0

full changelog

Bug fixes

  • render_views called in a spec can now override the config setting. (martinsvalin)
  • Fix render_views for anonymous controllers on 1.8.7. (hudge, mudge)
  • Eliminate use of deprecated process_view_paths
  • Fix false negatives when using route_to matcher with should_not
  • controller is no longer nil in config.before hooks
  • Change request.path_parameters keys to symbols to match real Rails environment (Nathan Broadbent)
  • Silence deprecation warnings in pre-2.9 generated view specs (Jonathan del Strother)

rspec-2.6.0 is released

May 12th, 2011

rspec-core-2.6.0

full changelog

  • Enhancements

    • shared_context (Damian Nurzynski)
      • extend groups matching specific metadata with:
        • method definitions
        • subject declarations
        • let/let! declarations
        • etc (anything you can do in a group)
    • its([:key]) works for any subject with #[]. (Peter Jaros)
    • treat_symbols_as_metadata_keys_with_true_values (Myron Marston)
    • Print a deprecation warning when you configure RSpec after defining an example. All configuration should happen before any examples are defined. (Myron Marston)
    • Pass the exit status of a DRb run to the invoking process. This causes specs run via DRb to not just return true or false. (Ilkka Laukkanen)
    • Refactoring of ConfigurationOptions#parse_options (Rodrigo Rosenfeld Rosas)
    • Report excluded filters in runner output (tip from andyl)
    • Clean up messages for filters/tags.
    • Restore –pattern/-P command line option from rspec-1
    • Support false as well as true in config.full_backtrace= (Andreas Tolf Tolfsen)
  • Bug fixes

    • Don’t stumble over an exception without a message (Hans Hasselberg)
    • Remove non-ascii characters from comments that were choking rcov (Geoffrey Byers)
    • Fixed backtrace so it doesn’t include lines from before the autorun at_exit hook (Myron Marston)
    • Include RSpec::Matchers when first example group is defined, rather than just before running the examples. This works around an obscure bug in ruby 1.9 that can cause infinite recursion. (Myron Marston)
    • Don’t send example_group_[started|finished] to formatters for empty groups.
    • Get specs passing on jruby (Sidu Ponnappa)
    • Fix bug where mixing nested groups and outer-level examples gave unpredictable :line_number behavior (Artur Małecki)
    • Regexp.escape the argument to –example (tip from Elliot Winkler)
    • Correctly pass/fail pending block with message expectations
    • CommandLine returns exit status (0/1) instead of true/false
    • Create path to formatter output file if it doesn’t exist (marekj).

rspec-expectations-2.6.0

full changelog

  • Enhancments

    • change matcher accepts Regexps (Robert Davis)
    • better descriptions for have_xxx matchers (Magnus Bergmark)
    • range.should cover(*values) (Anders Furseth)
  • Bug fixes

    • Removed non-ascii characters that were choking rcov (Geoffrey Byers)
    • change matcher dups arrays and hashes so their before/after states can be compared correctly.
    • Fix the order of inclusion of RSpec::Matchers in Test::Unit::TestCase and MiniTest::Unit::TestCase to prevent a SystemStackError (Myron Marston)

rspec-mocks-2.6.0

full changelog

  • Enhancements

    • Add support for any_instance.stub and any_instance.should_receive (Sidu Ponnappa and Andy Lindeman)
  • Bug fixes

    • fix bug in which multiple chains with shared messages ending in hashes failed to return the correct value

rspec-rails-2.6.0

full changelog

  • Enhancements

    • rails 3 shortcuts for routing specs (Joe Fiorini)
    • support nested resources in generators (Tim McEwan)
    • require ‘rspec/rails/mocks’ to use mock_model without requiring the whole rails framework
    • Update the controller spec generated by the rails scaffold generator:
    • Add documentation to the generated spec
    • Use any_instance to avoid stubbing finders
    • Use real objects instead of mock_model
    • Update capybara integration to work with capy 0.4 and 1.0.0.beta
    • Decorate paths passed to [append|prepend]_view_paths with empty templates unless rendering views. (Mark Turner)
  • Bug fixes

    • fix typo in “rake spec:statsetup” (Curtis Schofield)
    • expose named routes in anonymous controller specs (Andy Lindeman)
    • error when generating namespaced scaffold resources (Andy Lindeman)
    • Fix load order issue w/ Capybara (oleg dashevskii)
    • Fix monkey patches that broke due to internal changes in rails-3.1.0.beta1

We’re doing one more release candidate to update rspec-rails to work with rails-3.1.0.beta1. This will hopefully be the last release candidate, with a final release coming in just a few days.

rspec-rails-2.6.0.rc6

full changelog

  • Bug fixes
    • Fix load order issue w/ Capybara (oleg dashevskii)
    • Relax the dependencies on rails gems to >= 3.0 (Joel Moss)
    • Fix monkey patches that broke due to internal changes in rails-3.1.0.beta1

rspec-core-2.6.0.rc6

full changelog

  • Enhancements
    • Restore –pattern/-P command line option from rspec-1
    • Support false as well as true in config.full_backtrace= (Andreas Tolf Tolfsen)

This release addresses issues that were raised in the rspec-core-2.6.0.rc2 release.

NOTE: this was originally released as rc3, but there was a problem related to rubygems that made it uninstallable.

rspec-core-2.6.0.rc4

full changelog

Enhancements

  • Clean up messages for filters/tags.

rspec-mocks-2.6.0.rc4

full changelog

Bug fixes

  • Support multiple calls to any_instance in the same example (Sidu Ponnappa)

rspec-rails-2.6.0.rc4

full changelog

Enhancements

  • Update the controller spec generated by the rails scaffold generator:
    • Add documentation to the generated spec
    • Use any_instance to avoid stubbing finders
    • Use real objects instead of mock_model
  • Update capybara integration to work with capy 0.4 and 1.0.0.beta
  • Decorate paths passed to [append|prepend]_view_paths with empty templates unless rendering views. (Mark Turner)

rspec-1.3.2 and rspec-rails-1.3.4 have been released!

This is primarily a bug-fix release of the rspec-1.x series, and is recommended for all users who have not yet upgraded to rspec-2.

rspec-rails-1.3 users will need to upgrade to rspec-rails-1.3.4, which depends on rspec ~> 1.3.2 (meaning 1.3.2 and up, but not 2.0).

rspec 1.3.2

  • Enhancements

    • Raise a meaningful error when an argument-scoped stub is called with the wrong args (Alexey)
    • Dev: ignore .rbc files (Myron Marston)
  • Bug fixes

    • Fix regression in which an expectation should return the value from a previously defined stub of the same method (Tom Stuart)
    • Support heckling class methods (Dan Kubb)
    • Only try to pass messages to the superclass if the superclass responds to the method (Andrew Selder)

rspec-rails-1.3.4 is released!

rspec-rails 1.3.4

  • No new code
  • Depends on rspec ~> 1.3.2
    • rspec-rails 1.3.3 depended on rspec-1.3.1 explicitly, so this release allows you to upgrade to rspec-1.3.2 with rspec-rails.

rspec-rails-2.4.1 is released!

January 3rd, 2011

This is a bug fix release recommended for all users who have upgraded to rspec-rails-2.4.

rspec-rails-2.4.1 / 2011-01-03

full changelog

  • Bug fixes
    • fixed bug caused by including some Rails modules before RSpec’s RailsExampleGroup

RSpec 2 Documentation

December 23rd, 2010

RSpec-2 was released with, admittedly, less than complete documentation. The new docs are a work in progress that need your help. It’s all open source, and anybody who can write Markdown or Cucumber can contribute to it. Here’s how:

You

Fork the git repo you of the rspec project to which you want to contribute docs, make additions/edits to appropriate files in the features directory, and submit pull requests.

Me

I review, tweak, and organize the contributions, merge them in, and then push them to http://relishapp.com.

Source repositories

With the exception of the front page, all of the docs are stored in the features directories of rspec repositories on github:

rspec-core
rspec-expectations
rspec-mocks
rspec-rails

Relish

Relish is an application developed by Justin Ko and Matt Wynne to display Cucumber features for open and closed source projects. It is still fairly new and under regular development, so presentation, navigation, etc, are all improving as we go.

Cucumber and Markdown docs live in the features directory (and its subdirectories) in each project. There is a .nav file that sorts the navigation links. It’s pretty self-explanatory, and you probably won’t need to touch it. But now you know what it is.

Cukes

If you know what you’re doing with Cucumber, feel free to submit executable scenarios. Please make sure you run them and they pass against ruby-1.8.6, 1.8.7, 1.9.1, and 1.9.2. Bonus points for jruby and rbx.

Even if you don’t know what you’re doing with Cucumber, all of the Cucumber features have a narrative section at the top, which is plain text and not executed. Relish processes this section through Markdown, so it can be as expressive as you know how to make Markdown “speak.” Patches that add to this narrative are great, but so are patches that simply re-format them to make them more readable.

Pages

In addition to the Cucumber features, Relish supports pages using Markdown. Each project has a README file in the features directory which is displayed as the front page for that project. Each subdirectory below features can also have a README (optional), which would be displayed as the front page of that directory.

In addition to the README files, we can add [arbitrary pages using Markdown as well](http://relishapp.com/rspec/rspec-core/v/2-3/file/upgrade](http://relishapp.com/rspec/rspec-core/v/2-3/file/upgrade).

Questions?

If you want to help and you’re not sure where to start, feel free to contact me via email to the rspec-users list or a github issue in the project you’re interested in contributing to.

Thanks in advance for your help!