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

Extract warning methods into module #40

Merged
merged 2 commits into from
Feb 20, 2014
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
62 changes: 28 additions & 34 deletions lib/rspec/support/warnings.rb
Original file line number Diff line number Diff line change
@@ -1,42 +1,36 @@
module RSpec
module Support
module Warnings
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming this has something to do with the core PR @samphippen mentioned, but currently this can't be merged with this removal, as core has different implementations of these methods and this check is to prevent support overriding core's implementation.

def deprecate(deprecated, options = {})
warn_with "DEPRECATION: #{deprecated} is deprecated.", options
end

unless respond_to?(:deprecate)
# @private
#
# Used internally to print deprecation warnings
# when rspec-core isn't loaded
def warn_deprecation(message)
warn_with "DEPRECATION: \n #{message}"
end

# @private
#
# Used internally to print deprecation warnings
# when rspec-core isn't loaded
def self.deprecate(deprecated, options = {})
warn_with "DEPRECATION: #{deprecated} is deprecated.", options
end
end
# @private
#
# Used internally to print warnings
def warning(text, options={})
warn_with "WARNING: #{text}.", options
end

unless respond_to?(:warn_deprecation)

# @private
#
# Used internally to print deprecation warnings
# when rspec-core isn't loaded
def self.warn_deprecation(message)
warn_with "DEPRECATION: \n #{message}"
# @private
#
# Used internally to print longer warnings
def warn_with(message, options = {})
call_site = options.fetch(:call_site) { CallerFilter.first_non_rspec_line }
message << " Use #{options[:replacement]} instead." if options[:replacement]
message << " Called from #{call_site}." if call_site
::Kernel.warn message
end
end
end

# @private
#
# Used internally to print warnings
def self.warning(text, options={})
warn_with "WARNING: #{text}.", options
end

# @private
#
# Used internally to print longer warnings
def self.warn_with(message, options = {})
call_site = options.fetch(:call_site) { CallerFilter.first_non_rspec_line }
message << " Use #{options[:replacement]} instead." if options[:replacement]
message << " Called from #{call_site}." if call_site
::Kernel.warn message
end

extend RSpec::Support::Warnings
end
103 changes: 19 additions & 84 deletions spec/rspec/support/warnings_spec.rb
Original file line number Diff line number Diff line change
@@ -1,113 +1,48 @@
require "spec_helper"
require 'rspec/support/spec/in_sub_process'

# RSpec Core has already loaded these, we wish to test there
# definition so we undefine them first.
module RSpec
class << self
undef deprecate if defined?(RSpec.deprecate)
undef warn_deprecation if defined?(RSpec.warn_deprecation)
undef warn_with if defined?(RSpec.warn_with)
undef warning if defined?(RSpec.warning)
end
end
require "rspec/support/warnings"

describe "rspec warnings and deprecations" do
include RSpec::Support::InSubProcess

def run_with_rspec_core
in_sub_process do
load 'rspec/core/warnings.rb'
yield
end
end

def run_without_rspec_core
in_sub_process do
load 'rspec/support/warnings.rb'
yield
end
end

context "when rspec-core is available" do
describe "#deprecate" do
it "passes the hash to the reporter" do
run_with_rspec_core do
expect(RSpec.configuration.reporter).to receive(:deprecation).with(hash_including :deprecated => "deprecated_method", :replacement => "replacement")
RSpec.deprecate("deprecated_method", :replacement => "replacement")
end
end

it "adds the call site" do
run_with_rspec_core do
expect_deprecation_with_call_site(__FILE__, __LINE__ + 1)
RSpec.deprecate("deprecated_method")
end
end

it "doesn't override a passed call site" do
run_with_rspec_core do
expect_deprecation_with_call_site("some_file.rb", 17)
RSpec.deprecate("deprecated_method", :call_site => "/some_file.rb:17")
end
end
end

describe "#warn_deprecation" do
it "puts message in a hash" do
run_with_rspec_core do
expect(RSpec.configuration.reporter).to receive(:deprecation).with(hash_including :message => "this is the message")
RSpec.warn_deprecation("this is the message")
end
end
end
end
subject(:warning_object) {
Object.new.tap {|o| o.extend(RSpec::Support::Warnings)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We tend to use do/end for multiline blocks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, could this not just be a plain let?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be, but it is the subject of the test, so named subject makes more sense IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except subject is intended for one liners which you're not using, and explicit subject is a bit of a smell, so in general when a vanilla let can be used I favour it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely disagree. Just because it works for one liners does not mean it shouldn't be used elsewhere. Specifically I think it draws attention to the actual object under test, as opposed to collaborators.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do indeed disagree. I prefer to let my docstrings and let names explain what's under test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to say I agree with @samphippen subject distinguishes the object from the other collaborators. While it isn't absolutely necessary I think it's a nice hint.

}

context "when rspec-core is not available" do
shared_examples_for "falling back to Kernel.warn" do |args|
let(:method_name) { args.fetch(:method_name) }

shared_examples_for "falls back to warn for" do |method|
it 'falls back to warning with a plain message' do
run_without_rspec_core do
expect(::Kernel).to receive(:warn).with(/message/)
RSpec.send(method,'message')
end
expect(::Kernel).to receive(:warn).with(/message/)
warning_object.send(method_name, 'message')
end
end

it_behaves_like 'falls back to warn for', :deprecate
it_behaves_like 'falls back to warn for', :warn_deprecation
it_behaves_like 'falling back to Kernel.warn', :method_name => :deprecate
it_behaves_like 'falling back to Kernel.warn', :method_name => :warn_deprecation
end

shared_examples_for "warning helper" do |helper|
it 'warns with the message text' do
run_without_rspec_core do
expect(::Kernel).to receive(:warn).with(/Message/)
RSpec.send(helper, 'Message')
end
expect(::Kernel).to receive(:warn).with(/Message/)
warning_object.send(helper, 'Message')
end

it 'sets the calling line' do
run_without_rspec_core do
expect(::Kernel).to receive(:warn).with(/#{__FILE__}:#{__LINE__+1}/)
RSpec.send(helper, 'Message')
end
expect(::Kernel).to receive(:warn).with(/#{__FILE__}:#{__LINE__+1}/)
warning_object.send(helper, 'Message')
end

it 'optionally sets the replacement' do
run_without_rspec_core do
expect(::Kernel).to receive(:warn).with(/Use Replacement instead./)
RSpec.send(helper, 'Message', :replacement => 'Replacement')
end
expect(::Kernel).to receive(:warn).with(/Use Replacement instead./)
warning_object.send(helper, 'Message', :replacement => 'Replacement')
end
end

describe "#warning" do
it 'prepends WARNING:' do
run_without_rspec_core do
expect(::Kernel).to receive(:warn).with(/WARNING: Message\./)
RSpec.warning 'Message'
end
expect(::Kernel).to receive(:warn).with(/WARNING: Message\./)
warning_object.warning 'Message'
end

it_should_behave_like 'warning helper', :warning
end

Expand Down