rspec-expectations 2.99.0.beta1 → 2.99.0.beta2
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/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)
|