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

Commit 7f607f0

Browse files
authored
Merge pull request #2507 from rspec/myron/bisect-formatter-refactor
Avoid using `RSpec.configuration` from the bisect coordinator.
2 parents 8492f12 + 925bc20 commit 7f607f0

File tree

8 files changed

+74
-50
lines changed

8 files changed

+74
-50
lines changed

lib/rspec/core/bisect/coordinator.rb

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,47 +15,40 @@ module Bisect
1515
# - Formatters::BisectProgressFormatter: provides progress updates
1616
# to the user.
1717
class Coordinator
18-
def self.bisect_with(original_cli_args, configuration, formatter)
19-
new(original_cli_args, configuration, formatter).bisect
18+
def self.bisect_with(original_cli_args, formatter)
19+
new(original_cli_args, formatter).bisect
2020
end
2121

22-
def initialize(original_cli_args, configuration, formatter)
22+
def initialize(original_cli_args, formatter)
2323
@shell_command = ShellCommand.new(original_cli_args)
24-
@configuration = configuration
25-
@formatter = formatter
24+
@notifier = Bisect::Notifier.new(formatter)
2625
end
2726

2827
def bisect
29-
@configuration.add_formatter @formatter
28+
repro = ShellRunner.start(@shell_command) do |runner|
29+
minimizer = ExampleMinimizer.new(@shell_command, runner, @notifier)
3030

31-
reporter.close_after do
32-
repro = ShellRunner.start(@shell_command) do |runner|
33-
minimizer = ExampleMinimizer.new(@shell_command, runner, reporter)
34-
35-
gracefully_abort_on_sigint(minimizer)
36-
minimizer.find_minimal_repro
37-
minimizer.repro_command_for_currently_needed_ids
38-
end
39-
40-
reporter.publish(:bisect_repro_command, :repro => repro)
31+
gracefully_abort_on_sigint(minimizer)
32+
minimizer.find_minimal_repro
33+
minimizer.repro_command_for_currently_needed_ids
4134
end
4235

36+
@notifier.publish(:bisect_repro_command, :repro => repro)
37+
4338
true
4439
rescue BisectFailedError => e
45-
reporter.publish(:bisect_failed, :failure_explanation => e.message)
40+
@notifier.publish(:bisect_failed, :failure_explanation => e.message)
4641
false
42+
ensure
43+
@notifier.publish(:close)
4744
end
4845

4946
private
5047

51-
def reporter
52-
@configuration.reporter
53-
end
54-
5548
def gracefully_abort_on_sigint(minimizer)
5649
trap('INT') do
5750
repro = minimizer.repro_command_for_currently_needed_ids
58-
reporter.publish(:bisect_aborted, :repro => repro)
51+
@notifier.publish(:bisect_aborted, :repro => repro)
5952
exit(1)
6053
end
6154
end

lib/rspec/core/bisect/example_minimizer.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ module Bisect
77
# Contains the core bisect logic. Searches for examples we can ignore by
88
# repeatedly running different subsets of the suite.
99
class ExampleMinimizer
10-
attr_reader :shell_command, :runner, :reporter, :all_example_ids, :failed_example_ids
10+
attr_reader :shell_command, :runner, :all_example_ids, :failed_example_ids
1111
attr_accessor :remaining_ids
1212

13-
def initialize(shell_command, runner, reporter)
13+
def initialize(shell_command, runner, notifier)
1414
@shell_command = shell_command
1515
@runner = runner
16-
@reporter = reporter
16+
@notifier = notifier
1717
end
1818

1919
def find_minimal_repro
@@ -164,7 +164,7 @@ def abort_if_ordering_inconsistent(results)
164164
end
165165

166166
def notify(*args)
167-
reporter.publish(*args)
167+
@notifier.publish(*args)
168168
end
169169
end
170170
end

lib/rspec/core/bisect/utilities.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,22 @@ def self.for_failed_spec_run(spec_output)
1111
spec_output)
1212
end
1313
end
14+
15+
# Wraps a `formatter` providing a simple means to notify it in place
16+
# of an `RSpec::Core::Reporter`, without involving configuration in
17+
# any way.
18+
# @private
19+
class Notifier
20+
def initialize(formatter)
21+
@formatter = formatter
22+
end
23+
24+
def publish(event, *args)
25+
return unless @formatter.respond_to?(event)
26+
notification = Notifications::CustomNotification.for(*args)
27+
@formatter.__send__(event, notification)
28+
end
29+
end
1430
end
1531
end
1632
end

lib/rspec/core/formatters/bisect_progress_formatter.rb

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@ module Formatters
66
# @private
77
# Produces progress output while bisecting.
88
class BisectProgressFormatter < BaseTextFormatter
9-
# We've named all events with a `bisect_` prefix to prevent naming collisions.
10-
Formatters.register self, :bisect_starting, :bisect_original_run_complete,
11-
:bisect_round_started, :bisect_individual_run_complete,
12-
:bisect_complete, :bisect_repro_command,
13-
:bisect_failed, :bisect_aborted,
14-
:bisect_round_ignoring_ids, :bisect_round_detected_multiple_culprits,
15-
:bisect_dependency_check_started, :bisect_dependency_check_passed,
16-
:bisect_dependency_check_failed
17-
189
def bisect_starting(notification)
1910
@round_count = 0
2011
options = notification.original_cli_args.join(' ')
@@ -88,13 +79,10 @@ def bisect_aborted(notification)
8879
end
8980

9081
# @private
91-
# Produces detailed debug output while bisecting. Used when
92-
# bisect is performed while the `DEBUG_RSPEC_BISECT` ENV var is used.
93-
# Designed to provide details for us when we need to troubleshoot bisect bugs.
82+
# Produces detailed debug output while bisecting. Used when bisect is
83+
# performed with `--bisect=verbose`. Designed to provide details for
84+
# us when we need to troubleshoot bisect bugs.
9485
class BisectDebugFormatter < BisectProgressFormatter
95-
Formatters.register self, :bisect_original_run_complete, :bisect_individual_run_start,
96-
:bisect_individual_run_complete, :bisect_round_ignoring_ids
97-
9886
def bisect_original_run_complete(notification)
9987
output.puts " (#{Helpers.format_duration(notification.duration)})"
10088

lib/rspec/core/invocations.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ def call(options, _err, _out)
3131

3232
success = RSpec::Core::Bisect::Coordinator.bisect_with(
3333
options.args,
34-
RSpec.configuration,
3534
bisect_formatter_for(options.options[:bisect])
3635
)
3736

@@ -41,8 +40,13 @@ def call(options, _err, _out)
4140
private
4241

4342
def bisect_formatter_for(argument)
44-
return Formatters::BisectDebugFormatter if argument == "verbose"
45-
Formatters::BisectProgressFormatter
43+
klass = if argument == "verbose"
44+
Formatters::BisectDebugFormatter
45+
else
46+
Formatters::BisectProgressFormatter
47+
end
48+
49+
klass.new(RSpec.configuration.output_stream)
4650
end
4751
end
4852

spec/rspec/core/bisect/coordinator_spec.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ def find_minimal_repro(output, formatter=Formatters::BisectProgressFormatter)
1818
allow(Bisect::Server).to receive(:run).and_yield(instance_double(Bisect::Server))
1919
allow(Bisect::ShellRunner).to receive(:new).and_return(fake_runner)
2020

21-
RSpec.configuration.output_stream = output
22-
Bisect::Coordinator.bisect_with([], RSpec.configuration, formatter)
21+
Bisect::Coordinator.bisect_with([], formatter.new(output))
2322
ensure
2423
RSpec.reset # so that RSpec.configuration.output_stream isn't closed
2524
end
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
require 'rspec/core/bisect/utilities'
2+
3+
module RSpec::Core
4+
RSpec.describe Bisect::Notifier do
5+
class ExampleFormatterClass
6+
def foo(notification); end
7+
end
8+
9+
let(:formatter) { instance_spy(ExampleFormatterClass) }
10+
let(:notifier) { Bisect::Notifier.new(formatter) }
11+
12+
it 'publishes events to the wrapped formatter' do
13+
notifier.publish :foo, :length => 15, :width => 12
14+
15+
expect(formatter).to have_received(:foo).with(an_object_having_attributes(
16+
:length => 15, :width => 12
17+
))
18+
end
19+
20+
it 'does not publish events the formatter does not recognize' do
21+
expect {
22+
notifier.publish :unrecognized_event, :length => 15, :width => 12
23+
}.not_to raise_error
24+
end
25+
end
26+
end

spec/rspec/core/invocations_spec.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ def run_invocation
9292

9393
expect(RSpec::Core::Bisect::Coordinator).to have_received(:bisect_with).with(
9494
args,
95-
RSpec.configuration,
96-
Formatters::BisectProgressFormatter
95+
an_instance_of(Formatters::BisectProgressFormatter)
9796
)
9897
end
9998

@@ -123,8 +122,7 @@ def run_invocation
123122

124123
expect(RSpec::Core::Bisect::Coordinator).to have_received(:bisect_with).with(
125124
args,
126-
RSpec.configuration,
127-
Formatters::BisectDebugFormatter
125+
an_instance_of(Formatters::BisectDebugFormatter)
128126
)
129127
end
130128
end

0 commit comments

Comments
 (0)