rspec-expectations 2.7.0 → 2.8.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +117 -9
- data/lib/rspec/expectations.rb +24 -16
- data/lib/rspec/expectations/handler.rb +1 -1
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +91 -91
- data/lib/rspec/matchers/base_matcher.rb +41 -0
- data/lib/rspec/matchers/be.rb +31 -12
- data/lib/rspec/matchers/be_instance_of.rb +10 -12
- data/lib/rspec/matchers/be_kind_of.rb +10 -12
- data/lib/rspec/matchers/be_within.rb +36 -26
- data/lib/rspec/matchers/block_aliases.rb +2 -1
- data/lib/rspec/matchers/change.rb +1 -1
- data/lib/rspec/matchers/cover.rb +20 -19
- data/lib/rspec/matchers/eq.rb +22 -32
- data/lib/rspec/matchers/eql.rb +22 -28
- data/lib/rspec/matchers/equal.rb +37 -27
- data/lib/rspec/matchers/exist.rb +26 -18
- data/lib/rspec/matchers/have.rb +22 -28
- data/lib/rspec/matchers/include.rb +45 -37
- data/lib/rspec/matchers/match.rb +10 -10
- data/lib/rspec/matchers/match_array.rb +1 -7
- data/lib/rspec/matchers/matcher.rb +0 -8
- data/lib/rspec/matchers/operator_matcher.rb +0 -2
- data/lib/rspec/matchers/pretty.rb +25 -2
- data/lib/rspec/matchers/raise_error.rb +2 -16
- data/lib/rspec/matchers/respond_to.rb +1 -6
- data/lib/rspec/matchers/satisfy.rb +1 -6
- data/lib/rspec/matchers/throw_symbol.rb +2 -11
- data/spec/rspec/expectations/handler_spec.rb +1 -1
- data/spec/rspec/matchers/change_spec.rb +1 -1
- data/spec/rspec/matchers/description_generation_spec.rb +2 -2
- data/spec/rspec/matchers/eq_spec.rb +1 -1
- data/spec/rspec/matchers/eql_spec.rb +2 -2
- data/spec/rspec/matchers/equal_spec.rb +1 -1
- data/spec/rspec/matchers/include_spec.rb +4 -0
- data/spec/rspec/matchers/raise_error_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -0
- metadata +15 -10
data/README.md
CHANGED
@@ -1,21 +1,129 @@
|
|
1
1
|
# RSpec Expectations
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
[RSpec::Expectations](../RSpec/Expectations) lets you express expected outcomes
|
4
|
+
on an object in an example.
|
5
|
+
|
6
|
+
account.balance.should eq(Money.new(37.42, :USD))
|
5
7
|
|
6
8
|
## Install
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
+
If you want to use rspec-expectations with rspec, just install the rspec gem
|
11
|
+
and RubyGems will also install rspec-expectations for you (along with
|
12
|
+
rspec-core and rspec-mocks):
|
13
|
+
|
14
|
+
gem install rspec
|
15
|
+
|
16
|
+
If you want to use rspec-expectations with another tool, like Test::Unit,
|
17
|
+
Minitest, or Cucumber, you can install it directly:
|
18
|
+
|
19
|
+
gem install rspec-expectations
|
20
|
+
|
21
|
+
## Basic usage
|
22
|
+
|
23
|
+
Here's an example using rspec-core:
|
24
|
+
|
25
|
+
describe Order do
|
26
|
+
it "sums the prices of the items in its line items" do
|
27
|
+
order = Order.new
|
28
|
+
order.add_entry(LineItem.new(:item => Item.new(
|
29
|
+
:price => Money.new(1.11, :USD)
|
30
|
+
)
|
31
|
+
order.add_entry(LineItem.new(:item => Item.new(
|
32
|
+
:price => Money.new(2.22, :USD),
|
33
|
+
:quantity => 2
|
34
|
+
)
|
35
|
+
order.total.should eq(Money.new(5.55, :USD))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
The `describe` and `it` methods come from rspec-core. The `Order`, `LineItem`,
|
40
|
+
and `Item` classes would be from _your_ code. The last line of the example
|
41
|
+
expresses an expected outcome. If `order.total == Money.new(5.55, :USD)`, then
|
42
|
+
the example passes. If not, it fails with a message like:
|
43
|
+
|
44
|
+
expected: #<Money @value=5.55 @currency=:USD>
|
45
|
+
got: #<Money @value=1.11 @currency=:USD>
|
46
|
+
|
47
|
+
## Built-in matchers
|
48
|
+
|
49
|
+
### Equivalence
|
50
|
+
|
51
|
+
actual.should eq(expected) # passes if actual == expected
|
52
|
+
actual.should == expected # passes if actual == expected
|
53
|
+
actual.should eql(expected) # passes if actual.eql?(expected)
|
54
|
+
|
55
|
+
### Identity
|
56
|
+
|
57
|
+
actual.should be(expected) # passes if actual.equal?(expected)
|
58
|
+
actual.should equal(expected) # passes if actual.equal?(expected)
|
59
|
+
|
60
|
+
### Comparisons
|
61
|
+
|
62
|
+
actual.should be > expected
|
63
|
+
actual.should be >= expected
|
64
|
+
actual.should be <= expected
|
65
|
+
actual.should be < expected
|
66
|
+
actual.should be_within(delta).of(expected)
|
67
|
+
|
68
|
+
### Regular expressions
|
69
|
+
|
70
|
+
actual.should =~ /expression/
|
71
|
+
actual.should match(/expression/)
|
72
|
+
|
73
|
+
### Types/classes
|
74
|
+
|
75
|
+
actual.should be_an_instance_of(expected)
|
76
|
+
actual.should be_a_kind_of(expected)
|
77
|
+
|
78
|
+
### Truthiness
|
79
|
+
|
80
|
+
actual.should be_true # passes if actual is truthy (not nil or false)
|
81
|
+
actual.should be_false # passes if actual is falsy (nil or false)
|
82
|
+
actual.should be_nil # passes if actual is nil
|
83
|
+
|
84
|
+
### Expecting errors
|
85
|
+
|
86
|
+
expect { ... }.to raise_error
|
87
|
+
expect { ... }.to raise_error(ErrorClass)
|
88
|
+
expect { ... }.to raise_error("message")
|
89
|
+
expect { ... }.to raise_error(ErrorClass, "message")
|
90
|
+
|
91
|
+
### Expecting throws
|
92
|
+
|
93
|
+
expect { ... }.to throw_symbol
|
94
|
+
expect { ... }.to throw_symbol(:symbol)
|
95
|
+
expect { ... }.to throw_symbol(:symbol, 'value')
|
96
|
+
|
97
|
+
### Predicate matchers
|
98
|
+
|
99
|
+
actual.should be_xxx # passes if actual.xxx?
|
100
|
+
actual.should have_xxx(:arg) # passes if actual.has_xxx?(:arg)
|
101
|
+
|
102
|
+
See [RSpec::Matchers](../RSpec/Matchers) for more about predicate matchers.
|
103
|
+
|
104
|
+
### Ranges (Ruby >= 1.9 only)
|
105
|
+
|
106
|
+
(1..10).should cover(3)
|
107
|
+
|
108
|
+
### Collection membership
|
109
|
+
|
110
|
+
actual.should include(expected)
|
111
|
+
|
112
|
+
#### Examples
|
10
113
|
|
11
|
-
|
114
|
+
[1,2,3].should include(1)
|
115
|
+
[1,2,3].should include(1, 2)
|
116
|
+
{:a => 'b'}.should include(:a => 'b')
|
117
|
+
"this string".should include("is str")
|
12
118
|
|
13
|
-
|
119
|
+
## Learn more
|
14
120
|
|
15
|
-
|
121
|
+
See [RSpec::Expectations](../RSpec/Expectations) for more information about
|
122
|
+
`should` and `should_not` and how they work.
|
16
123
|
|
17
|
-
|
18
|
-
|
124
|
+
See [RSpec::Matchers](../RSpec/Matchers) for more information about the
|
125
|
+
built-in matchers that ship with rspec-expectations, and how to write your own
|
126
|
+
custom matchers.
|
19
127
|
|
20
128
|
## Also see
|
21
129
|
|
data/lib/rspec/expectations.rb
CHANGED
@@ -8,30 +8,38 @@ require 'rspec/expectations/version'
|
|
8
8
|
require 'rspec/expectations/differ'
|
9
9
|
|
10
10
|
module RSpec
|
11
|
-
# RSpec::Expectations
|
11
|
+
# RSpec::Expectations adds two instance methods to every object:
|
12
12
|
#
|
13
|
-
#
|
14
|
-
#
|
13
|
+
# should(matcher=nil)
|
14
|
+
# should_not(matcher=nil)
|
15
15
|
#
|
16
|
-
#
|
16
|
+
# Both methods take an optional matcher object (See
|
17
|
+
# [RSpec::Matchers](../RSpec/Matchers)). When `should` is invoked with a
|
18
|
+
# matcher, it turns around and calls `matcher.matches?(self)`. For example,
|
19
|
+
# in the expression:
|
17
20
|
#
|
18
|
-
#
|
21
|
+
# order.total.should eq(Money.new(5.55, :USD))
|
19
22
|
#
|
20
|
-
#
|
21
|
-
#
|
23
|
+
# the `should` method invokes the equivalent of `eq.matches?(order.total)`. If
|
24
|
+
# `matches?` returns true, the expectation is met and execution continues. If
|
25
|
+
# `false`, then the spec fails with the message returned by
|
26
|
+
# `eq.failure_message_for_should`.
|
22
27
|
#
|
23
|
-
#
|
28
|
+
# Given the expression:
|
24
29
|
#
|
25
|
-
#
|
26
|
-
# it returns +true+, the spec passes and execution continues. If it returns
|
27
|
-
# +false+, then the spec fails with the message returned by <tt>matcher.failure_message</tt>.
|
30
|
+
# order.entries.should_not include(entry)
|
28
31
|
#
|
29
|
-
#
|
30
|
-
# it
|
31
|
-
#
|
32
|
+
# the `should_not` method invokes the equivalent of
|
33
|
+
# `include.matches?(order.entries)`, but it interprets `false` as success, and
|
34
|
+
# `true` as a failure, using the message generated by
|
35
|
+
# `eq.failure_message_for_should_not`.
|
32
36
|
#
|
33
|
-
#
|
34
|
-
# matchers is quite simple.
|
37
|
+
# rspec-expectations ships with a standard set of useful matchers, and writing
|
38
|
+
# your own matchers is quite simple.
|
39
|
+
#
|
40
|
+
# See [RSpec::Matchers](../RSpec/Matchers) for more information about the
|
41
|
+
# built-in matchers that ship with rspec-expectations, and how to write your
|
42
|
+
# own custom matchers.
|
35
43
|
module Expectations
|
36
44
|
end
|
37
45
|
end
|
@@ -16,7 +16,7 @@ module RSpec
|
|
16
16
|
matcher.failure_message
|
17
17
|
|
18
18
|
if matcher.respond_to?(:diffable?) && matcher.diffable?
|
19
|
-
::RSpec::Expectations.fail_with message, matcher.expected
|
19
|
+
::RSpec::Expectations.fail_with message, matcher.expected, matcher.actual
|
20
20
|
else
|
21
21
|
::RSpec::Expectations.fail_with message
|
22
22
|
end
|
data/lib/rspec/matchers.rb
CHANGED
@@ -1,102 +1,102 @@
|
|
1
1
|
module RSpec
|
2
|
-
#
|
3
|
-
# expectations. A
|
2
|
+
# RSpec::Matchers provides a number of useful matchers we use to compose
|
3
|
+
# expectations. A matcher is any object that responds to the following:
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# matches?(actual)
|
6
|
+
# failure_message_for_should
|
7
7
|
#
|
8
8
|
# These methods are also part of the matcher protocol, but are optional:
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
10
|
+
# does_not_match?(actual)
|
11
|
+
# failure_message_for_should_not
|
12
|
+
# description
|
13
13
|
#
|
14
|
-
#
|
14
|
+
# ## Predicates
|
15
15
|
#
|
16
|
-
# In addition to
|
17
|
-
#
|
18
|
-
#
|
16
|
+
# In addition to matchers that are defined explicitly, RSpec will create
|
17
|
+
# custom matchers on the fly for any arbitrary predicate, giving your specs a
|
18
|
+
# much more natural language feel.
|
19
19
|
#
|
20
20
|
# A Ruby predicate is a method that ends with a "?" and returns true or false.
|
21
|
-
# Common examples are
|
21
|
+
# Common examples are `empty?`, `nil?`, and `instance_of?`.
|
22
22
|
#
|
23
|
-
# All you need to do is write
|
23
|
+
# All you need to do is write `should be_` followed by the predicate without
|
24
24
|
# the question mark, and RSpec will figure it out from there. For example:
|
25
25
|
#
|
26
|
-
#
|
27
|
-
#
|
26
|
+
# [].should be_empty # => [].empty?() | passes
|
27
|
+
# [].should_not be_empty # => [].empty?() | fails
|
28
28
|
#
|
29
29
|
# In addtion to prefixing the predicate matchers with "be_", you can also use "be_a_"
|
30
30
|
# and "be_an_", making your specs read much more naturally:
|
31
31
|
#
|
32
|
-
#
|
32
|
+
# "a string".should be_an_instance_of(String) =>"a string".instance_of?(String) #passes
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
34
|
+
# 3.should be_a_kind_of(Fixnum) # => 3.kind_of?(Numeric) | passes
|
35
|
+
# 3.should be_a_kind_of(Numeric) # => 3.kind_of?(Numeric) | passes
|
36
|
+
# 3.should be_an_instance_of(Fixnum) # => 3.instance_of?(Fixnum) | passes
|
37
|
+
# 3.should_not be_instance_of(Numeric) # => 3.instance_of?(Numeric) | fails
|
38
38
|
#
|
39
|
-
# RSpec will also create custom matchers for predicates like
|
39
|
+
# RSpec will also create custom matchers for predicates like `has_key?`. To
|
40
40
|
# use this feature, just state that the object should have_key(:key) and RSpec will
|
41
41
|
# call has_key?(:key) on the target. For example:
|
42
42
|
#
|
43
|
-
#
|
44
|
-
#
|
43
|
+
# {:a => "A"}.should have_key(:a) # => {:a => "A"}.has_key?(:a) | passes
|
44
|
+
# {:a => "A"}.should have_key(:b) # => {:a => "A"}.has_key?(:b) | fails
|
45
45
|
#
|
46
46
|
# You can use this feature to invoke any predicate that begins with "has_", whether it is
|
47
|
-
# part of the Ruby libraries (like
|
47
|
+
# part of the Ruby libraries (like `Hash#has_key?`) or a method you wrote on your own class.
|
48
48
|
#
|
49
|
-
#
|
49
|
+
# ## Custom Matchers
|
50
50
|
#
|
51
|
-
# When you find that none of the stock
|
52
|
-
#
|
53
|
-
#
|
51
|
+
# When you find that none of the stock matchers provide a natural feeling
|
52
|
+
# expectation, you can very easily write your own using RSpec's matcher DSL
|
53
|
+
# or writing one from scratch.
|
54
54
|
#
|
55
|
-
#
|
55
|
+
# ### Matcher DSL
|
56
56
|
#
|
57
57
|
# Imagine that you are writing a game in which players can be in various
|
58
58
|
# zones on a virtual board. To specify that bob should be in zone 4, you
|
59
59
|
# could say:
|
60
60
|
#
|
61
|
-
#
|
61
|
+
# bob.current_zone.should eql(Zone.new("4"))
|
62
62
|
#
|
63
63
|
# But you might find it more expressive to say:
|
64
64
|
#
|
65
|
-
#
|
65
|
+
# bob.should be_in_zone("4")
|
66
66
|
#
|
67
67
|
# and/or
|
68
68
|
#
|
69
|
-
#
|
69
|
+
# bob.should_not be_in_zone("3")
|
70
70
|
#
|
71
71
|
# You can create such a matcher like so:
|
72
72
|
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
73
|
+
# RSpec::Matchers.define :be_in_zone do |zone|
|
74
|
+
# match do |player|
|
75
|
+
# player.in_zone?(zone)
|
76
|
+
# end
|
77
|
+
# end
|
78
78
|
#
|
79
79
|
# This will generate a <tt>be_in_zone</tt> method that returns a matcher
|
80
80
|
# with logical default messages for failures. You can override the failure
|
81
81
|
# messages and the generated description as follows:
|
82
82
|
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
83
|
+
# RSpec::Matchers.define :be_in_zone do |zone|
|
84
|
+
# match do |player|
|
85
|
+
# player.in_zone?(zone)
|
86
|
+
# end
|
87
87
|
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
88
|
+
# failure_message_for_should do |player|
|
89
|
+
# # generate and return the appropriate string.
|
90
|
+
# end
|
91
91
|
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
92
|
+
# failure_message_for_should_not do |player|
|
93
|
+
# # generate and return the appropriate string.
|
94
|
+
# end
|
95
95
|
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
96
|
+
# description do
|
97
|
+
# # generate and return the appropriate string.
|
98
|
+
# end
|
99
|
+
# end
|
100
100
|
#
|
101
101
|
# Each of the message-generation methods has access to the block arguments
|
102
102
|
# passed to the <tt>create</tt> method (in this case, <tt>zone</tt>). The
|
@@ -104,67 +104,66 @@ module RSpec
|
|
104
104
|
# <tt>failure_message_for_should_not</tt>) are passed the actual value (the
|
105
105
|
# receiver of <tt>should</tt> or <tt>should_not</tt>).
|
106
106
|
#
|
107
|
-
#
|
107
|
+
# ### Custom Matcher from scratch
|
108
108
|
#
|
109
109
|
# You could also write a custom matcher from scratch, as follows:
|
110
110
|
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
111
|
+
# class BeInZone
|
112
|
+
# def initialize(expected)
|
113
|
+
# @expected = expected
|
114
|
+
# end
|
115
115
|
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
116
|
+
# def matches?(target)
|
117
|
+
# @target = target
|
118
|
+
# @target.current_zone.eql?(Zone.new(@expected))
|
119
|
+
# end
|
120
120
|
#
|
121
|
-
#
|
122
|
-
#
|
123
|
-
#
|
121
|
+
# def failure_message_for_should
|
122
|
+
# "expected #{@target.inspect} to be in Zone #{@expected}"
|
123
|
+
# end
|
124
124
|
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
125
|
+
# def failure_message_for_should_not
|
126
|
+
# "expected #{@target.inspect} not to be in Zone #{@expected}"
|
127
|
+
# end
|
128
|
+
# end
|
129
129
|
#
|
130
130
|
# ... and a method like this:
|
131
131
|
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
132
|
+
# def be_in_zone(expected)
|
133
|
+
# BeInZone.new(expected)
|
134
|
+
# end
|
135
135
|
#
|
136
136
|
# And then expose the method to your specs. This is normally done
|
137
137
|
# by including the method and the class in a module, which is then
|
138
138
|
# included in your spec:
|
139
139
|
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
140
|
+
# module CustomGameMatchers
|
141
|
+
# class BeInZone
|
142
|
+
# # ...
|
143
|
+
# end
|
144
144
|
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
145
|
+
# def be_in_zone(expected)
|
146
|
+
# # ...
|
147
|
+
# end
|
148
|
+
# end
|
149
149
|
#
|
150
|
-
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
150
|
+
# describe "Player behaviour" do
|
151
|
+
# include CustomGameMatchers
|
152
|
+
# # ...
|
153
|
+
# end
|
154
154
|
#
|
155
155
|
# or you can include in globally in a spec_helper.rb file <tt>require</tt>d
|
156
156
|
# from your spec file(s):
|
157
157
|
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
158
|
+
# RSpec::configure do |config|
|
159
|
+
# config.include(CustomGameMatchers)
|
160
|
+
# end
|
161
161
|
module Matchers
|
162
|
-
# Include Matchers for other test frameworks.
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
# https://gist.github.com/845896
|
162
|
+
# Include Matchers for other test frameworks. Note that MiniTest _must_
|
163
|
+
# come before TU because on ruby 1.9, T::U::TC is a subclass of MT::U::TC
|
164
|
+
# and a 1.9 bug can lead to infinite recursion from the `super` call in our
|
165
|
+
# method_missing hook. See this gist for more info:
|
166
|
+
# https://gist.github.com/845896
|
168
167
|
if defined?(MiniTest::Unit::TestCase)
|
169
168
|
MiniTest::Unit::TestCase.send(:include, self)
|
170
169
|
end
|
@@ -176,6 +175,7 @@ end
|
|
176
175
|
|
177
176
|
require 'rspec/matchers/extensions/instance_eval_with_args'
|
178
177
|
require 'rspec/matchers/pretty'
|
178
|
+
require 'rspec/matchers/base_matcher'
|
179
179
|
require 'rspec/matchers/matcher'
|
180
180
|
require 'rspec/matchers/operator_matcher'
|
181
181
|
require 'rspec/matchers/be'
|