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.
Files changed (38) hide show
  1. data/Changelog.md +35 -1
  2. data/features/step_definitions/additional_cli_steps.rb +10 -0
  3. data/features/test_frameworks/test_unit.feature +40 -0
  4. data/lib/rspec/expectations/caller_filter.rb +50 -45
  5. data/lib/rspec/expectations/deprecation.rb +8 -0
  6. data/lib/rspec/expectations/handler.rb +5 -1
  7. data/lib/rspec/expectations/version.rb +1 -1
  8. data/lib/rspec/matchers.rb +10 -1
  9. data/lib/rspec/matchers/be_close.rb +4 -1
  10. data/lib/rspec/matchers/built_in/base_matcher.rb +8 -9
  11. data/lib/rspec/matchers/built_in/be_within.rb +2 -1
  12. data/lib/rspec/matchers/built_in/change.rb +37 -1
  13. data/lib/rspec/matchers/built_in/has.rb +2 -1
  14. data/lib/rspec/matchers/built_in/have.rb +6 -2
  15. data/lib/rspec/matchers/built_in/raise_error.rb +2 -1
  16. data/lib/rspec/matchers/built_in/respond_to.rb +2 -1
  17. data/lib/rspec/matchers/built_in/satisfy.rb +2 -1
  18. data/lib/rspec/matchers/built_in/throw_symbol.rb +2 -1
  19. data/lib/rspec/matchers/built_in/yield.rb +4 -2
  20. data/lib/rspec/matchers/match_aliases.rb +22 -0
  21. data/lib/rspec/matchers/matcher.rb +18 -1
  22. data/lib/rspec/matchers/operator_matcher.rb +70 -70
  23. data/lib/rspec/matchers/test_unit_integration.rb +22 -5
  24. data/spec/rspec/expectations_spec.rb +1 -1
  25. data/spec/rspec/matchers/base_matcher_spec.rb +27 -12
  26. data/spec/rspec/matchers/be_close_spec.rb +4 -1
  27. data/spec/rspec/matchers/be_spec.rb +2 -2
  28. data/spec/rspec/matchers/change_spec.rb +76 -1
  29. data/spec/rspec/matchers/equal_spec.rb +26 -0
  30. data/spec/rspec/matchers/have_spec.rb +26 -18
  31. data/spec/rspec/matchers/matcher_spec.rb +13 -0
  32. data/spec/rspec/matchers/operator_matcher_spec.rb +25 -6
  33. data/spec/spec_helper.rb +0 -21
  34. data/spec/support/helper_methods.rb +28 -3
  35. data/spec/support/shared_examples.rb +42 -0
  36. metadata +20 -8
  37. checksums.yaml +0 -15
  38. data/spec/rspec/matchers/matchers_spec.rb +0 -37
@@ -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
- line
46
- end
47
- else
48
- # Earlier rubies do not support the two argument form of `caller`. This
49
- # fallback is logically the same, but slower.
50
- def self.first_non_rspec_line
51
- caller.find { |line| line !~ LIB_REGEX }
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
- ::RSpec::Expectations.fail_with message, matcher.expected, matcher.actual
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
@@ -2,7 +2,7 @@ module RSpec
2
2
  module Expectations
3
3
  # @private
4
4
  module Version
5
- STRING = '2.99.0.beta1'
5
+ STRING = '2.99.0.beta2'
6
6
  end
7
7
  end
8
8
  end
@@ -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})", :replacement => "be_within(#{delta}).of(#{expected})")
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 = nil)
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, :@expected
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, :@expected
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
- alias == matches?
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)}`", :replacement => deprecation_message)
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)