These methods now align with Ruby’s conditional semantics:
-
be_false
passes forfalse
andnil
-
be_true
passes for everything else
This is a change from the previous behaviour (which wasn’t working correctly anyway), which was supposed to treat be_true
as equal(true)
, and be_false
as equal(false)
.
If the actual values true
and false
are meaningful to your examples, you’ll want to change the to use equal(true)
and equal(false)
(or ==(true)
and ==(false)
).
We changed the raise_error
matcher to raise_exception
, and aliased it with raise_error
. This maintains backward compatibility, and also gives you the option of being more precise in specs about what is expected.
This allows you to wrap other expectations in the match
method. Consider this matcher:
Spec::Matchers.define :teach do |subject| match do |teacher| teacher.subjects.should include(subject) end end
The block passed to match
is called internally by Rspec, and is expected to return a boolean value. In this case, if should include(subject)
fails, it raises an ExpectationNotMetError
.
Beginning with rspec-1.3.0, when the match block raises an ExpectationNotMetError
, it is captured and the block returns false
. Otherwise it returns true
, so it works like any other matcher.
The new match_unless_raises
method allows you to wrap Test::Unit
assertions by capturing AssertionFailedError
and returning false, just as the match
method now does with ExpectationNotMetError
.
Spec::Matchers.define :teach do |subject| match_unless_raises Test::Unit::AssertionFailedError do |teacher| assert teacher.subjects.include?(subject) end end
If you have a spec/spec.opts file, the spec command will now use that automatically as long as you don’t include any options on the command line.
Writing specs tends to follow a regular pattern of using local variables, discovering duplication, and then having to convert to local variables to instance variables by adding an “@” symbol. The let() method assigns the result of a lazy eval’d block as the return value of an instance method using the same name. This way you can go from this:
describe Subscription do it "does something" do subscription = Subscription.create :limit => 1 subscription... end it "does something else" do subscription = Subscription.create :limit => 1 subscription... end end
to this:
describe Subscription do let(:subscription) { Subscription.create :limit => 1 } it "does something" do subscription... end it "does something else" do subscription... end end
If you’re in the habit of writing one-liners using implicit subject, this new its() feature is for you. Here’s the basic idea:
describe Array do its(:length) { should == 0 } end
Use Spec::Matchers.define instead of Spec::Matchers.create (which is now deprecated).
With the addition of the new Matcher DSL the old, confusing, and almost-nobody-uses-it explicit predicate matcher functionality’s days are now numbered.
If you’re not familiar with this feature, don’t worry about it. If you have anything that looks like this:
predicate_matchers[:swim] = :can_swim?
Or this
config.predicate_matchers[:swim] = :can_swim?
Change it to this:
Spec::Matchers.define :swim do match do |potential_swimmer| potential_swimmer.can_swim? end end
If you have an custom formatter, the add_example_group
method has been changed to example_group_started
, and kept as an alias so your formatters will still work. Though not yet, add_example_group
will be deprecated in a future minor release, and removed in a future major release, so we recommend you make this change now.
After minor public outcry and confusion, we restored necessary references to rubygems in rspec. If you use a different mechanism for managing gems, just set a NO_RUBYGEMS
environment variable (to any non-nil value).
This is probably only interesting to you if you use custom formatters.
Formatters now receive Spec::Example::ExampleGroupProxy and Spec::Example::ExampleGroup objects with cohesive APIs for reporting. See the RDoc for those classes and Spec::Runner::Formatter::BaseFormatter for more information.
We’ll be separating this out to its own gem for rspec 2.0, but for now, just install rspec >= 1.2.1 and add the following to your test_helper
file:
require 'spec/expectations' class Test::Unit::TestCase include Spec::Matchers end
This will add should()
and should_not()
to your objects, make all of rspec’s built-in matchers available to your tests, INCLUDING rspec’s DSL for creating matchers (see below, under Upgrade to rspec-1.2.0)
If you have ruby-debug installed, you can set a breakpoint by adding debugger()
in your code:
# some code ..... debugger # some more code ....
… and using the --debugger
or -u
command line option.
spec path/to/file.rb --debugger
-
If you use the ruby command to run specs instead of the spec command, you’ll need to require ‘spec/autorun’ or they won’t run. This won’t affect you if you use the spec command or the Spec::Rake::SpecTask that ships with RSpec.
-
require ‘spec/test/unit’ to invoke test/unit interop if you’re using RSpec’s core (this is handled implicitly with spec-rails)
-
setup and teardown are gone - use before and after instead
-
you can still use setup and teardown if you’re using Test::Unit::TestCase as the base ExampleGroup class (which is implicit in rspec-rails)
-
-
The matcher protocol has been improved. The old protocol is still supported, but we added support for two new methods that speak a bit more clearly:
failure_message => failure_message_for_should negative_failure_message => failure_message_for_should_not
-
All references to rubygems have been removed from within rspec’s code.
-
See gist.github.com/54177 for rationale and suggestions on alternative approaches to loading rubygems
-
RSpec now works with Ruby 1.9.1. See wiki.github.com/dchelimsky/rspec/ruby-191 for useful information.
RSpec works with heckle again! Gotta use heckle >= 1.4.2 for this to work though, and it only works with ruby-1.8.6 and 1.8.7 (heckle doesn’t support 1.9.1 yet).
[sudo] gem install heckle --version ">=1.4.2" spec spec/game/mastermind.rb --heckle Game::Mastermind
We’ve added a new DSL for generating custom matchers very simply and cleanly. We’ll still support the simple_matcher method, so never fear if you’re using that, but we recommend that you start developing your new matchers with this new syntax.
Spec::Matchers.create :be_a_multiple_of do |smaller| match do |bigger| bigger % smaller == 0 end end 9.should be_a_multiple_of(3)
See features/matchers/define_matcher.feature
for more examples