From 7adf2f08609ab3e7851cfbb018b829aa9f8db94a Mon Sep 17 00:00:00 2001 From: Phil Pirozhkov Date: Fri, 12 Mar 2021 00:38:38 +0300 Subject: [PATCH] Add RSpec 4 deprecation warnings See https://github.com/rspec/rspec/issues/61 --- Changelog.md | 4 +++ lib/rspec/core/configuration.rb | 33 +++++++++++++++++++---- lib/rspec/core/dsl.rb | 5 +++- lib/rspec/core/example.rb | 1 + lib/rspec/core/example_group.rb | 9 ++++++- lib/rspec/core/filter_manager.rb | 9 +++++++ lib/rspec/core/memoized_helpers.rb | 2 ++ spec/rspec/core/configuration_spec.rb | 34 ++++++++++++++++++++++++ spec/rspec/core/dsl_spec.rb | 15 +++++++++++ spec/rspec/core/example_group_spec.rb | 8 ++++++ spec/rspec/core/example_spec.rb | 6 +++++ spec/rspec/core/memoized_helpers_spec.rb | 2 ++ 12 files changed, 121 insertions(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index 1fd2766623..fc18bcc0d0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,10 @@ Bug fixes: * Fix exception presenter when the root cause exception has nil backtrace. (Zinovyev Ivan, #2903) +Deprecations: + +* Add RSpec 4 deprecation warnings. (Phil Pirozhkov, #2880) + ### 3.10.1 / 2020-12-27 [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.10.0...v3.10.1) diff --git a/lib/rspec/core/configuration.rb b/lib/rspec/core/configuration.rb index bb38a8de4f..4d259d3b8e 100644 --- a/lib/rspec/core/configuration.rb +++ b/lib/rspec/core/configuration.rb @@ -327,7 +327,11 @@ def exclude_pattern=(value) # (default: `false`). # @deprecated Use {#filter_run_when_matching} instead for the specific # filters that you want to be ignored if none match. - add_setting :run_all_when_everything_filtered + def run_all_when_everything_filtered=(value) + RSpec.deprecate("`run_all_when_everything_filtered` setting", :replacement => "`filter_run_when_matching :focus`") + @run_all_when_everything_filtered = value + end + add_read_only_setting :run_all_when_everything_filtered # @macro add_setting # Color to use to indicate success. Defaults to `:green` but can be set @@ -440,6 +444,11 @@ def shared_context_metadata_behavior=(value) "shared_context_metadata_behavior` to `#{value.inspect}`. Only " \ "`:trigger_inclusion` and `:apply_to_host_groups` are valid values." end + + if value == :trigger_inclusion + RSpec.deprecate("`shared_context_metadata_behavior` setting", + :message => "`:apply_to_host_groups` will become the default and only option.") + end end # Record the start time of the spec suite to measure load time. @@ -492,7 +501,12 @@ def bisect_runner=(value) # @private # @deprecated Use {#color_mode} = :on, instead of {#color} with {#tty} - add_setting :tty + def tty=(value) + RSpec.deprecate("`tty` setting", :replacement => "`color_mode`") + @tty = value + end + add_read_only_setting :tty + # @private attr_writer :files_to_run # @private @@ -933,8 +947,11 @@ def color_enabled?(output=output_stream) # # @deprecated No longer recommended because of complex behavior. Instead, # rely on the fact that TTYs will display color by default, or set - # {:color_mode} to :on to display color on a non-TTY output. - attr_writer :color + # {#color_mode} to :on to display color on a non-TTY output. + def color=(value) + RSpec.deprecate("`color` setting", :replacement => "`color_mode`") + @color = value + end # @private def libs=(libs) @@ -1217,7 +1234,13 @@ def alias_example_group_to(new_name, *args) def alias_it_behaves_like_to(new_name, report_label='') RSpec::Core::ExampleGroup.define_nested_shared_group_method(new_name, report_label) end - alias_method :alias_it_should_behave_like_to, :alias_it_behaves_like_to + + # Alias for `alias_it_behaves_like_to`. + # @deprecated Use {#alias_it_behaves_like_to} instead. + def alias_it_should_behave_like_to(new_name, report_label='') + RSpec.deprecate("`alias_it_should_behave_like_to`", :replacement => "`alias_it_behaves_like_to`") + alias_it_behaves_like_to(new_name, report_label) + end # Adds key/value pairs to the `inclusion_filter`. If `args` # includes any symbols that are not part of the hash, each symbol diff --git a/lib/rspec/core/dsl.rb b/lib/rspec/core/dsl.rb index 220403e6e3..b233ae4460 100644 --- a/lib/rspec/core/dsl.rb +++ b/lib/rspec/core/dsl.rb @@ -81,7 +81,10 @@ def self.remove_globally! def self.expose_example_group_alias_globally(method_name) change_global_dsl do remove_method(method_name) if method_defined?(method_name) - define_method(method_name) { |*a, &b| ::RSpec.__send__(method_name, *a, &b) } + define_method(method_name) do |*a, &b| + RSpec.deprecate("Globally-exposed DSL (`#{method_name}`)", :replacement => "`RSpec.#{method_name}`") + ::RSpec.__send__(method_name, *a, &b) + end end end diff --git a/lib/rspec/core/example.rb b/lib/rspec/core/example.rb index d3b891fa92..b08b16a79e 100644 --- a/lib/rspec/core/example.rb +++ b/lib/rspec/core/example.rb @@ -109,6 +109,7 @@ def location_rerun_argument # @note If there are multiple examples identified by this location, they will use {#id} # to rerun instead, but this method will still return the location (that's why it is deprecated!). def rerun_argument + RSpec.deprecate("`rerun_argument`", :replacement => "`location_rerun_argument`") location_rerun_argument end diff --git a/lib/rspec/core/example_group.rb b/lib/rspec/core/example_group.rb index 5efee9f386..760ce1145a 100644 --- a/lib/rspec/core/example_group.rb +++ b/lib/rspec/core/example_group.rb @@ -316,6 +316,8 @@ def self.define_example_group_method(name, metadata={}) # @see SharedExampleGroup def self.define_nested_shared_group_method(new_name, report_label="it should behave like") idempotently_define_singleton_method(new_name) do |name, *args, &customization_block| + yield if block_given? # to print a deprecation warning for it_should_behave_like usage + # Pass :caller so the :location metadata is set properly. # Otherwise, it'll be set to the next line because that's # the block's source_location. @@ -332,7 +334,9 @@ def self.define_nested_shared_group_method(new_name, report_label="it should beh define_nested_shared_group_method :it_behaves_like, "behaves like" # Generates a nested example group and includes the shared content # mapped to `name` in the nested group. - define_nested_shared_group_method :it_should_behave_like + define_nested_shared_group_method(:it_should_behave_like) do + RSpec.deprecate("`it_should_behave_like`", :replacement => "`it_behaves_like`") + end # Includes shared content mapped to `name` directly in the group in which # it is declared, as opposed to `it_behaves_like`, which creates a nested @@ -517,6 +521,9 @@ def self.top_level? # @private def self.ensure_example_groups_are_configured unless defined?(@@example_groups_configured) + unless RSpec.configuration.disable_monkey_patching + RSpec.deprecate("Monkey-patching mode", :call_site => nil) + end RSpec.configuration.configure_mock_framework RSpec.configuration.configure_expectation_framework # rubocop:disable Style/ClassVars diff --git a/lib/rspec/core/filter_manager.rb b/lib/rspec/core/filter_manager.rb index 7fe6cb18d2..1dadb03da4 100644 --- a/lib/rspec/core/filter_manager.rb +++ b/lib/rspec/core/filter_manager.rb @@ -89,6 +89,15 @@ def add_path_to_arrays_filter(filter_key, path, values) def prune_conditionally_filtered_examples(examples) examples.reject do |ex| meta = ex.metadata + if meta.key?(:if) + RSpec.deprecate("`:if` metadata will have no special meaning in RSpec 4 and", + :replacement => "`:skip` with a negated condition", + :call_site => meta[:location]) + end + if meta.key?(:unless) + RSpec.deprecate("`:unless` metadata will have no special meaning in RSpec 4 and", + :replacement => "`:skip`") + end !meta.fetch(:if, true) || meta[:unless] end end diff --git a/lib/rspec/core/memoized_helpers.rb b/lib/rspec/core/memoized_helpers.rb index adcfce7af3..4049f5c11f 100644 --- a/lib/rspec/core/memoized_helpers.rb +++ b/lib/rspec/core/memoized_helpers.rb @@ -78,6 +78,7 @@ def subject # @note If you are using RSpec's newer expect-based syntax you may # want to use `is_expected.to` instead of `should`. def should(matcher=nil, message=nil) + RSpec.deprecate("Monkey-patching `should`", :replacement => "RSpec Expectations' `is_expected.to`") enforce_value_expectation(matcher, 'should') RSpec::Expectations::PositiveExpectationHandler.handle_matcher(subject, matcher, message) end @@ -98,6 +99,7 @@ def should(matcher=nil, message=nil) # @note If you are using RSpec's newer expect-based syntax you may # want to use `is_expected.to_not` instead of `should_not`. def should_not(matcher=nil, message=nil) + RSpec.deprecate("Monkey-patching `should_not`", :replacement => "RSpec Expectations' `is_expected.not_to`") enforce_value_expectation(matcher, 'should_not') RSpec::Expectations::NegativeExpectationHandler.handle_matcher(subject, matcher, message) end diff --git a/spec/rspec/core/configuration_spec.rb b/spec/rspec/core/configuration_spec.rb index 62f709ed97..ecc69e4827 100644 --- a/spec/rspec/core/configuration_spec.rb +++ b/spec/rspec/core/configuration_spec.rb @@ -1306,6 +1306,18 @@ def metadata_hash(*args) config.run_all_when_everything_filtered = true expect(config.run_all_when_everything_filtered?).to be(true) end + + it "emits a deprecation message when set" do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /run_all_when_everything_filtered/) + config.run_all_when_everything_filtered = true + end + end + + describe "#tty=" do + it "emits a deprecation message when set" do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /tty/) + config.tty = true + end end describe "#color_mode" do @@ -1400,6 +1412,11 @@ def metadata_hash(*args) describe "#color=" do before { config.color_mode = :automatic } + it "emits a deprecation message when set" do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /color/) + config.color = true + end + context "given false" do before { config.color = false } @@ -2369,6 +2386,13 @@ class << self end end + describe '#alias_it_should_behave_like_to' do + it "emits a deprecation message when used" do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /alias_it_should_behave_like_to/) + config.alias_it_should_behave_like_to :it_should_have_behaved_like + end + end + it_behaves_like "metadata hash builder" do def metadata_hash(*args) config.alias_example_group_to :my_group_method, *args @@ -2904,6 +2928,16 @@ def emulate_not_configured_expectation_framework ":another_value", ":trigger_inclusion", ":apply_to_host_groups" )) end + + it "emits a deprecation message when set to :trigger_inclusion" do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /shared_context_metadata_behavior/) + config.shared_context_metadata_behavior = :trigger_inclusion + end + + it "does not emit a deprecation message when set to :apply_to_host_groups" do + expect_no_deprecation + config.shared_context_metadata_behavior = :apply_to_host_groups + end end # assigns files_or_directories_to_run and triggers post-processing diff --git a/spec/rspec/core/dsl_spec.rb b/spec/rspec/core/dsl_spec.rb index cb204f7a8a..7a33183876 100644 --- a/spec/rspec/core/dsl_spec.rb +++ b/spec/rspec/core/dsl_spec.rb @@ -27,6 +27,21 @@ def enable expect(Object.new).not_to respond_to(*method_names) end end + + it 'emits a deprecation warning' do + in_sub_process do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 6, /Globally-exposed DSL \(`describe`\)/) + changing_expose_dsl_globally do + RSpec.configuration.expose_dsl_globally = true + expect(RSpec.configuration.expose_dsl_globally?).to eq true + + Module.new do + describe 'monkey' do + end + end + end + end + end end context "when expose_dsl_globally is disabled" do diff --git a/spec/rspec/core/example_group_spec.rb b/spec/rspec/core/example_group_spec.rb index ec4cc26d73..749e341827 100644 --- a/spec/rspec/core/example_group_spec.rb +++ b/spec/rspec/core/example_group_spec.rb @@ -1883,6 +1883,14 @@ def foo; end end }.to raise_error("boom").and avoid_changing(RSpec::Support, :thread_local_data) end + + it "emits a deprecation warning when used" do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 3, /it_should_behave_like/) + RSpec.describe do + shared_examples_for("stuff") { } + it_should_behave_like "stuff" + end + end end it 'minimizes the number of methods that users could inadvertantly overwrite' do diff --git a/spec/rspec/core/example_spec.rb b/spec/rspec/core/example_spec.rb index c7ecb9ef36..32f3405f1d 100644 --- a/spec/rspec/core/example_spec.rb +++ b/spec/rspec/core/example_spec.rb @@ -38,6 +38,12 @@ def metadata_hash(*args) example = RSpec.describe.example expect(example.rerun_argument).to eq("#{RSpec::Core::Metadata.relative_path(__FILE__)}:#{__LINE__ - 1}") end + + it "emits a deprecation warning when used" do + example = RSpec.describe.example + expect_deprecation_with_call_site(__FILE__, __LINE__ + 1, /rerun_argument/) + example.rerun_argument + end end describe "#update_inherited_metadata" do diff --git a/spec/rspec/core/memoized_helpers_spec.rb b/spec/rspec/core/memoized_helpers_spec.rb index 0b220c3c95..bb12d2f852 100644 --- a/spec/rspec/core/memoized_helpers_spec.rb +++ b/spec/rspec/core/memoized_helpers_spec.rb @@ -660,11 +660,13 @@ def supports_value_expectations? subject { 'value or a Proc' } it '`should` prints a deprecation warning when given a value' do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 2, /Monkey-patching `should`/) expect_warn_deprecation(/The implicit block expectation syntax is deprecated, you should pass/) expect { should block_matcher }.not_to raise_error end it '`should_not` prints a deprecation warning when given a value' do + expect_deprecation_with_call_site(__FILE__, __LINE__ + 2, /Monkey-patching `should_not`/) expect_warn_deprecation(/The implicit block expectation syntax is deprecated, you should pass/) expect { should_not block_matcher }.to raise_error(Exception) end