Logo: Relish

  1. Sign up
  2. Sign in

Project: RSpec Core 3.0


The Changelog has a complete list of everything that changed, but
here are more detailed explanations for those items that warrant them.


what's new

rspec command with no arguments

Now you can just type


to run all the specs in the spec directory. If you keep your specs in a
different directory, you can override the default with the --default-path
argument in a config file:

# in .rspec
--default-path specs

rspec command supports multiple line numbers

Use either of the following to run the examples declared on lines
37 and 42 of a_spec.rb:

rspec path/to/a_spec.rb --line_number 37 --line_number 42
rspec path/to/a_spec.rb:37:42

what's changed

skip_bundler and gemfile rake task options are deprecated and have no effect.

RSpec's rake task invokes the rspec command in a subshell. If you invoke
bundle exec rake or include Bundler.setup in your Rakefile, then
Bundler will be activated in the subshell as well.

Previously, the rake task managed this for you based on the presence of a
Gemfile. In 2.7.0.rc1, this is done based on the presence of the
BUNDLE_GEMFILE environment variable, which is set in the parent shell by Bundler.

In 2.7.0.rc2 (not yet released), the rake task doesn't do anything at all.
Turns out Bundler just does the right thing, so rspec doesn't need to do


new APIs for sharing content

Use shared_context together with include_context to share before/after
hooks, let declarations, and method definitions across example groups.

Use shared_examples together with include_examples to share examples
across different contexts.

All of the old APIs are still supported, but these 4 are easy to remember, and
serve most use cases.

See shared_context and shared_examples under "Example Groups" for more


Yes it's a long name, but it's a great feature, and it's going to be the
default behavior in rspec-3. This lets you add metadata to a group or example
like this:

describe "something", :awesome do

And then you can run that group (or example) using the tags feature:

rspec spec --tag awesome

We're making this an opt-in for rspec-2.6 because describe "string", :symbol
is a perfectly legal construct in pre-2.6 releases and we want to maintain
compatibility in minor releases as much as is possible.



Use this to configure RSpec to use rspec/expectations (default),
stdlib assertions (Test::Unit with Ruby 1.8, MiniTest with Ruby 1.9),
or both:

RSpec.configure do |config|
  config.expect_with :rspec          # => rspec/expectations
  config.expect_with :stdlib         # => Test::Unit or MinitTest
  config.expect_with :rspec, :stdlib # => both


Command line


Now you can tag groups and examples using metadata and access those tags from
the command line. So if you have a group with :foo => true:

describe "something", :foo => true do
  it "does something" do
    # ...

... now you can run just that group like this:

rspec spec --tags foo


Add this flag to the command line to tell rspec to clean up and exit after the
first failure:

rspec spec --fail-fast


:if and :unless keys

Use :if and :unless keys to conditionally run examples with simple boolean

describe "something" do
  it "does something", :if => RUBY_VERSION == 1.8.7 do
    # ...
  it "does something", :unless => RUBY_VERSION == 1.8.7 do
    # ...

Conditionally 'pending' examples

Make examples pending based on a condition. This is most useful when you
have an example that runs in multiple contexts and fails in one of those due to
a bug in a third-party dependency that you expect to be fixed in the future.

describe "something" do
  it "does something that doesn't yet work right on JRuby" do
    pending("waiting for the JRuby team to fix issue XYZ", :if => RUBY_PLATFORM == 'java') do
      # the content of your spec

This example would run normally on all ruby interpretters except JRuby. On JRuby,
it uses the block form of pending, which causes the example to still be run and
will remain pending as long as it fails. In the future, if you upgraded your
JRuby installation to a newer release that allows the example to pass, RSpec
will report it as a failure (Expected pending '...' to fail. No Error was raised.),
so that know that you can remove the call to pending.

New features in rspec-core-2.0


The new runner for rspec-2 comes from Micronaut.


In rspec-2, every example and example group comes with metadata information
like the file and line number on which it was declared, the arguments passed to
describe and it, etc. This metadata can be appended to through a hash
argument passed to describe or it, allowing us to pre and post-process
each example in a variety of ways.


The most obvious use is for filtering the run. For example:

# in spec/spec_helper.rb
RSpec.configure do |c|
  c.filter_run :focus => true

# in any spec file
describe "something" do
  it "does something", :focus => true do
    # ....

When you run the rspec command, rspec will run only the examples that have
:focus => true in the hash.

You can also add run_all_when_everything_filtered to the config:

RSpec.configure do |c|
  c.filter_run :focus => true
  c.run_all_when_everything_filtered = true

Now if there are no examples tagged with :focus => true, all examples
will be run. This makes it really easy to focus on one example for a
while, but then go back to running all of the examples by removing that
argument from it. Works with describe too, in which case it runs
all of the examples in that group.

The configuration will accept a lambda, which provides a lot of flexibility
in filtering examples. Say, for example, you have a spec for functionality that
behaves slightly differently in Ruby 1.8 and Ruby 1.9. We have that in
rspec-core, and here's how we're getting the right stuff to run under the
right version:

# in spec/spec_helper.rb
RSpec.configure do |c|
  c.exclusion_filter = { :ruby => lambda {|version|
    !(RUBY_VERSION.to_s =~ /^#{version.to_s}/)

# in any spec file
describe "something" do
  it "does something", :ruby => 1.8 do
    # ....

  it "does something", :ruby => 1.9 do
    # ....

In this case, we're using exclusion_filter instead of filter_run or
filter, which indicate inclusion filters. So each of those examples is
excluded if we're not running the version of Ruby they work with.

Shared example groups

Shared example groups are now run in a nested group within the including group
(they used to be run in the same group). Nested groups inherit before, after,
around, and let hooks, as well as any methods that are defined in the parent

This new approach provides better encapsulation, better output, and an
opportunity to add contextual information to the shared group via a block
passed to it_should_behave_like.

See features/example_groups/shared_example_group.feature for more information.

NOTICE: An example group including shared examples no longer has access to
any of the methods, hooks or state defined inside the shared group. This will
break rspec-1 specs that were using shared example groups to extend the behavior
of including groups.

Upgrading from rspec-1.x

rspec command

The command to run specs is now rspec instead of spec.

rspec ./spec

Co-habitation of rspec-1 and rspec-2

Early beta versions of RSpec-2 included a spec command, which conflicted with
the RSpec-1 spec command because RSpec-1's was installed by the rspec gem,
while RSpec-2's is installed by the rspec-core gem.

If you installed one of these early versions, the safest bet is to uninstall
rspec-1 and rspec-core-2, and then reinstall both. After you do this, you will
be able to run rspec-2 like this:

rspec ./spec

... and rspec-1 like this:

spec _1.3.1_ ./spec

Rubygems inspects the first argument to any gem executable to see if it's
formatted like a version number surrounded by underscores. If so, it uses that
version (e.g. 1.3.1). If not, it uses the most recent version (e.g.

rake task

A few things changed in the Rake task used to run specs:

  1. The file in which it is defined changed from spec/rake/spectask to

  2. The spec_opts accessor has been deprecated in favor of rspec_opts. Also,
    the rspec command no longer supports the --options command line option
    so the options must be embedded directly in the Rakefile, or stored in the
    .rspec files mentioned above.

  3. The spec_files accessor has been replaced by pattern.

    # rspec-1
    require 'spec/rake/spectask'
    Spec::Rake::SpecTask.new do |t|
      t.spec_opts = ['--options', "\"spec/spec.opts\""]
      t.spec_files = FileList['spec/**/*.rb']
    # rspec-2
    require 'rspec/core/rake_task'
    RSpec::Core::RakeTask.new do |t|
      t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
      t.pattern = 'spec/**/*_spec.rb'

RSpec is the new Spec

The root namespace (top level module) is now RSpec instead of Spec, and
the root directory under lib within all of the rspec gems is rspec instead of spec.


Typically in spec/spec_helper.rb, configuration is now done like this:

RSpec.configure do |c|
  # ....


Command line options can be persisted in a .rspec file in a project. You
can also store a .rspec file in your home directory (~/.rspec) with global
options. Precedence is:

command line

context is no longer a top-level method

We removed context from the main object because it was creating conflicts with
IRB and some users who had Context domain objects. describe is still there,
so if you want to use context at the top level, just alias it:

alias :context :describe

Of course, you can still use context to declare a nested group:

describe "something" do
  context "in some context" do
    it "does something" do
      # ...

$KCODE no longer set implicitly to 'u'

In RSpec-1, the runner set $KCODE to 'u', which impacts, among other
things, the behaviour of Regular Expressions when applied to non-ascii
characters. This is no longer the case in RSpec-2.

Last published over 1 year ago by myronmarston.