Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Add helpful warning message for shared example groups #2278

Merged
merged 1 commit into from
Jul 7, 2016
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
33 changes: 24 additions & 9 deletions lib/rspec/core/shared_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -213,20 +213,35 @@ def valid_name?(candidate)

def warn_if_key_taken(context, key, new_block)
existing_module = shared_example_groups[context][key]

return unless existing_module

RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil
|WARNING: Shared example group '#{key}' has been previously defined at:
| #{formatted_location existing_module.definition}
|...and you are now defining it at:
| #{formatted_location new_block}
|The new definition will overwrite the original one.
WARNING
old_definition_location = formatted_location existing_module.definition
new_definition_location = formatted_location new_block
loaded_spec_files = RSpec.configuration.loaded_spec_files

if loaded_spec_files.include?(new_definition_location) && old_definition_location == new_definition_location
RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil
|WARNING: Your shared example group, '#{key}', defined at:
| #{old_definition_location}
|was automatically loaded by RSpec because the file name
|matches the configured autoloading pattern (#{RSpec.configuration.pattern}),
|and is also being required from somewhere else. To fix this
|warning, either rename the file to not match the pattern, or
|do not explicitly require the file.
WARNING
else
RSpec.warn_with <<-WARNING.gsub(/^ +\|/, ''), :call_site => nil
|WARNING: Shared example group '#{key}' has been previously defined at:
| #{old_definition_location}
|...and you are now defining it at:
| #{new_definition_location}
|The new definition will overwrite the original one.
WARNING
end
end

def formatted_location(block)
block.source_location.join ":"
block.source_location.join(":").gsub(/:in.*$/, '')
end

if Proc.method_defined?(:source_location)
Expand Down
18 changes: 17 additions & 1 deletion spec/rspec/core/shared_example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def find_implementation_block(registry, scope, name)
expect(Kernel).to_not respond_to(shared_method_name)
end

it "displays a warning when adding a second shared example group with the same name" do
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(':')

Expand All @@ -82,6 +82,22 @@ def find_implementation_block(registry, scope, name)
expect(warning).to_not include 'Called from'
end

it 'displays a helpful message when you define a shared example group in *_spec.rb file' do
warning = nil
allow(::Kernel).to receive(:warn) { |msg| warning = msg }
declaration = nil

2.times do
group.send(shared_method_name, 'some shared group') {}
declaration = [__FILE__, __LINE__ - 1].join(':')
RSpec.configuration.loaded_spec_files << declaration
end

better_error = 'was automatically loaded by RSpec because the file name'
expect(warning).to include('some shared group', declaration, better_error)
expect(warning).to_not include 'Called from'
end

it 'works with top level defined examples in modules' do
expect(RSpec::configuration.reporter).to_not receive(:deprecation)
RSpec.describe('example group') { include_context 'top level in module' }
Expand Down