Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove shared_context_metadata_behavior config option and make apply_to_host_groups the default #2834

Merged
merged 1 commit into from
Jan 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
12 changes: 0 additions & 12 deletions features/example_groups/shared_context.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 0 additions & 17 deletions features/example_groups/shared_examples.feature
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
54 changes: 0 additions & 54 deletions lib/rspec/core/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 0 additions & 7 deletions lib/rspec/core/project_initializer/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 0 additions & 22 deletions lib/rspec/core/shared_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand All @@ -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
Expand Down
25 changes: 0 additions & 25 deletions spec/rspec/core/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 0 additions & 10 deletions spec/rspec/core/example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 0 additions & 18 deletions spec/rspec/core/metadata_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 7 additions & 5 deletions spec/rspec/core/shared_context_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 1 addition & 66 deletions spec/rspec/core/shared_example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down