rspec-expectations 2.10.0 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.md +24 -1
- data/README.md +36 -2
- data/features/built_in_matchers/be.feature +52 -14
- data/features/syntax_configuration.feature +68 -0
- data/lib/rspec/expectations.rb +2 -0
- data/lib/rspec/expectations/expectation_target.rb +52 -0
- data/lib/rspec/expectations/extensions.rb +0 -1
- data/lib/rspec/expectations/syntax.rb +105 -0
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +12 -5
- data/lib/rspec/matchers/built_in/base_matcher.rb +16 -7
- data/lib/rspec/matchers/built_in/be.rb +27 -25
- data/lib/rspec/matchers/built_in/be_instance_of.rb +3 -5
- data/lib/rspec/matchers/built_in/be_kind_of.rb +3 -5
- data/lib/rspec/matchers/built_in/be_within.rb +17 -11
- data/lib/rspec/matchers/built_in/cover.rb +5 -6
- data/lib/rspec/matchers/built_in/eq.rb +4 -8
- data/lib/rspec/matchers/built_in/eql.rb +3 -5
- data/lib/rspec/matchers/built_in/equal.rb +6 -10
- data/lib/rspec/matchers/built_in/exist.rb +11 -13
- data/lib/rspec/matchers/built_in/include.rb +5 -6
- data/lib/rspec/matchers/built_in/match.rb +3 -4
- data/lib/rspec/matchers/built_in/match_array.rb +7 -14
- data/lib/rspec/matchers/built_in/start_and_end_with.rb +1 -3
- data/lib/rspec/matchers/built_in/yield.rb +2 -5
- data/lib/rspec/matchers/configuration.rb +66 -0
- data/spec/rspec/expectations/expectation_target_spec.rb +65 -0
- data/spec/rspec/expectations/extensions/kernel_spec.rb +22 -0
- data/spec/rspec/matchers/base_matcher_spec.rb +8 -6
- data/spec/rspec/matchers/be_spec.rb +2 -2
- data/spec/rspec/matchers/be_within_spec.rb +9 -1
- data/spec/rspec/matchers/configuration_spec.rb +160 -0
- data/spec/rspec/matchers/eq_spec.rb +16 -4
- data/spec/rspec/matchers/equal_spec.rb +7 -7
- data/spec/rspec/matchers/match_array_spec.rb +12 -0
- data/spec/rspec/matchers/yield_spec.rb +3 -3
- data/spec/support/in_sub_process.rb +31 -0
- metadata +16 -9
- data/lib/rspec/expectations/extensions/kernel.rb +0 -26
- data/lib/rspec/matchers/block_aliases.rb +0 -21
- data/spec/rspec/matchers/compatibility_spec.rb +0 -28
@@ -64,9 +64,7 @@ module RSpec
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
-
class YieldControl
|
68
|
-
include BaseMatcher
|
69
|
-
|
67
|
+
class YieldControl < BaseMatcher
|
70
68
|
def matches?(block)
|
71
69
|
probe = YieldProbe.probe(block)
|
72
70
|
probe.yielded_once?(:yield_control)
|
@@ -81,8 +79,7 @@ module RSpec
|
|
81
79
|
end
|
82
80
|
end
|
83
81
|
|
84
|
-
class YieldWithNoArgs
|
85
|
-
include BaseMatcher
|
82
|
+
class YieldWithNoArgs < BaseMatcher
|
86
83
|
|
87
84
|
def matches?(block)
|
88
85
|
@probe = YieldProbe.probe(block)
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'rspec/expectations/syntax'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Matchers
|
5
|
+
# Provides configuration options for rspec-expectations.
|
6
|
+
class Configuration
|
7
|
+
# Configures the supported syntax.
|
8
|
+
# @param [Array<Symbol>, Symbol] values the syntaxes to enable
|
9
|
+
# @example
|
10
|
+
# RSpec.configure do |rspec|
|
11
|
+
# rspec.expect_with :rspec do |c|
|
12
|
+
# c.syntax = :should
|
13
|
+
# # or
|
14
|
+
# c.syntax = :expect
|
15
|
+
# # or
|
16
|
+
# c.syntax = [:should, :expect]
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
def syntax=(values)
|
20
|
+
if Array(values).include?(:expect)
|
21
|
+
Expectations::Syntax.enable_expect
|
22
|
+
else
|
23
|
+
Expectations::Syntax.disable_expect
|
24
|
+
end
|
25
|
+
|
26
|
+
if Array(values).include?(:should)
|
27
|
+
Expectations::Syntax.enable_should
|
28
|
+
else
|
29
|
+
Expectations::Syntax.disable_should
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# The list of configured syntaxes.
|
34
|
+
# @return [Array<Symbol>] the list of configured syntaxes.
|
35
|
+
def syntax
|
36
|
+
syntaxes = []
|
37
|
+
syntaxes << :should if Expectations::Syntax.should_enabled?
|
38
|
+
syntaxes << :expect if Expectations::Syntax.expect_enabled?
|
39
|
+
syntaxes
|
40
|
+
end
|
41
|
+
|
42
|
+
# Adds `should` and `should_not` to the given classes
|
43
|
+
# or modules. This can be used to ensure `should` works
|
44
|
+
# properly on things like proxy objects (particular
|
45
|
+
# `Delegator`-subclassed objects on 1.8).
|
46
|
+
#
|
47
|
+
# @param [Array<Module>] modules the list of classes or modules
|
48
|
+
# to add `should` and `should_not` to.
|
49
|
+
def add_should_and_should_not_to(*modules)
|
50
|
+
modules.each do |mod|
|
51
|
+
Expectations::Syntax.enable_should(mod)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# The configuration object
|
57
|
+
# @return [RSpec::Matchers::Configuration] the configuration object
|
58
|
+
def self.configuration
|
59
|
+
@configuration ||= Configuration.new
|
60
|
+
end
|
61
|
+
|
62
|
+
# set default syntax
|
63
|
+
configuration.syntax = [:expect, :should]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Expectations
|
5
|
+
# so our examples below can set expectations about the target
|
6
|
+
ExpectationTarget.send(:attr_reader, :target)
|
7
|
+
|
8
|
+
describe ExpectationTarget do
|
9
|
+
context 'when constructed via #expect' do
|
10
|
+
it 'constructs a new instance targetting the given argument' do
|
11
|
+
expect(7).target.should eq(7)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'constructs a new instance targetting the given block' do
|
15
|
+
block = lambda {}
|
16
|
+
expect(&block).target.should be(block)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'raises an ArgumentError when given an argument and a block' do
|
20
|
+
lambda { expect(7) { } }.should raise_error(ArgumentError)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'raises an ArgumentError when given neither an argument nor a block' do
|
24
|
+
lambda { expect }.should raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'can be passed nil' do
|
28
|
+
expect(nil).target.should be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'passes a valid positive expectation' do
|
32
|
+
expect(5).to eq(5)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'passes a valid negative expectation' do
|
36
|
+
expect(5).to_not eq(4)
|
37
|
+
expect(5).not_to eq(4)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'fails an invalid positive expectation' do
|
41
|
+
lambda { expect(5).to eq(4) }.should fail_with(/expected: 4.*got: 5/m)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'fails an invalid negative expectation' do
|
45
|
+
message = /expected 5 not to be a kind of Fixnum/
|
46
|
+
lambda { expect(5).to_not be_a(Fixnum) }.should fail_with(message)
|
47
|
+
lambda { expect(5).not_to be_a(Fixnum) }.should fail_with(message)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'does not support operator matchers from #to' do
|
51
|
+
expect {
|
52
|
+
expect(3).to == 3
|
53
|
+
}.to raise_error(ArgumentError)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'does not support operator matchers from #not_to' do
|
57
|
+
expect {
|
58
|
+
expect(3).not_to == 4
|
59
|
+
}.to raise_error(ArgumentError)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -20,6 +20,28 @@ describe Object, "#should" do
|
|
20
20
|
@target.should @matcher
|
21
21
|
}.should fail_with("the failure message")
|
22
22
|
end
|
23
|
+
|
24
|
+
context "on interpretters that have BasicObject", :if => defined?(BasicObject) do
|
25
|
+
let(:proxy_class) do
|
26
|
+
Class.new(BasicObject) do
|
27
|
+
def initialize(target)
|
28
|
+
@target = target
|
29
|
+
end
|
30
|
+
|
31
|
+
def proxied?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(name, *args)
|
36
|
+
@target.send(name, *args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'works properly on BasicObject-subclassed proxy objects' do
|
42
|
+
proxy_class.new(Object.new).should be_proxied
|
43
|
+
end
|
44
|
+
end
|
23
45
|
end
|
24
46
|
|
25
47
|
describe Object, "#should_not" do
|
@@ -2,9 +2,7 @@ module RSpec::Matchers::BuiltIn
|
|
2
2
|
describe BaseMatcher do
|
3
3
|
describe "#match_unless_raises" do
|
4
4
|
let(:matcher) do
|
5
|
-
Class.new
|
6
|
-
include BaseMatcher
|
7
|
-
end.new
|
5
|
+
Class.new(BaseMatcher).new
|
8
6
|
end
|
9
7
|
|
10
8
|
it "returns true if there are no errors" do
|
@@ -41,12 +39,16 @@ module RSpec::Matchers::BuiltIn
|
|
41
39
|
|
42
40
|
describe "#==" do
|
43
41
|
it "responds the same way as matches?" do
|
44
|
-
matcher = Class.new do
|
45
|
-
|
42
|
+
matcher = Class.new(BaseMatcher) do
|
43
|
+
def initialize(expected)
|
44
|
+
@expected = expected
|
45
|
+
end
|
46
|
+
|
46
47
|
def matches?(actual)
|
47
|
-
actual == expected
|
48
|
+
(@actual = actual) == @expected
|
48
49
|
end
|
49
50
|
end
|
51
|
+
|
50
52
|
matcher.new(3).matches?(3).should be_true
|
51
53
|
matcher.new(3).should eq(3)
|
52
54
|
|
@@ -237,7 +237,7 @@ describe "should be_true" do
|
|
237
237
|
it "fails when actual equal?(false)" do
|
238
238
|
lambda {
|
239
239
|
false.should be_true
|
240
|
-
}.should fail_with("expected
|
240
|
+
}.should fail_with("expected: true value\n got: false")
|
241
241
|
end
|
242
242
|
end
|
243
243
|
|
@@ -253,7 +253,7 @@ describe "should be_false" do
|
|
253
253
|
it "fails when actual equal?(true)" do
|
254
254
|
lambda {
|
255
255
|
true.should be_false
|
256
|
-
}.should fail_with("expected
|
256
|
+
}.should fail_with("expected: false value\n got: true")
|
257
257
|
end
|
258
258
|
end
|
259
259
|
|
@@ -57,7 +57,15 @@ module RSpec
|
|
57
57
|
|
58
58
|
it "raises an error if no expected value is given" do
|
59
59
|
matcher = be_within(0.5)
|
60
|
-
expect { matcher.matches?(5.1) }.to raise_error(
|
60
|
+
expect { matcher.matches?(5.1) }.to raise_error(
|
61
|
+
ArgumentError, /must set an expected value using #of/
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "raises an error if the actual value is not of a Numeric type" do
|
66
|
+
expect { be_within(0.1).of(0).matches?(nil) }.to raise_error(
|
67
|
+
ArgumentError, /The actual value \(nil\) must be of a `Numeric` type/
|
68
|
+
)
|
61
69
|
end
|
62
70
|
end
|
63
71
|
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'delegate'
|
3
|
+
|
4
|
+
module RSpec
|
5
|
+
module Matchers
|
6
|
+
describe ".configuration" do
|
7
|
+
it 'returns a memoized configuration instance' do
|
8
|
+
RSpec::Matchers.configuration.should be_a(RSpec::Matchers::Configuration)
|
9
|
+
RSpec::Matchers.configuration.should be(RSpec::Matchers.configuration)
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'on an interpreter that does not provide BasicObject', :unless => defined?(::BasicObject) do
|
13
|
+
before { RSpec::Expectations::Syntax.disable_should(Delegator) }
|
14
|
+
|
15
|
+
let(:klass) do
|
16
|
+
Class.new(SimpleDelegator) do
|
17
|
+
def delegated?; true; end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:instance) { klass.new(Object.new) }
|
22
|
+
|
23
|
+
it 'provides a means to manually add it Delegator' do
|
24
|
+
instance.should_not respond_to(:delegated?) # because #should is being delegated...
|
25
|
+
RSpec::Matchers.configuration.add_should_and_should_not_to Delegator
|
26
|
+
instance.should respond_to(:delegated?) # now it should work!
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
shared_examples_for "configuring the expectation syntax" do
|
32
|
+
# We want a sandboxed method that ensures that we wind up with
|
33
|
+
# both syntaxes properly enabled when the example ends.
|
34
|
+
#
|
35
|
+
# On platforms that fork, using a sub process is the easiest,
|
36
|
+
# most robust way to achieve that.
|
37
|
+
#
|
38
|
+
# On jRuby we just re-enable both syntaxes at the end of the example;
|
39
|
+
# however, this is a generally inferior approach because it depends on
|
40
|
+
# the code-under-test working properly; if it doesn't work properly,
|
41
|
+
# it could leave things in a "broken" state where tons of other examples fail.
|
42
|
+
if RUBY_PLATFORM == "java"
|
43
|
+
def sandboxed
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
configure_syntax([:should, :expect])
|
47
|
+
end
|
48
|
+
else
|
49
|
+
include InSubProcess
|
50
|
+
alias sandboxed in_sub_process
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'is configured to :should and :expect by default' do
|
54
|
+
configured_syntax.should eq([:should, :expect])
|
55
|
+
|
56
|
+
3.should eq(3)
|
57
|
+
3.should_not eq(4)
|
58
|
+
expect(3).to eq(3)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'can limit the syntax to :should' do
|
62
|
+
sandboxed do
|
63
|
+
configure_syntax :should
|
64
|
+
configured_syntax.should eq([:should])
|
65
|
+
|
66
|
+
3.should eq(3)
|
67
|
+
3.should_not eq(4)
|
68
|
+
lambda { expect(6).to eq(6) }.should raise_error(NameError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'is a no-op when configured to :should twice' do
|
73
|
+
sandboxed do
|
74
|
+
::Kernel.stub(:method_added).and_raise("no methods should be added here")
|
75
|
+
|
76
|
+
configure_syntax :should
|
77
|
+
configure_syntax :should
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'can limit the syntax to :expect' do
|
82
|
+
sandboxed do
|
83
|
+
configure_syntax :expect
|
84
|
+
expect(configured_syntax).to eq([:expect])
|
85
|
+
|
86
|
+
expect(3).to eq(3)
|
87
|
+
expect { 3.should eq(3) }.to raise_error(NameError)
|
88
|
+
expect { 3.should_not eq(3) }.to raise_error(NameError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'is a no-op when configured to :expect twice' do
|
93
|
+
sandboxed do
|
94
|
+
RSpec::Matchers.stub(:method_added).and_raise("no methods should be added here")
|
95
|
+
|
96
|
+
configure_syntax :expect
|
97
|
+
configure_syntax :expect
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'can re-enable the :should syntax' do
|
102
|
+
sandboxed do
|
103
|
+
configure_syntax :expect
|
104
|
+
configure_syntax [:should, :expect]
|
105
|
+
configured_syntax.should eq([:should, :expect])
|
106
|
+
|
107
|
+
3.should eq(3)
|
108
|
+
3.should_not eq(4)
|
109
|
+
expect(3).to eq(3)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'can re-enable the :expect syntax' do
|
114
|
+
sandboxed do
|
115
|
+
configure_syntax :should
|
116
|
+
configure_syntax [:should, :expect]
|
117
|
+
configured_syntax.should eq([:should, :expect])
|
118
|
+
|
119
|
+
3.should eq(3)
|
120
|
+
3.should_not eq(4)
|
121
|
+
expect(3).to eq(3)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "configuring rspec-expectations directly" do
|
127
|
+
it_behaves_like "configuring the expectation syntax" do
|
128
|
+
def configure_syntax(syntax)
|
129
|
+
RSpec::Matchers.configuration.syntax = syntax
|
130
|
+
end
|
131
|
+
|
132
|
+
def configured_syntax
|
133
|
+
RSpec::Matchers.configuration.syntax
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "configuring using the rspec-core config API" do
|
139
|
+
it_behaves_like "configuring the expectation syntax" do
|
140
|
+
def configure_syntax(syntax)
|
141
|
+
RSpec.configure do |rspec|
|
142
|
+
rspec.expect_with :rspec do |c|
|
143
|
+
c.syntax = syntax
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def configured_syntax
|
149
|
+
RSpec.configure do |rspec|
|
150
|
+
rspec.expect_with :rspec do |c|
|
151
|
+
return c.syntax
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
@@ -14,23 +14,35 @@ module RSpec
|
|
14
14
|
it "does not match when actual != expected" do
|
15
15
|
1.should_not eq(2)
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
|
+
it "compares by sending == to actual (not expected)" do
|
19
|
+
called = false
|
20
|
+
actual = Class.new do
|
21
|
+
define_method :== do |other|
|
22
|
+
called = true
|
23
|
+
end
|
24
|
+
end.new
|
25
|
+
|
26
|
+
actual.should eq :anything # to trigger the matches? method
|
27
|
+
called.should be_true
|
28
|
+
end
|
29
|
+
|
18
30
|
it "describes itself" do
|
19
31
|
matcher = eq(1)
|
20
32
|
matcher.matches?(1)
|
21
|
-
matcher.description.should
|
33
|
+
matcher.description.should eq "eq 1"
|
22
34
|
end
|
23
35
|
|
24
36
|
it "provides message, expected and actual on #failure_message" do
|
25
37
|
matcher = eq("1")
|
26
38
|
matcher.matches?(1)
|
27
|
-
matcher.failure_message_for_should.should
|
39
|
+
matcher.failure_message_for_should.should eq "\nexpected: \"1\"\n got: 1\n\n(compared using ==)\n"
|
28
40
|
end
|
29
41
|
|
30
42
|
it "provides message, expected and actual on #negative_failure_message" do
|
31
43
|
matcher = eq(1)
|
32
44
|
matcher.matches?(1)
|
33
|
-
matcher.failure_message_for_should_not.should
|
45
|
+
matcher.failure_message_for_should_not.should eq "\nexpected: value != 1\n got: 1\n\n(compared using ==)\n"
|
34
46
|
end
|
35
47
|
end
|
36
48
|
end
|