diff --git a/lib/rspec/core/formatters.rb b/lib/rspec/core/formatters.rb index 8ca9112b8a..f0238f85cd 100644 --- a/lib/rspec/core/formatters.rb +++ b/lib/rspec/core/formatters.rb @@ -194,10 +194,16 @@ def register(formatter, notifications) def duplicate_formatter_exists?(new_formatter) @formatters.any? do |formatter| - formatter.class == new_formatter.class && formatter.output == new_formatter.output + formatter.class == new_formatter.class && + has_matching_output?(formatter, new_formatter) end end + def has_matching_output?(formatter, new_formatter) + return true unless formatter.respond_to?(:output) && new_formatter.respond_to?(:output) + formatter.output == new_formatter.output + end + def existing_formatter_implements?(notification) @reporter.registered_listeners(notification).any? end diff --git a/spec/rspec/core/formatters_spec.rb b/spec/rspec/core/formatters_spec.rb index 06c9bb664e..aee305da97 100644 --- a/spec/rspec/core/formatters_spec.rb +++ b/spec/rspec/core/formatters_spec.rb @@ -144,9 +144,27 @@ module RSpec::Core::Formatters loader.add :documentation, path }.to change { loader.formatters.length } end + + plain_old_formatter = Class.new do + RSpec::Core::Formatters.register self, :example_started + + def initialize(output) + end + end + + it "handles formatters which do not subclass our formatters" do + expect { + loader.add plain_old_formatter, output + }.to change { loader.formatters.length } + + # deliberate duplicate to ensure we can check for them correctly + expect { + loader.add plain_old_formatter, output + }.to_not change { loader.formatters.length } + end end - context "When a custom formatter exists" do + context "when a custom formatter exists" do specific_formatter = RSpec::Core::Formatters::JsonFormatter generic_formatter = specific_formatter.superclass