RSpec::Expectations¶ ↑
This is the detailed readme for rspec-expectations, see also:
Basic usage¶ ↑
Here’s an example using rspec-core:
RSpec.describe Order do it "sums the prices of the items in its line items" do order = Order.new order.add_entry(LineItem.new(:item => Item.new( :price => Money.new(1.11, :USD) ))) order.add_entry(LineItem.new(:item => Item.new( :price => Money.new(2.22, :USD), :quantity => 2 ))) expect(order.total).to eq(Money.new(5.55, :USD)) end end
The describe and it methods come from rspec-core. The Order, LineItem, Item and Money classes would be from your code. The last line of the example expresses an expected outcome. If order.total == Money.new(5.55, :USD), then the example passes. If not, it fails with a message like:
expected: #<Money @value=5.55 @currency=:USD>
got: #<Money @value=1.11 @currency=:USD>
Built-in matchers¶ ↑
Equivalence¶ ↑
expect(actual).to eq(expected) # passes if actual == expected expect(actual).to eql(expected) # passes if actual.eql?(expected) expect(actual).not_to eql(not_expected) # passes if not(actual.eql?(expected))
Note: The new expect syntax no longer supports the == matcher.
Identity¶ ↑
expect(actual).to be(expected) # passes if actual.equal?(expected) expect(actual).to equal(expected) # passes if actual.equal?(expected)
Comparisons¶ ↑
expect(actual).to be > expected expect(actual).to be >= expected expect(actual).to be <= expected expect(actual).to be < expected expect(actual).to be_within(delta).of(expected)
Regular expressions¶ ↑
expect(actual).to match(/expression/)
Note: The new expect syntax no longer supports the =~ matcher.
Types/classes¶ ↑
expect(actual).to be_an_instance_of(expected) # passes if actual.class == expected expect(actual).to be_a(expected) # passes if actual.kind_of?(expected) expect(actual).to be_an(expected) # an alias for be_a expect(actual).to be_a_kind_of(expected) # another alias
Truthiness¶ ↑
expect(actual).to be_truthy # passes if actual is truthy (not nil or false) expect(actual).to be true # passes if actual == true expect(actual).to be_falsy # passes if actual is falsy (nil or false) expect(actual).to be false # passes if actual == false expect(actual).to be_nil # passes if actual is nil expect(actual).to_not be_nil # passes if actual is not nil
Expecting errors¶ ↑
expect { ... }.to raise_error expect { ... }.to raise_error(ErrorClass) expect { ... }.to raise_error("message") expect { ... }.to raise_error(ErrorClass, "message")
Expecting throws¶ ↑
expect { ... }.to throw_symbol expect { ... }.to throw_symbol(:symbol) expect { ... }.to throw_symbol(:symbol, 'value')
Yielding¶ ↑
expect { |b| 5.tap(&b) }.to yield_control # passes regardless of yielded args expect { |b| yield_if_true(true, &b) }.to yield_with_no_args # passes only if no args are yielded expect { |b| 5.tap(&b) }.to yield_with_args(5) expect { |b| 5.tap(&b) }.to yield_with_args(Integer) expect { |b| "a string".tap(&b) }.to yield_with_args(/str/) expect { |b| [1, 2, 3].each(&b) }.to yield_successive_args(1, 2, 3) expect { |b| { :a => 1, :b => 2 }.each(&b) }.to yield_successive_args([:a, 1], [:b, 2])
Predicate matchers¶ ↑
expect(actual).to be_xxx # passes if actual.xxx? expect(actual).to have_xxx(:arg) # passes if actual.has_xxx?(:arg)
Ranges¶ ↑
expect(1..10).to cover(3)
Collection membership¶ ↑
# exact order, entire collection expect(actual).to eq(expected) # exact order, partial collection (based on an exact position) expect(actual).to start_with(expected) expect(actual).to end_with(expected) # any order, entire collection expect(actual).to match_array(expected) # You can also express this by passing the expected elements # as individual arguments expect(actual).to contain_exactly(expected_element1, expected_element2) # any order, partial collection expect(actual).to include(expected)
Examples¶ ↑
expect([1, 2, 3]).to eq([1, 2, 3]) # Order dependent equality check expect([1, 2, 3]).to include(1) # Exact ordering, partial collection matches expect([1, 2, 3]).to include(2, 3) # expect([1, 2, 3]).to start_with(1) # As above, but from the start of the collection expect([1, 2, 3]).to start_with(1, 2) # expect([1, 2, 3]).to end_with(3) # As above but from the end of the collection expect([1, 2, 3]).to end_with(2, 3) # expect({:a => 'b'}).to include(:a => 'b') # Matching within hashes expect("this string").to include("is str") # Matching within strings expect("this string").to start_with("this") # expect("this string").to end_with("ring") # expect([1, 2, 3]).to contain_exactly(2, 3, 1) # Order independent matches expect([1, 2, 3]).to match_array([3, 2, 1]) # # Order dependent compound matchers expect( [{:a => 'hash'},{:a => 'another'}] ).to match([a_hash_including(:a => 'hash'), a_hash_including(:a => 'another')])
Compound Matcher Expressions¶ ↑
You can also create compound matcher expressions using and or or:
expect(alphabet).to start_with("a").and end_with("z") expect(stoplight.color).to eq("red").or eq("green").or eq("yellow")
Composing Matchers¶ ↑
Many of the built-in matchers are designed to take matchers as arguments, to allow you to flexibly specify only the essential aspects of an object or data structure. In addition, all of the built-in matchers have one or more aliases that provide better phrasing for when they are used as arguments to another matcher.
Examples¶ ↑
expect { k += 1.05 }.to change { k }.by( a_value_within(0.1).of(1.0) ) expect { s = "barn" }.to change { s } .from( a_string_matching(/foo/) ) .to( a_string_matching(/bar/) ) expect(["barn", 2.45]).to contain_exactly( a_value_within(0.1).of(2.5), a_string_starting_with("bar") ) expect(["barn", "food", 2.45]).to end_with( a_string_matching("foo"), a_value > 2 ) expect(["barn", 2.45]).to include( a_string_starting_with("bar") ) expect(:a => "food", :b => "good").to include(:a => a_string_matching(/foo/)) hash = { :a => { :b => ["foo", 5], :c => { :d => 2.05 } } } expect(hash).to match( :a => { :b => a_collection_containing_exactly( a_string_starting_with("f"), an_instance_of(Integer) ), :c => { :d => (a_value < 3) } } ) expect { |probe| [1, 2, 3].each(&probe) }.to yield_successive_args( a_value < 2, 2, a_value > 2 )
Usage outside rspec-core¶ ↑
You always need to load rspec/expectations even if you only want to use one part of the library:
require 'rspec/expectations'
Then simply include RSpec::Matchers in any class:
class MyClass include RSpec::Matchers def do_something(arg) expect(arg).to be > 0 # do other stuff end end