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

Commit b9070c1

Browse files
Make --bisect work in SPEC_OPTS
Proof-of-concept - not intended for merge! Previously, using SPEC_OPTS='--bisect' would result in infinite rspec processes starting, as every child process spawned by bisect would still have "--bisect" in the ENV, and would start the bisection anew. While Open3.capture2e accepts an environment value, this is merged with the parent process's ENV to give the new process its environment, so we can't just delete 'SPEC_OPTS' from the env, we need to overwrite it with a blank value: Open3.capture2e({ 'SPEC_OPTS' => '' }, cmd) This resolves resolved the infinite process problem, but highlighted a new problem. Due to the way the Bisect::Runner is invoked in options parsing, the bisection lost any options specified at the command line. For example: $ SPEC_OPTS='--bisect' rspec blah_spec.rb --seed 1234 Because SPEC_OPTS and ARGV are parsed separately, in this case `#bisect_and_exit` gets invoked during the parsing of SPEC_OPTS, which means that the bisect runner is started without the file and seed arguments. To address this I've made the OptionParser set a :bisect option, which is then picked up in the main Runner to invoke the actual bisection. I've also had to bodge in a means of getting the combined CLI and environment args to pass to the Bisect::Runner. This is why we need to completely clear SPEC_OPTS for the child processes, rather than just remove "--bisect", as all the args passed in the parent's SPEC_OPTS get moved to the CLI args for the child command. The bisect tests fail on this commit because of the aruba helpers modifying the SPEC_OPTS environment variable, which affects the test output. The bisect feature itself does now work with SPEC_OPTS='--bisect', however.
1 parent 7517cba commit b9070c1

File tree

3 files changed

+26
-20
lines changed

3 files changed

+26
-20
lines changed

lib/rspec/core/bisect/runner.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ def run_locations(*capture_args)
7171
# https://github.com/jruby/jruby/issues/2766
7272
if Open3.respond_to?(:capture2e) && !RSpec::Support::Ruby.jruby?
7373
def run_command(cmd)
74-
Open3.capture2e(cmd).first
74+
Open3.capture2e(spec_opts_without_bisect, cmd).first
7575
end
7676
else # for 1.8.7
7777
# :nocov:
7878
def run_command(cmd)
7979
out = err = nil
8080

81-
Open3.popen3(cmd) do |_, stdout, stderr|
81+
Open3.popen3(spec_opts_without_bisect, cmd) do |_, stdout, stderr|
8282
# Reading the streams blocks until the process is complete
8383
out = stdout.read
8484
err = stderr.read
@@ -89,6 +89,10 @@ def run_command(cmd)
8989
# :nocov:
9090
end
9191

92+
def spec_opts_without_bisect
93+
{ 'SPEC_OPTS' => ENV.fetch('SPEC_OPTS', '').gsub(/--bisect/, '') }
94+
end
95+
9296
def reusable_cli_options
9397
@reusable_cli_options ||= begin
9498
opts = original_cli_args_without_locations

lib/rspec/core/option_parser.rb

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def parser(options)
6868

6969
parser.on('--bisect[=verbose]', 'Repeatedly runs the suite in order to isolate the failures to the ',
7070
' smallest reproducible case.') do |argument|
71-
bisect_and_exit(argument)
71+
options[:bisect] = argument || true
7272
end
7373

7474
parser.on('--[no-]fail-fast[=COUNT]', 'Abort the run after a certain number of failures (1 by default).') do |argument|
@@ -288,23 +288,6 @@ def initialize_project_and_exit
288288
exit
289289
end
290290

291-
def bisect_and_exit(argument)
292-
RSpec::Support.require_rspec_core "bisect/coordinator"
293-
294-
success = Bisect::Coordinator.bisect_with(
295-
original_args,
296-
RSpec.configuration,
297-
bisect_formatter_for(argument)
298-
)
299-
300-
exit(success ? 0 : 1)
301-
end
302-
303-
def bisect_formatter_for(argument)
304-
return Formatters::BisectDebugFormatter if argument == "verbose"
305-
Formatters::BisectProgressFormatter
306-
end
307-
308291
def print_version_and_exit
309292
puts RSpec::Core::Version::STRING
310293
exit

lib/rspec/core/runner.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,30 @@ def self.run(args, err=$stderr, out=$stdout)
7373
rescue DRb::DRbConnError
7474
err.puts "No DRb server is running. Running in local process instead ..."
7575
end
76+
elsif options.options[:bisect]
77+
bisect_and_exit(options.options[:bisect], args)
7678
end
7779

7880
new(options).run(err, out)
7981
end
8082

83+
def self.bisect_and_exit(argument, original_args)
84+
RSpec::Support.require_rspec_core "bisect/coordinator"
85+
86+
success = Bisect::Coordinator.bisect_with(
87+
original_args,
88+
RSpec.configuration,
89+
bisect_formatter_for(argument)
90+
)
91+
92+
exit(success ? 0 : 1)
93+
end
94+
95+
def self.bisect_formatter_for(argument)
96+
return Formatters::BisectDebugFormatter if argument == "verbose"
97+
Formatters::BisectProgressFormatter
98+
end
99+
81100
def initialize(options, configuration=RSpec.configuration, world=RSpec.world)
82101
@options = options
83102
@configuration = configuration

0 commit comments

Comments
 (0)