rspec-expectations 2.99.0.beta1 → 2.99.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.md +35 -1
- data/features/step_definitions/additional_cli_steps.rb +10 -0
- data/features/test_frameworks/test_unit.feature +40 -0
- data/lib/rspec/expectations/caller_filter.rb +50 -45
- data/lib/rspec/expectations/deprecation.rb +8 -0
- data/lib/rspec/expectations/handler.rb +5 -1
- data/lib/rspec/expectations/version.rb +1 -1
- data/lib/rspec/matchers.rb +10 -1
- data/lib/rspec/matchers/be_close.rb +4 -1
- data/lib/rspec/matchers/built_in/base_matcher.rb +8 -9
- data/lib/rspec/matchers/built_in/be_within.rb +2 -1
- data/lib/rspec/matchers/built_in/change.rb +37 -1
- data/lib/rspec/matchers/built_in/has.rb +2 -1
- data/lib/rspec/matchers/built_in/have.rb +6 -2
- data/lib/rspec/matchers/built_in/raise_error.rb +2 -1
- data/lib/rspec/matchers/built_in/respond_to.rb +2 -1
- data/lib/rspec/matchers/built_in/satisfy.rb +2 -1
- data/lib/rspec/matchers/built_in/throw_symbol.rb +2 -1
- data/lib/rspec/matchers/built_in/yield.rb +4 -2
- data/lib/rspec/matchers/match_aliases.rb +22 -0
- data/lib/rspec/matchers/matcher.rb +18 -1
- data/lib/rspec/matchers/operator_matcher.rb +70 -70
- data/lib/rspec/matchers/test_unit_integration.rb +22 -5
- data/spec/rspec/expectations_spec.rb +1 -1
- data/spec/rspec/matchers/base_matcher_spec.rb +27 -12
- data/spec/rspec/matchers/be_close_spec.rb +4 -1
- data/spec/rspec/matchers/be_spec.rb +2 -2
- data/spec/rspec/matchers/change_spec.rb +76 -1
- data/spec/rspec/matchers/equal_spec.rb +26 -0
- data/spec/rspec/matchers/have_spec.rb +26 -18
- data/spec/rspec/matchers/matcher_spec.rb +13 -0
- data/spec/rspec/matchers/operator_matcher_spec.rb +25 -6
- data/spec/spec_helper.rb +0 -21
- data/spec/support/helper_methods.rb +28 -3
- data/spec/support/shared_examples.rb +42 -0
- metadata +20 -8
- checksums.yaml +0 -15
- data/spec/rspec/matchers/matchers_spec.rb +0 -37
data/Changelog.md
CHANGED
@@ -1,7 +1,33 @@
|
|
1
|
+
### 2.99.0.beta2 / 2014-02-17
|
2
|
+
[full changelog](http://github.com/rspec/rspec-expectations/compare/v2.99.0.beta1...v2.99.0.beta2)
|
3
|
+
|
4
|
+
Deprecations:
|
5
|
+
|
6
|
+
* Deprecate chaining `by`, `by_at_least`, `by_at_most` or `to` off of
|
7
|
+
`expect { }.not_to change { }`. The docs have always said these are
|
8
|
+
not supported for the negative form but now they explicitly raise
|
9
|
+
errors in RSpec 3. (Myron Marston)
|
10
|
+
* Change the semantics of `expect { }.not_to change { x }.from(y)`.
|
11
|
+
In RSpec 2.x, this expectation would only fail if `x` started with
|
12
|
+
the value of `y` and changed. If it started with a different value
|
13
|
+
and changed, it would pass. In RSpec 3, it will pass only if the
|
14
|
+
value starts at `y` and it does not change. (Myron Marston)
|
15
|
+
* Deprecate `matcher == value` as an alias for `matcher.matches?(value)`,
|
16
|
+
in favor of `matcher === value`. (Myron Marston)
|
17
|
+
* Deprecate `RSpec::Matchers::OperatorMatcher` in favor of
|
18
|
+
`RSpec::Matchers::BuiltIn::OperatorMatcher`. (Myron Marston)
|
19
|
+
* Deprecate auto-integration with Test::Unit and minitest.
|
20
|
+
Instead, include `RSpec::Matchers` in the appropriate test case
|
21
|
+
base class yourself. (Myron Marston)
|
22
|
+
* Deprecate treating `#expected` on a DSL-generated custom matcher
|
23
|
+
as an array when only 1 argument is passed to the matcher method.
|
24
|
+
In RSpec 3 it will be the single value in order to make diffs
|
25
|
+
work properly. (Jon Rowe)
|
26
|
+
|
1
27
|
### 2.99.0.beta1 / 2013-11-07
|
2
28
|
[full changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.4...v2.99.0.beta1)
|
3
29
|
|
4
|
-
Deprecations
|
30
|
+
Deprecations:
|
5
31
|
|
6
32
|
* Deprecate `have`, `have_at_least` and `have_at_most`. You can continue using those
|
7
33
|
matchers through https://github.com/rspec/rspec-collection_matchers, or
|
@@ -23,6 +49,14 @@ Deprecations
|
|
23
49
|
* RSpec 2.x allowed helper methods defined either way to be used for
|
24
50
|
either purpose, but RSpec 3.0 will not.
|
25
51
|
|
52
|
+
### 2.14.5 / 2014-02-01
|
53
|
+
[full changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.4...v2.14.5)
|
54
|
+
|
55
|
+
Bug fixes
|
56
|
+
|
57
|
+
* Fix wrong matcher descriptions with falsey expected value
|
58
|
+
(yujinakayama)
|
59
|
+
|
26
60
|
### 2.14.4 / 2013-11-06
|
27
61
|
[full changelog](http://github.com/rspec/rspec-expectations/compare/v2.14.3...v2.14.4)
|
28
62
|
|
@@ -20,3 +20,13 @@ Then /^the example should fail$/ do
|
|
20
20
|
step %q{the output should contain "1 failure"}
|
21
21
|
step %q{the exit status should not be 0}
|
22
22
|
end
|
23
|
+
|
24
|
+
deprecation_message = /rspec-expectations' built-in integration with (Test::Unit|minitest < 5.x) is deprecated/
|
25
|
+
|
26
|
+
Then /^the output should contain a deprecation warning about rspec\-expecations' built\-in integration$/ do
|
27
|
+
expect(all_output).to match(deprecation_message)
|
28
|
+
end
|
29
|
+
|
30
|
+
Then /^the output should not contain a deprecation warning about rspec\-expecations' built\-in integration$/ do
|
31
|
+
expect(all_output).not_to match(deprecation_message)
|
32
|
+
end
|
@@ -42,3 +42,43 @@ Feature: Test::Unit integration
|
|
42
42
|
Then the output should contain "3 tests, 0 assertions, 0 failures, 1 errors" or "3 tests, 0 assertions, 1 failures, 0 errors"
|
43
43
|
And the output should contain "expected empty? to return true, got false"
|
44
44
|
And the output should contain "be_an_int is deprecated"
|
45
|
+
And the output should contain a deprecation warning about rspec-expecations' built-in integration
|
46
|
+
|
47
|
+
Scenario: use rspec/expectations with Test::Unit
|
48
|
+
Given a file named "rspec_expectations_with_manual_integration_test.rb" with:
|
49
|
+
"""
|
50
|
+
require 'test/unit'
|
51
|
+
require "rspec/expectations"
|
52
|
+
|
53
|
+
class RSpecExpectationsTest < Test::Unit::TestCase
|
54
|
+
include ::RSpec::Matchers
|
55
|
+
|
56
|
+
RSpec::Matchers.define :be_an_integer do
|
57
|
+
match { |actual| Integer === actual }
|
58
|
+
end
|
59
|
+
|
60
|
+
def be_an_int
|
61
|
+
# This is actually an internal rspec-expectations API, but is used
|
62
|
+
# here to demonstrate that deprecation warnings from within
|
63
|
+
# rspec-expectations work correcty without depending on rspec-core
|
64
|
+
RSpec.deprecate(:be_an_int, :replacement => :be_an_integer)
|
65
|
+
be_an_integer
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_passing_expectation
|
69
|
+
expect(1 + 3).to eq 4
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_failing_expectation
|
73
|
+
expect([1,2]).to be_empty
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_custom_matcher_with_deprecation_warning
|
77
|
+
expect(1).to be_an_int
|
78
|
+
end
|
79
|
+
end
|
80
|
+
"""
|
81
|
+
When I run `ruby rspec_expectations_with_manual_integration_test.rb`
|
82
|
+
Then the output should contain "3 tests, 0 assertions, 0 failures, 1 errors" or "3 tests, 0 assertions, 1 failures, 0 errors"
|
83
|
+
And the output should not contain a deprecation warning about rspec-expecations' built-in integration
|
84
|
+
|
@@ -3,53 +3,58 @@ module RSpec
|
|
3
3
|
# non-rspec lines. This enables errors to be reported at the call site in
|
4
4
|
# the code using the library, which is far more useful than the particular
|
5
5
|
# internal method that raised an error.
|
6
|
-
class CallerFilter
|
7
|
-
|
8
|
-
RSPEC_LIBS = %w[
|
9
|
-
core
|
10
|
-
mocks
|
11
|
-
expectations
|
12
|
-
matchers
|
13
|
-
rails
|
14
|
-
]
|
15
|
-
|
16
|
-
ADDITIONAL_TOP_LEVEL_FILES = %w[ autorun ]
|
17
|
-
|
18
|
-
LIB_REGEX = %r{/lib/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)}
|
19
|
-
|
20
|
-
if RUBY_VERSION >= '2.0.0'
|
21
|
-
def self.first_non_rspec_line
|
22
|
-
# `caller` is an expensive method that scales linearly with the size of
|
23
|
-
# the stack. The performance hit for fetching it in chunks is small,
|
24
|
-
# and since the target line is probably near the top of the stack, the
|
25
|
-
# overall improvement of a chunked search like this is significant.
|
26
|
-
#
|
27
|
-
# See benchmarks/caller.rb for measurements.
|
28
|
-
|
29
|
-
# Initial value here is mostly arbitrary, but is chosen to give good
|
30
|
-
# performance on the common case of creating a double.
|
31
|
-
increment = 5
|
32
|
-
i = 1
|
33
|
-
line = nil
|
34
|
-
|
35
|
-
while !line
|
36
|
-
stack = caller(i, increment)
|
37
|
-
raise "No non-lib lines in stack" unless stack
|
38
|
-
|
39
|
-
line = stack.find { |l| l !~ LIB_REGEX }
|
40
|
-
|
41
|
-
i += increment
|
42
|
-
increment *= 2 # The choice of two here is arbitrary.
|
43
|
-
end
|
44
6
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
7
|
+
unless defined?(CallerFilter)
|
8
|
+
|
9
|
+
class CallerFilter
|
10
|
+
|
11
|
+
RSPEC_LIBS = %w[
|
12
|
+
core
|
13
|
+
mocks
|
14
|
+
expectations
|
15
|
+
matchers
|
16
|
+
rails
|
17
|
+
]
|
18
|
+
|
19
|
+
ADDITIONAL_TOP_LEVEL_FILES = %w[ autorun ]
|
20
|
+
|
21
|
+
LIB_REGEX = %r{/lib/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)}
|
22
|
+
|
23
|
+
if RUBY_VERSION >= '2.0.0'
|
24
|
+
def self.first_non_rspec_line
|
25
|
+
# `caller` is an expensive method that scales linearly with the size of
|
26
|
+
# the stack. The performance hit for fetching it in chunks is small,
|
27
|
+
# and since the target line is probably near the top of the stack, the
|
28
|
+
# overall improvement of a chunked search like this is significant.
|
29
|
+
#
|
30
|
+
# See benchmarks/caller.rb for measurements.
|
31
|
+
|
32
|
+
# Initial value here is mostly arbitrary, but is chosen to give good
|
33
|
+
# performance on the common case of creating a double.
|
34
|
+
increment = 5
|
35
|
+
i = 1
|
36
|
+
line = nil
|
37
|
+
|
38
|
+
while !line
|
39
|
+
stack = caller(i, increment)
|
40
|
+
return nil unless stack
|
41
|
+
|
42
|
+
line = stack.find { |l| l !~ LIB_REGEX }
|
43
|
+
|
44
|
+
i += increment
|
45
|
+
increment *= 2 # The choice of two here is arbitrary.
|
46
|
+
end
|
47
|
+
|
48
|
+
line
|
49
|
+
end
|
50
|
+
else
|
51
|
+
# Earlier rubies do not support the two argument form of `caller`. This
|
52
|
+
# fallback is logically the same, but slower.
|
53
|
+
def self.first_non_rspec_line
|
54
|
+
caller.find { |line| line !~ LIB_REGEX }
|
55
|
+
end
|
52
56
|
end
|
53
57
|
end
|
58
|
+
|
54
59
|
end
|
55
60
|
end
|
@@ -12,6 +12,14 @@ module RSpec
|
|
12
12
|
message << " Called from #{CallerFilter.first_non_rspec_line}."
|
13
13
|
warn message
|
14
14
|
end
|
15
|
+
|
16
|
+
# @private
|
17
|
+
#
|
18
|
+
# Used internally to print deprecation warnings
|
19
|
+
def warn_deprecation(warning)
|
20
|
+
message = "\nDEPRECATION: #{warning}\n"
|
21
|
+
warn message
|
22
|
+
end
|
15
23
|
end
|
16
24
|
end
|
17
25
|
|
@@ -31,7 +31,11 @@ module RSpec
|
|
31
31
|
matcher.failure_message
|
32
32
|
|
33
33
|
if matcher.respond_to?(:diffable?) && matcher.diffable?
|
34
|
-
|
34
|
+
if RSpec::Matchers::DSL::Matcher === matcher
|
35
|
+
::RSpec::Expectations.fail_with message, matcher.expected_as_array, matcher.actual
|
36
|
+
else
|
37
|
+
::RSpec::Expectations.fail_with message, matcher.expected, matcher.actual
|
38
|
+
end
|
35
39
|
else
|
36
40
|
::RSpec::Expectations.fail_with message
|
37
41
|
end
|
data/lib/rspec/matchers.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rspec/matchers/extensions/instance_eval_with_args'
|
2
2
|
require 'rspec/matchers/pretty'
|
3
3
|
|
4
|
+
require 'rspec/matchers/match_aliases'
|
4
5
|
require 'rspec/matchers/built_in'
|
5
6
|
require 'rspec/matchers/matcher'
|
6
7
|
require 'rspec/matchers/operator_matcher'
|
@@ -707,6 +708,14 @@ module RSpec
|
|
707
708
|
BuiltIn::MatchArray.new(array)
|
708
709
|
end
|
709
710
|
|
710
|
-
OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
|
711
|
+
BuiltIn::OperatorMatcher.register(Enumerable, '=~', BuiltIn::MatchArray)
|
712
|
+
|
713
|
+
def self.const_missing(name)
|
714
|
+
return super unless name == :OperatorMatcher
|
715
|
+
|
716
|
+
RSpec.deprecate("RSpec::Matchers::OperatorMatcher",
|
717
|
+
:replacement => "RSpec::Matchers::BuiltIn::OperatorMatcher")
|
718
|
+
BuiltIn::OperatorMatcher
|
719
|
+
end
|
711
720
|
end
|
712
721
|
end
|
@@ -2,7 +2,10 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
# @deprecated use +be_within+ instead.
|
4
4
|
def be_close(expected, delta)
|
5
|
-
RSpec.deprecate("be_close(#{expected}, #{delta})",
|
5
|
+
RSpec.deprecate("be_close(#{expected}, #{delta})",
|
6
|
+
:replacement => "be_within(#{delta}).of(#{expected})",
|
7
|
+
:type => 'the be_close matcher'
|
8
|
+
)
|
6
9
|
be_within(delta).of(expected)
|
7
10
|
end
|
8
11
|
end
|
@@ -13,11 +13,14 @@ module RSpec
|
|
13
13
|
# class. If/when this changes, we will announce it and remove this warning.
|
14
14
|
class BaseMatcher
|
15
15
|
include RSpec::Matchers::Pretty
|
16
|
+
include RSpec::Matchers::MatchAliases
|
17
|
+
|
18
|
+
UNDEFINED = Object.new.freeze
|
16
19
|
|
17
20
|
attr_reader :actual, :expected, :rescued_exception
|
18
21
|
|
19
|
-
def initialize(expected =
|
20
|
-
@expected = expected
|
22
|
+
def initialize(expected = UNDEFINED)
|
23
|
+
@expected = expected unless UNDEFINED.equal?(expected)
|
21
24
|
end
|
22
25
|
|
23
26
|
def matches?(actual)
|
@@ -36,27 +39,23 @@ module RSpec
|
|
36
39
|
end
|
37
40
|
|
38
41
|
def failure_message_for_should
|
39
|
-
assert_ivars :@actual
|
42
|
+
assert_ivars :@actual
|
40
43
|
"expected #{@actual.inspect} to #{name_to_sentence}#{expected_to_sentence}"
|
41
44
|
end
|
42
45
|
|
43
46
|
def failure_message_for_should_not
|
44
|
-
assert_ivars :@actual
|
47
|
+
assert_ivars :@actual
|
45
48
|
"expected #{@actual.inspect} not to #{name_to_sentence}#{expected_to_sentence}"
|
46
49
|
end
|
47
50
|
|
48
51
|
def description
|
49
|
-
expected ? "#{name_to_sentence} #{@expected.inspect}" : name_to_sentence
|
52
|
+
defined?(@expected) ? "#{name_to_sentence} #{@expected.inspect}" : name_to_sentence
|
50
53
|
end
|
51
54
|
|
52
55
|
def diffable?
|
53
56
|
false
|
54
57
|
end
|
55
58
|
|
56
|
-
def ==(other)
|
57
|
-
matches?(other)
|
58
|
-
end
|
59
|
-
|
60
59
|
private
|
61
60
|
|
62
61
|
def assert_ivars *ivars
|
@@ -2,6 +2,8 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
4
|
class BeWithin
|
5
|
+
include MatchAliases
|
6
|
+
|
5
7
|
def initialize(delta)
|
6
8
|
@delta = delta
|
7
9
|
end
|
@@ -12,7 +14,6 @@ module RSpec
|
|
12
14
|
raise needs_subtractable unless @actual.respond_to? :-
|
13
15
|
(@actual - @expected).abs <= @tolerance
|
14
16
|
end
|
15
|
-
alias == matches?
|
16
17
|
|
17
18
|
def of(expected)
|
18
19
|
@expected = expected
|
@@ -2,6 +2,8 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
4
|
class Change
|
5
|
+
include MatchAliases
|
6
|
+
|
5
7
|
def initialize(receiver=nil, message=nil, &block)
|
6
8
|
@message = message
|
7
9
|
@value_proc = block || lambda {receiver.__send__(message)}
|
@@ -18,7 +20,41 @@ module RSpec
|
|
18
20
|
|
19
21
|
(!change_expected? || changed?) && matches_before? && matches_after? && matches_expected_delta? && matches_min? && matches_max?
|
20
22
|
end
|
21
|
-
|
23
|
+
|
24
|
+
def does_not_match?(event_proc, &block)
|
25
|
+
expression = if @expected_delta
|
26
|
+
"by()"
|
27
|
+
elsif @minimum
|
28
|
+
"by_at_least()"
|
29
|
+
elsif @maximum
|
30
|
+
"by_at_most()"
|
31
|
+
elsif @eval_after
|
32
|
+
"to()"
|
33
|
+
end
|
34
|
+
|
35
|
+
if expression
|
36
|
+
RSpec.deprecate("`expect { }.not_to change { }.#{expression}`")
|
37
|
+
end
|
38
|
+
|
39
|
+
matched_positively = matches?(event_proc, &block)
|
40
|
+
|
41
|
+
unless matches_before?
|
42
|
+
RSpec.warn_deprecation(<<-EOS.gsub(/^\s+\|/, ''))
|
43
|
+
|--------------------------------------------------------------------
|
44
|
+
|The semantics of `expect { }.not_to change { }.from()` are changing
|
45
|
+
|in RSpec 3. In RSpec 2.x, this would pass if the value changed but
|
46
|
+
|the starting value was not what you specified with `from()`. In
|
47
|
+
|RSpec 3, this will only pass if the starting value matches your
|
48
|
+
|`from()` value _and_ it has not changed.
|
49
|
+
|
|
50
|
+
|You have an expectation that relies upon the old RSpec 2.x semantics
|
51
|
+
|at: #{CallerFilter.first_non_rspec_line}"
|
52
|
+
|--------------------------------------------------------------------
|
53
|
+
EOS
|
54
|
+
end
|
55
|
+
|
56
|
+
!matched_positively
|
57
|
+
end
|
22
58
|
|
23
59
|
def raise_block_syntax_error
|
24
60
|
raise SyntaxError.new(<<-MESSAGE)
|
@@ -2,6 +2,8 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
4
|
class Has
|
5
|
+
include MatchAliases
|
6
|
+
|
5
7
|
def initialize(expected, *args)
|
6
8
|
@expected, @args = expected, args
|
7
9
|
end
|
@@ -9,7 +11,6 @@ module RSpec
|
|
9
11
|
def matches?(actual)
|
10
12
|
actual.__send__(predicate(@expected), *@args)
|
11
13
|
end
|
12
|
-
alias == matches?
|
13
14
|
|
14
15
|
def failure_message_for_should
|
15
16
|
"expected ##{predicate(@expected)}#{failure_message_args_description} to return true, got false"
|
@@ -2,6 +2,8 @@ module RSpec
|
|
2
2
|
module Matchers
|
3
3
|
module BuiltIn
|
4
4
|
class Have
|
5
|
+
include MatchAliases
|
6
|
+
|
5
7
|
QUERY_METHODS = [:size, :length, :count].freeze
|
6
8
|
|
7
9
|
def initialize(expected, relativity=:exactly)
|
@@ -54,7 +56,6 @@ module RSpec
|
|
54
56
|
else @actual == @expected
|
55
57
|
end
|
56
58
|
end
|
57
|
-
alias == matches?
|
58
59
|
|
59
60
|
def does_not_match?(collection_or_owner)
|
60
61
|
@negative_expectation = true
|
@@ -143,7 +144,10 @@ EOF
|
|
143
144
|
deprecation_message << "or replace your expectation with something like "
|
144
145
|
deprecation_message << "`expect(#{cardinality_expression(query_method)}).#{expectation_format_method} #{suggested_matcher_expression}`"
|
145
146
|
|
146
|
-
RSpec.deprecate("`#{expectation_expression(query_method)}`",
|
147
|
+
RSpec.deprecate("`#{expectation_expression(query_method)}`",
|
148
|
+
:replacement => deprecation_message,
|
149
|
+
:type => "the have matcher"
|
150
|
+
)
|
147
151
|
end
|
148
152
|
|
149
153
|
def expectation_expression(query_method)
|