From 72e4fd940c467054b44f39fd55ea2906a2cd7d1a Mon Sep 17 00:00:00 2001 From: Phil Pirozhkov Date: Wed, 30 Dec 2020 02:57:52 +0300 Subject: [PATCH] Remove shared_context_metadata_behavior config option Fixes https://github.com/rspec/rspec-core/issues/2832 --- Changelog.md | 2 + .../example_groups/shared_context.feature | 12 ---- .../example_groups/shared_examples.feature | 17 ----- lib/rspec/core/configuration.rb | 54 --------------- .../project_initializer/spec/spec_helper.rb | 7 -- lib/rspec/core/shared_example_group.rb | 22 ------ spec/rspec/core/configuration_spec.rb | 25 ------- spec/rspec/core/example_group_spec.rb | 10 --- spec/rspec/core/metadata_spec.rb | 18 ----- spec/rspec/core/shared_context_spec.rb | 12 ++-- spec/rspec/core/shared_example_group_spec.rb | 67 +------------------ 11 files changed, 10 insertions(+), 236 deletions(-) diff --git a/Changelog.md b/Changelog.md index 5a17cfa747..767b62cc36 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,8 @@ Breaking Changes: * Extract `should` syntax (including the non-monkey-patching one liner). (Phil Pirozhkov, #2803) * Remove globally-exposed DSL (example and shared group methods in the root scope and on Module). (Phil Pirozhkov, #2803) +* Change the default `shared_context_metadata_behavior` to `apply_to_host_groups` + and remove the configuration option. (Phil Pirozhkov, #2834) * Remove `run_all_when_everything_filtered` configuration option. (Phil Pirozhkov, #2845) Enhancements: diff --git a/features/example_groups/shared_context.feature b/features/example_groups/shared_context.feature index 7bea9c31d4..a502934714 100644 --- a/features/example_groups/shared_context.feature +++ b/features/example_groups/shared_context.feature @@ -2,21 +2,9 @@ Feature: shared context Use `shared_context` to define a block that will be evaluated in the context of example groups either locally, using `include_context` in an example group, or globally using `config.include_context`. - When implicitly including shared contexts via matching metadata, the normal way is to define matching metadata on an example group, in which case the context is included in the entire group. However, you also have the option to include it in an individual example instead. RSpec treats every example as having a singleton example group (analogous to Ruby's singleton classes) containing just the one example. - Background: Given a file named "shared_stuff.rb" with: """ruby - RSpec.configure do |rspec| - # This config option will be enabled by default on RSpec 4, - # but for reasons of backwards compatibility, you have to - # set it on RSpec 3. - # - # It causes the host group and examples to inherit metadata - # from the shared context. - rspec.shared_context_metadata_behavior = :apply_to_host_groups - end - RSpec.shared_context "shared stuff", :shared_context => :metadata do before { @some_var = :some_value } def shared_method diff --git a/features/example_groups/shared_examples.feature b/features/example_groups/shared_examples.feature index c63ce45a79..a62009625b 100644 --- a/features/example_groups/shared_examples.feature +++ b/features/example_groups/shared_examples.feature @@ -257,23 +257,6 @@ Feature: shared examples responds to <=> """ - Scenario: Sharing metadata automatically includes shared example groups - Given a file named "shared_example_metadata_spec.rb" with: - """ruby - RSpec.shared_examples "shared stuff", :a => :b do - it 'runs wherever the metadata is shared' do - end - end - - RSpec.describe String, :a => :b do - end - """ - When I run `rspec shared_example_metadata_spec.rb` - Then the output should contain: - """ - 1 example, 0 failures - """ - Scenario: Shared examples are nestable by context Given a file named "context_specific_examples_spec.rb" with: """Ruby diff --git a/lib/rspec/core/configuration.rb b/lib/rspec/core/configuration.rb index d538f38b70..8732923ee3 100644 --- a/lib/rspec/core/configuration.rb +++ b/lib/rspec/core/configuration.rb @@ -362,59 +362,6 @@ def treat_symbols_as_metadata_keys_with_true_values=(_value) ) end - # @macro define_reader - # Configures how RSpec treats metadata passed as part of a shared example - # group definition. For example, given this shared example group definition: - # - # RSpec.shared_context "uses DB", :db => true do - # around(:example) do |ex| - # MyORM.transaction(:rollback => true, &ex) - # end - # end - # - # ...there are two ways RSpec can treat the `:db => true` metadata, each - # of which has a corresponding config option: - # - # 1. `:trigger_inclusion`: this shared context will be implicitly included - # in any groups (or examples) that have `:db => true` metadata. - # 2. `:apply_to_host_groups`: the metadata will be inherited by the metadata - # hash of all host groups and examples. - # - # `:trigger_inclusion` is the legacy behavior from before RSpec 3.5 but should - # be considered deprecated. Instead, you can explicitly include a group with - # `include_context`: - # - # RSpec.describe "My model" do - # include_context "uses DB" - # end - # - # ...or you can configure RSpec to include the context based on matching metadata - # using an API that mirrors configured module inclusion: - # - # RSpec.configure do |rspec| - # rspec.include_context "uses DB", :db => true - # end - # - # `:apply_to_host_groups` is a new feature of RSpec 3.5 and will be the only - # supported behavior in RSpec 4. - # - # @overload shared_context_metadata_behavior - # @return [:trigger_inclusion, :apply_to_host_groups] the configured behavior - # @overload shared_context_metadata_behavior=(value) - # @param value [:trigger_inclusion, :apply_to_host_groups] sets the configured behavior - define_reader :shared_context_metadata_behavior - # @see shared_context_metadata_behavior - def shared_context_metadata_behavior=(value) - case value - when :trigger_inclusion, :apply_to_host_groups - @shared_context_metadata_behavior = value - else - raise ArgumentError, "Cannot set `RSpec.configuration." \ - "shared_context_metadata_behavior` to `#{value.inspect}`. Only " \ - "`:trigger_inclusion` and `:apply_to_host_groups` are valid values." - end - end - # Record the start time of the spec suite to measure load time. # return [Time] add_setting :start_time @@ -530,7 +477,6 @@ def initialize @threadsafe = true @max_displayed_failure_line_count = 10 @world = World::Null - @shared_context_metadata_behavior = :trigger_inclusion define_built_in_hooks end diff --git a/lib/rspec/core/project_initializer/spec/spec_helper.rb b/lib/rspec/core/project_initializer/spec/spec_helper.rb index 63bdc7686f..6290058689 100644 --- a/lib/rspec/core/project_initializer/spec/spec_helper.rb +++ b/lib/rspec/core/project_initializer/spec/spec_helper.rb @@ -37,13 +37,6 @@ mocks.verify_partial_doubles = true end - # This option will default to `:apply_to_host_groups` in RSpec 4 (and will - # have no way to turn it off -- the option exists only for backwards - # compatibility in RSpec 3). It causes shared context metadata to be - # inherited by the metadata hash of host groups and examples, rather than - # triggering implicit auto-inclusion in groups with matching metadata. - config.shared_context_metadata_behavior = :apply_to_host_groups - # The settings below are suggested to provide a good initial experience # with RSpec, but feel free to customize to your heart's content. =begin diff --git a/lib/rspec/core/shared_example_group.rb b/lib/rspec/core/shared_example_group.rb index 1bccff73be..4871d3f940 100644 --- a/lib/rspec/core/shared_example_group.rb +++ b/lib/rspec/core/shared_example_group.rb @@ -125,10 +125,6 @@ def add(context, name, *metadata_args, &block) "block or remove the definition." end - if RSpec.configuration.shared_context_metadata_behavior == :trigger_inclusion - return legacy_add(context, name, *metadata_args, &block) - end - unless valid_name?(name) raise ArgumentError, "Shared example group names can only be a string, " \ "symbol or module but got: #{name.inspect}" @@ -152,24 +148,6 @@ def find(lookup_contexts, name) private - # TODO: remove this in RSpec 4. This exists only to support - # `config.shared_context_metadata_behavior == :trigger_inclusion`, - # the legacy behavior of shared context metadata, which we do - # not want to support in RSpec 4. - def legacy_add(context, name, *metadata_args, &block) - shared_module = SharedExampleGroupModule.new(name, block, {}) - - if valid_name?(name) - warn_if_key_taken context, name, block - shared_example_groups[context][name] = shared_module - else - metadata_args.unshift name - end - - return if metadata_args.empty? - RSpec.configuration.include shared_module, *metadata_args - end - def shared_example_groups @shared_example_groups ||= Hash.new { |hash, context| hash[context] = {} } end diff --git a/spec/rspec/core/configuration_spec.rb b/spec/rspec/core/configuration_spec.rb index 422ea469d9..7cafb376e0 100644 --- a/spec/rspec/core/configuration_spec.rb +++ b/spec/rspec/core/configuration_spec.rb @@ -2758,31 +2758,6 @@ def strategy.order(list) end end - describe "#shared_context_metadata_behavior" do - it "defaults to :trigger_inclusion for backwards compatibility" do - expect(config.shared_context_metadata_behavior).to eq :trigger_inclusion - end - - it "can be set to :apply_to_host_groups" do - config.shared_context_metadata_behavior = :apply_to_host_groups - expect(config.shared_context_metadata_behavior).to eq :apply_to_host_groups - end - - it "can be set to :trigger_inclusion explicitly" do - config.shared_context_metadata_behavior = :trigger_inclusion - expect(config.shared_context_metadata_behavior).to eq :trigger_inclusion - end - - it "cannot be set to any other values" do - expect { - config.shared_context_metadata_behavior = :another_value - }.to raise_error(ArgumentError, a_string_including( - "shared_context_metadata_behavior", - ":another_value", ":trigger_inclusion", ":apply_to_host_groups" - )) - end - end - # assigns files_or_directories_to_run and triggers post-processing # via `files_to_run`. def assign_files_or_directories_to_run(*value) diff --git a/spec/rspec/core/example_group_spec.rb b/spec/rspec/core/example_group_spec.rb index b07a5e4334..c4f92076e6 100644 --- a/spec/rspec/core/example_group_spec.rb +++ b/spec/rspec/core/example_group_spec.rb @@ -149,16 +149,6 @@ def metadata_hash(*args) }.to raise_error(/ExampleGroups::CallingAnUndefinedMethod/) end - it "assigns the const before including shared contexts via metadata so error messages from eval'ing the context include the name" do - RSpec.shared_context("foo", :foo) { bar } - - expect { - RSpec.describe("Including shared context via metadata", :foo) - }.to raise_error(NameError, - a_string_including('ExampleGroups::IncludingSharedContextViaMetadata', 'bar') - ) - end - it 'does not have problems with example groups named "Core"' do RSpec.describe("Core") expect(defined?(::RSpec::ExampleGroups::Core)).to be diff --git a/spec/rspec/core/metadata_spec.rb b/spec/rspec/core/metadata_spec.rb index 9cebe65ce2..bf72dcf62f 100644 --- a/spec/rspec/core/metadata_spec.rb +++ b/spec/rspec/core/metadata_spec.rb @@ -310,24 +310,6 @@ def metadata_for(*args) end end - context "generated by an unnested shared group included via metadata" do - it "is an array containing an object with shared group name and inclusion location" do - meta = nil - - RSpec.shared_examples_for("some shared behavior", :include_it => true) do - meta = example { }.metadata - end - - line = __LINE__ + 1 - RSpec.describe("Group", :include_it => true) { } - - expect(meta[:shared_group_inclusion_backtrace]).to match [ an_object_having_attributes( - :shared_group_name => "some shared behavior", - :inclusion_location => a_string_including("#{Metadata.relative_path __FILE__}:#{line}") - ) ] - end - end - { :it_behaves_like => "generates a nested group", :include_examples => "adds the examples directly to the host group" diff --git a/spec/rspec/core/shared_context_spec.rb b/spec/rspec/core/shared_context_spec.rb index 133fce977c..f307328b24 100644 --- a/spec/rspec/core/shared_context_spec.rb +++ b/spec/rspec/core/shared_context_spec.rb @@ -36,15 +36,17 @@ it "runs the before each hooks in configuration before those of the shared context" do ordered_hooks = [] - RSpec.configure do |c| - c.before(:each) { ordered_hooks << "config" } - end - RSpec.shared_context("before each stuff", :example => :before_each_hook_order) do + RSpec.shared_context("before each stuff") do before(:each) { ordered_hooks << "shared_context"} end - group = RSpec.describe "description", :example => :before_each_hook_order do + RSpec.configure do |c| + c.before(:each) { ordered_hooks << "config" } + c.include_context "before each stuff" + end + + group = RSpec.describe "description" do before(:each) { ordered_hooks << "example_group" } example {} end diff --git a/spec/rspec/core/shared_example_group_spec.rb b/spec/rspec/core/shared_example_group_spec.rb index db95bd76b5..6d38eaee22 100644 --- a/spec/rspec/core/shared_example_group_spec.rb +++ b/spec/rspec/core/shared_example_group_spec.rb @@ -40,10 +40,6 @@ module Core describe shared_method_name do let(:group) { RSpec.describe('example group') } - before do - RSpec.configuration.shared_context_metadata_behavior = :apply_to_host_groups - end - define_method :define_shared_group do |*args, &block| group.send(shared_method_name, *args, &block) end @@ -179,62 +175,7 @@ def find_implementation_block(registry, scope, name) end end - context "when `config.shared_context_metadata_behavior == :trigger_inclusion`" do - before do - RSpec.configuration.shared_context_metadata_behavior = :trigger_inclusion - end - - context "given a hash" do - it "includes itself in matching example groups" do - implementation = Proc.new { def self.bar; 'bar'; end } - define_shared_group(:foo => :bar, &implementation) - - matching_group = RSpec.describe "Group", :foo => :bar - non_matching_group = RSpec.describe "Group" - - expect(matching_group.bar).to eq("bar") - expect(non_matching_group).not_to respond_to(:bar) - end - end - - context "given a string and a hash" do - it "captures the given string and block in the World's collection of shared example groups" do - implementation = lambda { } - define_shared_group("name", :foo => :bar, &implementation) - expect(find_implementation_block(registry, group, "name")).to eq implementation - end - - it "delegates include on configuration" do - implementation = Proc.new { def self.bar; 'bar'; end } - define_shared_group("name", :foo => :bar, &implementation) - - matching_group = RSpec.describe "Group", :foo => :bar - non_matching_group = RSpec.describe "Group" - - expect(matching_group.bar).to eq("bar") - expect(non_matching_group).not_to respond_to(:bar) - end - end - - it "displays a warning when adding a second shared example group with the same name" do - group.send(shared_method_name, 'some shared group') {} - original_declaration = [__FILE__, __LINE__ - 1].join(':') - - warning = nil - allow(::Kernel).to receive(:warn) { |msg| warning = msg } - - group.send(shared_method_name, 'some shared group') {} - second_declaration = [__FILE__, __LINE__ - 1].join(':') - expect(warning).to include('some shared group', original_declaration, second_declaration) - expect(warning).to_not include 'Called from' - end - end - - context "when `config.shared_context_metadata_behavior == :apply_to_host_groups`" do - before do - RSpec.configuration.shared_context_metadata_behavior = :apply_to_host_groups - end - + describe "metadata" do it "does not auto-include the shared group based on passed metadata" do define_top_level_shared_group("name", :foo => :bar) do def self.bar; 'bar'; end @@ -338,12 +279,6 @@ def self.bar; 'bar'; end end context "when the group is included via `config.include_context` and matching metadata" do - before do - # To ensure we don't accidentally include shared contexts the - # old way in this context, we disable the option here. - RSpec.configuration.shared_context_metadata_behavior = :apply_to_host_groups - end - describe "when it has a `let` and applies to an individual example via metadata" do it 'defines the `let` method correctly' do define_top_level_shared_group("name") do