diff --git a/README.md b/README.md index 3888c9377..33ef493dd 100644 --- a/README.md +++ b/README.md @@ -219,16 +219,15 @@ expect( ## `should` syntax In addition to the `expect` syntax, rspec-expectations continues to support the -`should` syntax: +non-monkey patching `should` syntax: ```ruby -actual.should eq expected -actual.should be > 3 -[1, 2, 3].should_not include 4 +subject(:number) { 4 } +it { should eq(4) } +it { should be > 3 } +it { should_not be_even } ``` -See [detailed information on the `should` syntax and its usage.](https://github.com/rspec/rspec-expectations/blob/main/Should.md) - ## Compound Matcher Expressions You can also create compound matcher expressions using `and` or `or`: diff --git a/Should.md b/Should.md deleted file mode 100644 index ec8d66811..000000000 --- a/Should.md +++ /dev/null @@ -1,176 +0,0 @@ -# `should` and `should_not` syntax - -From the beginning RSpec::Expectations provided `should` and `should_not` methods -to define expectations on any object. In version 2.11 `expect` method was -introduced which is now the recommended way to define expectations on an object. - -### Why switch over from `should` to `expect` - -#### Fix edge case issues - -`should` and `should_not` work by being added to every object. However, RSpec -does not own every object and cannot ensure they work consistently on every object. -In particular, they can lead to surprising failures when used with BasicObject-subclassed -proxy objects. - -`expect` avoids these problems altogether by not needing to be available on all objects. - -#### Unification of block and value syntaxes - -Before version 2.11 `expect` was just a more readable alternative for block -expectations. Since version 2.11 `expect` can be used for both block and value -expectations. - -```ruby -expect(actual).to eq(expected) -expect { ... }.to raise_error(ErrorClass) -``` - -See -[http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax](http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax) -For a detailed explanation - -### One-liners - -The one-liner syntax supported by -[rspec-core](http://rubydoc.info/gems/rspec-core) uses `should` even when -`config.syntax = :expect`. It reads better than the alternative, and does not -require a global monkey patch: - -```ruby -describe User do - it { should validate_presence_of :email } -end -``` - -It can also be expressed with the `is_expected` syntax: - -```ruby -describe User do - it { is_expected.to validate_presence_of :email } -end -``` - -### Using either `expect` or `should` or both - -By default, both `expect` and `should` syntaxes are available. In the future, -the default may be changed to only enable the `expect` syntax. - -If you want your project to only use any one of these syntaxes, you can configure -it: - -```ruby -RSpec.configure do |config| - config.expect_with :rspec do |c| - c.syntax = :expect # disables `should` - # or - c.syntax = :should # disables `expect` - # or - c.syntax = [:should, :expect] # default, enables both `should` and `expect` - end -end -``` - -See -[RSpec::Expectations::Syntax#expect](http://rubydoc.info/gems/rspec-expectations/RSpec/Expectations/Syntax:expect) -for more information. - -## Usage - -The `should` and `should_not` methods can be used to define expectations on any -object. - -```ruby -actual.should eq expected -actual.should be > 3 -[1, 2, 3].should_not include 4 -``` - -## Using Built-in matchers - -### Equivalence - -```ruby -actual.should eq(expected) # passes if actual == expected -actual.should == expected # passes if actual == expected -actual.should_not eql(expected) # passes if actual.eql?(expected) -``` - -Note: we recommend the `eq` matcher over `==` to avoid Ruby's "== in a -useless context" warning when the `==` matcher is used anywhere but the -last statement of an example. - -### Identity - -```ruby -actual.should be(expected) # passes if actual.equal?(expected) -actual.should_not equal(expected) # passes if actual.equal?(expected) -``` - -### Comparisons - -```ruby -actual.should be > expected -actual.should be >= expected -actual.should be <= expected -actual.should be < expected -actual.should be_within(delta).of(expected) -``` - -### Regular expressions - -```ruby -actual.should match(/expression/) -actual.should =~ /expression/ -``` - -### Types/classes - -```ruby -actual.should be_an_instance_of(expected) -actual.should_not be_a_kind_of(expected) -``` - -### Truthiness - -```ruby -actual.should be_true # passes if actual is truthy (not nil or false) -actual.should be_false # passes if actual is falsy (nil or false) -actual.should be_nil # passes if actual is nil -``` - -### Predicate matchers - -```ruby -actual.should be_xxx # passes if actual.xxx? -actual.should_not have_xxx(:arg) # passes if actual.has_xxx?(:arg) -``` - -### Ranges (Ruby >= 1.9 only) - -```ruby -(1..10).should cover(3) -``` - -### Collection membership - -```ruby -actual.should include(expected) -actual.should start_with(expected) -actual.should end_with(expected) -``` - -#### Examples - -```ruby -[1,2,3].should include(1) -[1,2,3].should include(1, 2) -[1,2,3].should start_with(1) -[1,2,3].should start_with(1,2) -[1,2,3].should end_with(3) -[1,2,3].should end_with(2,3) -{:a => 'b'}.should include(:a => 'b') -"this string".should include("is str") -"this string".should start_with("this") -"this string".should end_with("ring") -``` diff --git a/features/built_in_matchers/README.md b/features/built_in_matchers/README.md index a9cda832d..522126ce9 100644 --- a/features/built_in_matchers/README.md +++ b/features/built_in_matchers/README.md @@ -1,13 +1,12 @@ rspec-expectations ships with a number of built-in matchers. Each matcher can be used with `expect(..).to` or `expect(..).not_to` to define positive and negative expectations -respectively on an object. Most matchers can also be accessed using the `(...).should` and -`(...).should_not` syntax; see [using should syntax](https://github.com/rspec/rspec-expectations/blob/main/Should.md) for why we recommend using `expect`. +respectively on an object. e.g. expect(result).to eq(3) expect(list).not_to be_empty - pi.should be > 3 + should be > 3 ## Object identity diff --git a/features/support/disallow_certain_apis.rb b/features/support/disallow_certain_apis.rb deleted file mode 100644 index fc89d382f..000000000 --- a/features/support/disallow_certain_apis.rb +++ /dev/null @@ -1,33 +0,0 @@ -# This file is designed to prevent the use of certain APIs that -# we don't want used from our cukes, since they function as documentation. - -if defined?(Cucumber) - require 'shellwords' - Before('~@allow-disallowed-api') do - set_environment_variable('SPEC_OPTS', "-r#{Shellwords.escape(__FILE__)}") - end -else - module DisallowOneLinerShould - def should(*) - raise "one-liner should is not allowed" - end - - def should_not(*) - raise "one-liner should_not is not allowed" - end - end - - RSpec.configure do |rspec| - rspec.expose_dsl_globally = false - - rspec.mock_with :rspec do |mocks| - mocks.syntax = :expect - end - - rspec.expect_with :rspec do |expectations| - expectations.syntax = :expect - end - - rspec.include DisallowOneLinerShould - end -end diff --git a/features/syntax_configuration.feature b/features/syntax_configuration.feature deleted file mode 100644 index fdbafbc86..000000000 --- a/features/syntax_configuration.feature +++ /dev/null @@ -1,92 +0,0 @@ -@allow-disallowed-api -Feature: Syntax Configuration - - The primary syntax provided by rspec-expectations is based on - the `expect` method, which explicitly wraps an object or block - of code in order to set an expectation on it. - - There's also an older `should`-based syntax, which relies upon `should` being - monkey-patched onto every object in the system. However, this syntax can at times lead to - some surprising failures, since RSpec does not own every object in the system and cannot - guarantee that it will always work consistently. - - We recommend you use the `expect` syntax unless you have a specific reason you prefer the - `should` syntax. We have no plans to ever completely remove the `should` syntax but starting - in RSpec 3, a deprecation warning will be issued if you do not explicitly enable it, with the - plan to disable it by default in RSpec 4 (and potentially move it into an external gem). - - If you have an old `should`-based project that you would like to upgrade to the `expect`, - check out [transpec](http://yujinakayama.me/transpec/), which can perform the conversion automatically for you. - - Background: - Given a file named "spec/syntaxes_spec.rb" with: - """ruby - require 'spec_helper' - - RSpec.describe "using the should syntax" do - specify { 3.should eq(3) } - specify { 3.should_not eq(4) } - specify { lambda { raise "boom" }.should raise_error("boom") } - specify { lambda { }.should_not raise_error } - end - - RSpec.describe "using the expect syntax" do - specify { expect(3).to eq(3) } - specify { expect(3).not_to eq(4) } - specify { expect { raise "boom" }.to raise_error("boom") } - specify { expect { }.not_to raise_error } - end - """ - - Scenario: Both syntaxes are available by default - Given a file named "spec/spec_helper.rb" with: - """ruby - """ - When I run `rspec` - Then the examples should all pass - And the output should contain "Using `should` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax is deprecated" - - Scenario: Disable should syntax - Given a file named "spec/spec_helper.rb" with: - """ruby - RSpec.configure do |config| - config.expect_with :rspec do |expectations| - expectations.syntax = :expect - end - end - """ - When I run `rspec` - Then the output should contain all of these: - | 8 examples, 4 failures | - | undefined method `should' | - - Scenario: Disable expect syntax - Given a file named "spec/spec_helper.rb" with: - """ruby - RSpec.configure do |config| - config.expect_with :rspec do |expectations| - expectations.syntax = :should - end - config.mock_with :rspec do |mocks| - mocks.syntax = :should - end - end - """ - When I run `rspec` - Then the output should contain all of these: - | 8 examples, 4 failures | - | undefined method `expect' | - - Scenario: Explicitly enable both syntaxes - Given a file named "spec/spec_helper.rb" with: - """ruby - RSpec.configure do |config| - config.expect_with :rspec do |expectations| - expectations.syntax = [:should, :expect] - end - end - """ - When I run `rspec` - Then the examples should all pass - And the output should not contain "deprecated" - diff --git a/lib/rspec/expectations/configuration.rb b/lib/rspec/expectations/configuration.rb index a16b5b5e4..ddfbb5313 100644 --- a/lib/rspec/expectations/configuration.rb +++ b/lib/rspec/expectations/configuration.rb @@ -1,5 +1,3 @@ -RSpec::Support.require_rspec_expectations "syntax" - module RSpec module Expectations # Provides configuration options for rspec-expectations. @@ -31,32 +29,6 @@ def initialize @strict_predicate_matchers = false end - # Configures the supported syntax. - # @param [Array, Symbol] values the syntaxes to enable - # @example - # RSpec.configure do |rspec| - # rspec.expect_with :rspec do |c| - # c.syntax = :should - # # or - # c.syntax = :expect - # # or - # c.syntax = [:should, :expect] - # end - # end - def syntax=(values) - if Array(values).include?(:expect) - Expectations::Syntax.enable_expect - else - Expectations::Syntax.disable_expect - end - - if Array(values).include?(:should) - Expectations::Syntax.enable_should - else - Expectations::Syntax.disable_should - end - end - # Configures the maximum character length that RSpec will print while # formatting an object. You can set length to nil to prevent RSpec from # doing truncation. @@ -71,19 +43,6 @@ def max_formatted_output_length=(length) RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = length end - # The list of configured syntaxes. - # @return [Array] the list of configured syntaxes. - # @example - # unless RSpec::Matchers.configuration.syntax.include?(:expect) - # raise "this RSpec extension gem requires the rspec-expectations `:expect` syntax" - # end - def syntax - syntaxes = [] - syntaxes << :should if Expectations::Syntax.should_enabled? - syntaxes << :expect if Expectations::Syntax.expect_enabled? - syntaxes - end - if ::RSpec.respond_to?(:configuration) def color? ::RSpec.configuration.color_enabled? @@ -102,18 +61,6 @@ def color? end end - # Adds `should` and `should_not` to the given classes - # or modules. This can be used to ensure `should` works - # properly on things like proxy objects. - # - # @param [Array] modules the list of classes or modules - # to add `should` and `should_not` to. - def add_should_and_should_not_to(*modules) - modules.each do |mod| - Expectations::Syntax.enable_should(mod) - end - end - # Sets or gets the backtrace formatter. The backtrace formatter should # implement `#format_backtrace(Array)`. This is used # to format backtraces of errors handled by the `raise_error` @@ -145,12 +92,6 @@ def include_chain_clauses_in_custom_matcher_descriptions? @include_chain_clauses_in_custom_matcher_descriptions ||= false end - # @private - def reset_syntaxes_to_default - self.syntax = [:should, :expect] - RSpec::Expectations::Syntax.warn_about_should! - end - # @api private # Null implementation of a backtrace formatter used by default # when rspec-core is not loaded. Does no filtering. @@ -222,8 +163,5 @@ def false_positives_handler def self.configuration @configuration ||= Configuration.new end - - # set default syntax - configuration.reset_syntaxes_to_default end end diff --git a/lib/rspec/expectations/syntax.rb b/lib/rspec/expectations/syntax.rb deleted file mode 100644 index c61670cd4..000000000 --- a/lib/rspec/expectations/syntax.rb +++ /dev/null @@ -1,130 +0,0 @@ -module RSpec - module Expectations - # @api private - # Provides methods for enabling and disabling the available - # syntaxes provided by rspec-expectations. - module Syntax - module_function - - # @api private - # Determines where we add `should` and `should_not`. - def default_should_host - @default_should_host ||= ::Object.ancestors.last - end - - # @api private - # Instructs rspec-expectations to warn on first usage of `should` or `should_not`. - # Enabled by default. This is largely here to facilitate testing. - def warn_about_should! - @warn_about_should = true - end - - # @api private - # Generates a deprecation warning for the given method if no warning - # has already been issued. - def warn_about_should_unless_configured(method_name) - return unless @warn_about_should - - RSpec.deprecate( - "Using `#{method_name}` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax", - :replacement => "the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }`" - ) - - @warn_about_should = false - end - - # @api private - # Enables the `should` syntax. - def enable_should(syntax_host=default_should_host) - @warn_about_should = false if syntax_host == default_should_host - return if should_enabled?(syntax_host) - - syntax_host.module_exec do - def should(matcher=nil, message=nil, &block) - ::RSpec::Expectations::Syntax.warn_about_should_unless_configured(::Kernel.__method__) - ::RSpec::Expectations::PositiveExpectationHandler.handle_matcher(self, matcher, message, &block) - end - - def should_not(matcher=nil, message=nil, &block) - ::RSpec::Expectations::Syntax.warn_about_should_unless_configured(::Kernel.__method__) - ::RSpec::Expectations::NegativeExpectationHandler.handle_matcher(self, matcher, message, &block) - end - end - end - - # @api private - # Disables the `should` syntax. - def disable_should(syntax_host=default_should_host) - return unless should_enabled?(syntax_host) - - syntax_host.module_exec do - undef should - undef should_not - end - end - - # @api private - # Enables the `expect` syntax. - def enable_expect(syntax_host=::RSpec::Matchers) - return if expect_enabled?(syntax_host) - - syntax_host.module_exec do - def expect(value=::RSpec::Expectations::ExpectationTarget::UndefinedValue, &block) - ::RSpec::Expectations::ExpectationTarget.for(value, block) - end - end - end - - # @api private - # Disables the `expect` syntax. - def disable_expect(syntax_host=::RSpec::Matchers) - return unless expect_enabled?(syntax_host) - - syntax_host.module_exec do - undef expect - end - end - - # @api private - # Indicates whether or not the `should` syntax is enabled. - def should_enabled?(syntax_host=default_should_host) - syntax_host.method_defined?(:should) - end - - # @api private - # Indicates whether or not the `expect` syntax is enabled. - def expect_enabled?(syntax_host=::RSpec::Matchers) - syntax_host.method_defined?(:expect) - end - end - end -end - -# The legacy `:should` syntax adds the following methods directly to -# `BasicObject` so that they are available off of any object. Note, however, -# that this syntax does not always play nice with delegate/proxy objects. -# We recommend you use the non-monkeypatching `:expect` syntax instead. -class BasicObject - # @method should(matcher, message) - # Passes if `matcher` returns true. Available on every `Object`. - # @example - # actual.should eq expected - # actual.should match /expression/ - # @param [Matcher] - # matcher - # @param [String] message optional message to display when the expectation fails - # @return [Boolean] true if the expectation succeeds (else raises) - # @note This is only available when you have enabled the `:should` syntax. - # @see RSpec::Matchers - - # @method should_not(matcher, message) - # Passes if `matcher` returns false. Available on every `Object`. - # @example - # actual.should_not eq expected - # @param [Matcher] - # matcher - # @param [String] message optional message to display when the expectation fails - # @return [Boolean] false if the negative expectation succeeds (else raises) - # @note This is only available when you have enabled the `:should` syntax. - # @see RSpec::Matchers -end diff --git a/lib/rspec/matchers.rb b/lib/rspec/matchers.rb index dc978411a..bffcb0a38 100644 --- a/lib/rspec/matchers.rb +++ b/lib/rspec/matchers.rb @@ -306,6 +306,11 @@ def aggregate_failures(label=nil, metadata={}, &block) Expectations::FailureAggregator.new(label, metadata).aggregate(&block) end + # TODO: docs + def expect(value=::RSpec::Expectations::ExpectationTarget::UndefinedValue, &block) + ::RSpec::Expectations::ExpectationTarget.for(value, block) + end + # Passes if actual is truthy (anything but false or nil) def be_truthy BuiltIn::BeTruthy.new diff --git a/lib/rspec/matchers/built_in/operators.rb b/lib/rspec/matchers/built_in/operators.rb index 64f8f3b23..188eb14a9 100644 --- a/lib/rspec/matchers/built_in/operators.rb +++ b/lib/rspec/matchers/built_in/operators.rb @@ -6,7 +6,7 @@ module BuiltIn # @api private # Provides the implementation for operator matchers. # Not intended to be instantiated directly. - # Only available for use with `should`. + # Only available for use with `should` one-liner syntax. class OperatorMatcher class << self # @private @@ -93,7 +93,7 @@ def eval_match(actual, operator, expected) end # @private - # Handles operator matcher for `should`. + # Handles operator matcher for positive expectations class PositiveOperatorMatcher < OperatorMatcher def __delegate_operator(actual, operator, expected) if actual.__send__(operator, expected) @@ -112,7 +112,7 @@ def __delegate_operator(actual, operator, expected) end # @private - # Handles operator matcher for `should_not`. + # Handles operator matcher for negative expectations class NegativeOperatorMatcher < OperatorMatcher def __delegate_operator(actual, operator, expected) return false unless actual.__send__(operator, expected) diff --git a/spec/rspec/expectations/configuration_spec.rb b/spec/rspec/expectations/configuration_spec.rb index a488068f4..59ced1c05 100644 --- a/spec/rspec/expectations/configuration_spec.rb +++ b/spec/rspec/expectations/configuration_spec.rb @@ -121,146 +121,6 @@ class << rspec_dup; undef configuration; end expect(config.on_potential_false_positives).to eq :raise end end - - shared_examples "configuring the expectation syntax" do - before do - @orig_syntax = RSpec::Matchers.configuration.syntax - end - - after do - configure_syntax(@orig_syntax) - end - - it 'can limit the syntax to :should' do - configure_syntax :should - configured_syntax.should eq([:should]) - - 3.should eq(3) - 3.should_not eq(4) - lambda { expect(6).to eq(6) }.should raise_error(NameError) - end - - it 'is a no-op when configured to :should twice' do - configure_syntax :should - method_added_count = 0 - allow(Expectations::Syntax.default_should_host).to receive(:method_added) { method_added_count += 1 } - configure_syntax :should - - method_added_count.should eq(0) - end - - it 'can limit the syntax to :expect' do - configure_syntax :expect - expect(configured_syntax).to eq([:expect]) - - expect(3).to eq(3) - expect { 3.should eq(3) }.to raise_error(NameError) - expect { 3.should_not eq(3) }.to raise_error(NameError) - end - - it 'is a no-op when configured to :expect twice' do - allow(RSpec::Matchers).to receive(:method_added).and_raise("no methods should be added here") - - configure_syntax :expect - configure_syntax :expect - end - - describe "`:should` being enabled by default deprecation" do - before { configure_default_syntax } - - it "warns when the should syntax is called by default" do - expected_arguments = [ - /Using.*without explicitly enabling/, - { :replacement => "the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }`" } - ] - - expect(RSpec).to receive(:deprecate).with(*expected_arguments) - 3.should eq(3) - end - - it "includes the call site in the deprecation warning by default" do - expect_deprecation_with_call_site(__FILE__, __LINE__ + 1) - 3.should eq(3) - end - - it "does not warn when only the should syntax is explicitly configured" do - configure_syntax(:should) - RSpec.should_not receive(:deprecate) - 3.should eq(3) - end - - it "does not warn when both the should and expect syntaxes are explicitly configured" do - configure_syntax([:should, :expect]) - expect(RSpec).not_to receive(:deprecate) - 3.should eq(3) - end - end - - it 'can re-enable the :should syntax' do - configure_syntax :expect - configure_syntax [:should, :expect] - configured_syntax.should eq([:should, :expect]) - - 3.should eq(3) - 3.should_not eq(4) - expect(3).to eq(3) - end - - it 'can re-enable the :expect syntax' do - configure_syntax :should - configure_syntax [:should, :expect] - configured_syntax.should eq([:should, :expect]) - - 3.should eq(3) - 3.should_not eq(4) - expect(3).to eq(3) - end - end - - def configure_default_syntax - RSpec::Matchers.configuration.reset_syntaxes_to_default - end - - describe "configuring rspec-expectations directly" do - it_behaves_like "configuring the expectation syntax" do - def configure_syntax(syntax) - RSpec::Matchers.configuration.syntax = syntax - end - - def configured_syntax - RSpec::Matchers.configuration.syntax - end - end - end - - describe "configuring using the rspec-core config API" do - it_behaves_like "configuring the expectation syntax" do - def configure_syntax(syntax) - RSpec.configure do |rspec| - rspec.expect_with :rspec do |c| - c.syntax = syntax - end - end - end - - def configured_syntax - RSpec.configure do |rspec| - rspec.expect_with :rspec do |c| - return c.syntax - end - end - end - end - end - - it 'enables both syntaxes by default' do - # This is kinda a hack, but since we want to enforce use of - # the expect syntax within our specs here, we have modified the - # config setting, which makes it hard to get at the original - # default value. in spec_helper.rb we store the default value - # in $default_expectation_syntax so we can use it here. - expect($default_expectation_syntax).to contain_exactly(:expect, :should) # rubocop:disable Style/GlobalVars - end end end end diff --git a/spec/rspec/expectations/extensions/kernel_spec.rb b/spec/rspec/expectations/extensions/kernel_spec.rb index c8c4e20b5..aca63f76e 100644 --- a/spec/rspec/expectations/extensions/kernel_spec.rb +++ b/spec/rspec/expectations/extensions/kernel_spec.rb @@ -43,16 +43,6 @@ def method_missing(name, *args) it 'works properly on BasicObject-subclassed proxy objects' do expect(proxy_class.new(Object.new)).to be_proxied end - - it 'does not break the deprecation check on BasicObject-subclassed proxy objects' do - begin - should_enabled = RSpec::Expectations::Syntax.should_enabled? - RSpec::Expectations::Syntax.enable_should unless should_enabled - proxy_class.new(BasicObject.new).should be_proxied - ensure - RSpec::Expectations::Syntax.disable_should if should_enabled - end - end end end diff --git a/spec/rspec/expectations/syntax_spec.rb b/spec/rspec/expectations/syntax_spec.rb index a931aee4f..19cd87494 100644 --- a/spec/rspec/expectations/syntax_spec.rb +++ b/spec/rspec/expectations/syntax_spec.rb @@ -1,6 +1,6 @@ module RSpec module Expectations - RSpec.describe Syntax do + RSpec.describe 'Syntax' do context "when passing a message to an expectation" do let(:warner) { ::Kernel } @@ -70,18 +70,6 @@ module Expectations end end end - - describe "enabling the should syntax on something other than the default syntax host" do - include_context "with the default expectation syntax" - - it "continues to warn about the should syntax" do - my_host = Class.new - expect(RSpec).to receive(:deprecate) - Syntax.enable_should(my_host) - - 3.should eq 3 - end - end end end end diff --git a/spec/rspec/matchers/built_in/be_spec.rb b/spec/rspec/matchers/built_in/be_spec.rb index 7ef0d9762..fd98aff07 100644 --- a/spec/rspec/matchers/built_in/be_spec.rb +++ b/spec/rspec/matchers/built_in/be_spec.rb @@ -746,14 +746,16 @@ def send end end -RSpec.describe "should be =~", :uses_should do +RSpec.describe "should be =~" do + subject { "a string" } + it "passes when =~ operator returns true" do - "a string".should be =~ /str/ + should be =~ /str/ end it "fails when =~ operator returns false" do expect { - "a string".should be =~ /blah/ + should be =~ /blah/ }.to fail_with(%(expected: =~ /blah/\n got: "a string")) end end diff --git a/spec/rspec/matchers/built_in/contain_exactly_spec.rb b/spec/rspec/matchers/built_in/contain_exactly_spec.rb index 075d7469c..cee758c73 100644 --- a/spec/rspec/matchers/built_in/contain_exactly_spec.rb +++ b/spec/rspec/matchers/built_in/contain_exactly_spec.rb @@ -24,76 +24,6 @@ def to_ary end end -RSpec.describe "should =~ array", :uses_should do - it "passes a valid positive expectation" do - [1, 2].should =~ [2, 1] - end - - it "fails an invalid positive expectation" do - expect { - [1, 2, 3].should =~ [2, 1] - }.to fail_with(/expected collection contained/) - end - - context "when the array defines a `=~` method" do - it 'delegates to that method rather than using the contain_exactly matcher' do - array = [] - def array.=~(other) - other == :foo - end - - array.should =~ :foo - expect { - array.should =~ :bar - }.to fail_with(/expected: :bar/) - end - end - - context 'when the array defines a `send` method' do - it 'still works' do - array = [1, 2] - def array.send; :sent; end - - array.should =~ array - end - end - - context "when the array undefines `=~`" do - it 'still works' do - array_klass = Class.new(Array) { undef =~ } - array = array_klass.new([1, 2]) - - array.should =~ [1, 2] - - expect { - array.should =~ [0, 1, 2] - }.to fail_with(/expected collection contained/) - end - end -end - -RSpec.describe "should_not =~ [:with, :multiple, :args]", :uses_should do - it "fails when the arrays match" do - expect { - [1, 2, 3].should_not =~ [1, 2, 3] - }.to fail_with "expected [1, 2, 3] not to contain exactly 1, 2, and 3" - end - - it "fails when the arrays match in a different order" do - expect { - [1, 3, 2].should_not =~ [1, 2, 3] - }.to fail_with "expected [1, 3, 2] not to contain exactly 1, 2, and 3" - end - - it "passes when there are extra elements in the array" do - [1, 3].should_not =~ [1, 2, 3] - end - - it "passes when there are elements missing from the array" do - [1, 2, 3, 4].should_not =~ [1, 2, 3] - end -end - RSpec.describe "using contain_exactly with expect" do it "passes a valid positive expectation" do expect([1, 2]).to contain_exactly(2, 1) diff --git a/spec/rspec/matchers/built_in/operators_spec.rb b/spec/rspec/matchers/built_in/operators_spec.rb index 830ff38d8..a24ab290b 100644 --- a/spec/rspec/matchers/built_in/operators_spec.rb +++ b/spec/rspec/matchers/built_in/operators_spec.rb @@ -12,195 +12,199 @@ def method_missing(name, *args, &block) end end -RSpec.describe "operator matchers", :uses_should do +RSpec.describe "operator matchers" do describe "should ==" do + subject { 'apple'.dup } + it "delegates message to target" do - subject = "apple".dup expect(subject).to receive(:==).with("apple").and_return(true) - subject.should == "apple" + should == "apple" end it "returns true on success" do - subject = "apple" - (subject.should == "apple").should be_truthy + expect(should == "apple").to be(true) end it "fails when target.==(actual) returns false" do - subject = "apple" expect(RSpec::Expectations).to receive(:fail_with).with(%{expected: "orange"\n got: "apple" (using ==)}, "orange", "apple") - subject.should == "orange" + should == "orange" end - it "works when #method is overriden" do - myobj = MethodOverrideObject.new - expect { - myobj.should == myobj - }.to_not raise_error + context "when #method is overriden" do + subject(:myobj) { MethodOverrideObject.new } + it { expect { should == myobj }.to_not raise_error } end - it "works when implemented via method_missing" do - obj = Object.new + context "when implemented via method_missing" do + let(:obj) { Object.new } + subject(:myobj) { MethodMissingObject.new(obj) } - myobj = MethodMissingObject.new(obj) - (myobj.should == obj).nil? # just to avoid `useless use of == in void context` warning - myobj.should_not == Object.new + it { should == obj } + it { should_not == Object.new } end end describe "unsupported operators" do + subject { "apple" } + it "raises an appropriate error for should != expected" do expect { - "apple".should != "pear" + should != "pear" }.to raise_error(/does not support `should != expected`. Use `should_not == expected`/) end it "raises an appropriate error for should_not != expected" do expect { - "apple".should_not != "pear" + should_not != "pear" }.to raise_error(/does not support `should_not != expected`. Use `should == expected`/) end it "raises an appropriate error for should !~ expected" do expect { - "apple".should !~ /regex/ + should !~ /regex/ }.to raise_error(/does not support `should !~ expected`. Use `should_not =~ expected`/) end it "raises an appropriate error for should_not !~ expected" do expect { - "apple".should_not !~ /regex/ + should_not !~ /regex/ }.to raise_error(/does not support `should_not !~ expected`. Use `should =~ expected`/) end end describe "should_not ==" do + subject { "orange" } + it "delegates message to target" do - subject = "orange".dup expect(subject).to receive(:==).with("apple").and_return(false) - subject.should_not == "apple" + should_not == "apple" end - it "returns true on success" do - subject = "apple" - (subject.should_not == "orange").should be_falsey + it "returns false on success" do + expect(should_not == "apple").to be(false) end - it "fails when target.==(actual) returns false" do - subject = "apple" - expect(RSpec::Expectations).to receive(:fail_with).with(%(expected not: == "apple"\n got: "apple"), "apple", "apple") - subject.should_not == "apple" + it "fails when target.==(actual) returns true" do + expect(RSpec::Expectations).to receive(:fail_with).with(%(expected not: == "orange"\n got: "orange"), "orange", "orange") + should_not == "orange" end end describe "should ===" do + subject { "apple" } + it "delegates message to target" do - subject = "apple".dup expect(subject).to receive(:===).with("apple").and_return(true) - subject.should === "apple" + should === "apple" end it "fails when target.===(actual) returns false" do - subject = "apple".dup expect(subject).to receive(:===).with("orange").and_return(false) expect(RSpec::Expectations).to receive(:fail_with).with(%{expected: "orange"\n got: "apple" (using ===)}, "orange", "apple") - subject.should === "orange" + should === "orange" end end describe "should_not ===" do + subject { "apple" } + it "delegates message to target" do - subject = "orange".dup expect(subject).to receive(:===).with("apple").and_return(false) - subject.should_not === "apple" + should_not === "apple" end - it "fails when target.===(actual) returns false" do - subject = "apple".dup + it "fails when target.===(actual) returns true" do expect(subject).to receive(:===).with("apple").and_return(true) expect(RSpec::Expectations).to receive(:fail_with).with(%(expected not: === "apple"\n got: "apple"), "apple", "apple") - subject.should_not === "apple" + should_not === "apple" end end describe "should =~" do + subject { "foo" } + it "delegates message to target" do - subject = "foo".dup expect(subject).to receive(:=~).with(/oo/).and_return(true) - subject.should =~ /oo/ + should =~ /oo/ end it "fails when target.=~(actual) returns false" do - subject = "fu".dup - expect(subject).to receive(:=~).with(/oo/).and_return(false) - expect(RSpec::Expectations).to receive(:fail_with).with(%{expected: /oo/\n got: "fu" (using =~)}, /oo/, "fu") - subject.should =~ /oo/ + expect(RSpec::Expectations).to receive(:fail_with).with(%{expected: /fu/\n got: "foo" (using =~)}, /fu/, "foo") + should =~ /fu/ end end describe "should_not =~" do + subject { "foo" } + it "delegates message to target" do - subject = "fu".dup - expect(subject).to receive(:=~).with(/oo/).and_return(false) - subject.should_not =~ /oo/ + expect(subject).to receive(:=~).with(/fu/).and_return(false) + should_not =~ /fu/ end it "fails when target.=~(actual) returns false" do - subject = "foo".dup - expect(subject).to receive(:=~).with(/oo/).and_return(true) expect(RSpec::Expectations).to receive(:fail_with).with(%(expected not: =~ /oo/\n got: "foo"), /oo/, "foo") - subject.should_not =~ /oo/ + should_not =~ /oo/ end end describe "should >" do + subject { 4 } + it "passes if > passes" do - 4.should > 3 + should > 3 end it "fails if > fails" do expect(RSpec::Expectations).to receive(:fail_with).with("expected: > 5\n got: 4", 5, 4) - 4.should > 5 + should > 5 end end describe "should >=" do + subject { 4 } + it "passes if actual == expected" do - 4.should >= 4 + should >= 4 end it "passes if actual > expected" do - 4.should >= 3 + should >= 3 end it "fails if > fails" do expect(RSpec::Expectations).to receive(:fail_with).with("expected: >= 5\n got: 4", 5, 4) - 4.should >= 5 + should >= 5 end end describe "should <" do + subject { 4 } + it "passes if < passes" do - 4.should < 5 + should < 5 end it "fails if > fails" do expect(RSpec::Expectations).to receive(:fail_with).with("expected: < 3\n got: 4", 3, 4) - 4.should < 3 + should < 3 end end describe "should <=" do + subject { 4 } + it "passes if actual == expected" do - 4.should <= 4 + should <= 4 end it "passes if actual < expected" do - 4.should <= 5 + should <= 5 end it "fails if > fails" do expect(RSpec::Expectations).to receive(:fail_with).with("expected: <= 3\n got: 4", 3, 4) - 4.should <= 3 + should <= 3 end end @@ -228,22 +232,20 @@ def method_missing(name, *args, &block) end describe RSpec::Matchers::BuiltIn::PositiveOperatorMatcher do + subject(:o) { Object.new } + it "works when the target has implemented #send" do - o = Object.new def o.send(*_args); raise "DOH! Library developers shouldn't use #send!" end - expect { - o.should == o - }.not_to raise_error + expect { should == o }.not_to raise_error end end describe RSpec::Matchers::BuiltIn::NegativeOperatorMatcher do + subject(:o) { Object.new } + it "works when the target has implemented #send" do - o = Object.new def o.send(*_args); raise "DOH! Library developers shouldn't use #send!" end - expect { - o.should_not == :foo - }.not_to raise_error + expect { should_not == :foo }.not_to raise_error end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6934bc9a1..a2c2ece27 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -39,8 +39,6 @@ def hash_inspect(hash) config.include RSpec::Support::InSubProcess config.expect_with :rspec do |expectations| - $default_expectation_syntax = expectations.syntax # rubocop:disable Style/GlobalVars - expectations.syntax = :expect expectations.include_chain_clauses_in_custom_matcher_descriptions = true expectations.strict_predicate_matchers = true end @@ -49,8 +47,6 @@ def hash_inspect(hash) mocks.verify_partial_doubles = true end - config.disable_monkey_patching! - # We don't want rspec-core to look in our `lib` for failure snippets. # When it does that, it inevitably finds this line: # `RSpec::Support.notify_failure(RSpec::Expectations::ExpectationNotMetError.new message)` @@ -59,46 +55,6 @@ def hash_inspect(hash) config.project_source_dirs -= ["lib"] end -RSpec.shared_context "with #should enabled", :uses_should do - orig_syntax = nil - - before(:all) do - orig_syntax = RSpec::Matchers.configuration.syntax - RSpec::Matchers.configuration.syntax = [:expect, :should] - end - - after(:context) do - RSpec::Matchers.configuration.syntax = orig_syntax - end -end - -RSpec.shared_context "with the default expectation syntax" do - orig_syntax = nil - - before(:context) do - orig_syntax = RSpec::Matchers.configuration.syntax - RSpec::Matchers.configuration.reset_syntaxes_to_default - end - - after(:context) do - RSpec::Matchers.configuration.syntax = orig_syntax - end - -end - -RSpec.shared_context "with #should exclusively enabled", :uses_only_should do - orig_syntax = nil - - before(:context) do - orig_syntax = RSpec::Matchers.configuration.syntax - RSpec::Matchers.configuration.syntax = :should - end - - after(:context) do - RSpec::Matchers.configuration.syntax = orig_syntax - end -end - RSpec.shared_context "isolate include_chain_clauses_in_custom_matcher_descriptions" do around do |ex| orig = RSpec::Expectations.configuration.include_chain_clauses_in_custom_matcher_descriptions?