rspec-core 3.7.1 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Changelog.md +29 -0
  5. data/README.md +1 -1
  6. data/lib/rspec/core/bisect/coordinator.rb +26 -30
  7. data/lib/rspec/core/bisect/example_minimizer.rb +12 -8
  8. data/lib/rspec/core/bisect/fork_runner.rb +134 -0
  9. data/lib/rspec/core/bisect/server.rb +4 -13
  10. data/lib/rspec/core/bisect/{runner.rb → shell_command.rb} +27 -70
  11. data/lib/rspec/core/bisect/shell_runner.rb +73 -0
  12. data/lib/rspec/core/bisect/utilities.rb +58 -0
  13. data/lib/rspec/core/configuration.rb +133 -53
  14. data/lib/rspec/core/configuration_options.rb +41 -4
  15. data/lib/rspec/core/example.rb +4 -4
  16. data/lib/rspec/core/example_group.rb +1 -0
  17. data/lib/rspec/core/formatters.rb +10 -6
  18. data/lib/rspec/core/formatters/base_bisect_formatter.rb +45 -0
  19. data/lib/rspec/core/formatters/bisect_drb_formatter.rb +29 -0
  20. data/lib/rspec/core/formatters/bisect_progress_formatter.rb +29 -16
  21. data/lib/rspec/core/formatters/deprecation_formatter.rb +3 -1
  22. data/lib/rspec/core/formatters/exception_presenter.rb +1 -0
  23. data/lib/rspec/core/formatters/html_printer.rb +0 -2
  24. data/lib/rspec/core/formatters/protocol.rb +17 -17
  25. data/lib/rspec/core/formatters/syntax_highlighter.rb +19 -19
  26. data/lib/rspec/core/hooks.rb +1 -3
  27. data/lib/rspec/core/invocations.rb +8 -6
  28. data/lib/rspec/core/memoized_helpers.rb +2 -2
  29. data/lib/rspec/core/profiler.rb +3 -1
  30. data/lib/rspec/core/reporter.rb +3 -6
  31. data/lib/rspec/core/runner.rb +20 -14
  32. data/lib/rspec/core/shared_example_group.rb +1 -3
  33. data/lib/rspec/core/shell_escape.rb +2 -2
  34. data/lib/rspec/core/version.rb +1 -1
  35. data/lib/rspec/core/world.rb +11 -0
  36. metadata +12 -8
  37. metadata.gz.sig +0 -0
  38. data/lib/rspec/core/formatters/bisect_formatter.rb +0 -69
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 82269549116ef3ac8ad256ce6deafa672865194fcdb4b1a194f21e29c6e2bff7
4
- data.tar.gz: 20f2bac3761d3b34c947cb1214b50ef3a6b27abddb9d852857f0302a0f84cd5c
2
+ SHA1:
3
+ metadata.gz: 01f0ed2875b8c4e0801d2857936e4a4116ceb309
4
+ data.tar.gz: 58b9a780de52779ef48a2c510d99c14dd7a22f1d
5
5
  SHA512:
6
- metadata.gz: 2acb4568e22713e22debbf548052112e903af5297c6ec8e8be9b9c8c2c657b79eb9c7a2c83efcf9d4366c40f7134bf77ca7eea3ba8f82dd36ac9a554a744e04e
7
- data.tar.gz: 9b88592b83c97d497774f0b47fa837c895ffabd7c0e52806d3f8c773c505110e6b1f6f1fa8ae348b1533fde353d07fa803cc1c21511d27748e61147dbd505423
6
+ metadata.gz: dc81061f5a9badff82a346285c6571447b9884906540c0502aeec96c1d100d4c764e2422f87dadd46148a8db96926b9c1a5e5d57a72adda28d6f05ddceae65e9
7
+ data.tar.gz: 940193670454593373c80e55c407e31a70b3eb8f9579b108663ec9234e2025149a93aed2d8aec8e2e7eeffd124853bf1a5a068d2a79e4bbcaed551b769d485fd
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,32 @@
1
+ ### 3.8.0 / 2018-08-04
2
+ [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.7.1...v3.8.0)
3
+
4
+ Enhancements:
5
+
6
+ * Improve shell escaping used by `RSpec::Core::RakeTask` and `--bisect` so
7
+ that it works on `Pathname` objects. (Andrew Vit, #2479)
8
+ * Nicely format errors encountered while loading files specified
9
+ by `--require` option. (Myron Marston, #2504)
10
+ * Significantly improve the performance of `--bisect` on platforms that
11
+ support forking by replacing the shell-based runner with one that uses
12
+ forking so that RSpec and the application environment can be booted only
13
+ once, instead of once per spec run. (Myron Marston, #2511)
14
+ * Provide a configuration API to pick which bisect runner is used for
15
+ `--bisect`. Pick a runner via `config.bisect_runner = :shell` or
16
+ `config.bisect_runner = :fork` in a file loaded by a `--require`
17
+ option passed at the command line or set in `.rspec`. (Myron Marston, #2511)
18
+ * Support the [XDG Base Directory
19
+ Specification](https://specifications.freedesktop.org/basedir-spec/latest/)
20
+ for the global options file. `~/.rspec` is still supported when no
21
+ options file is found in `$XDG_CONFIG_HOME/rspec/options` (Magnus Bergmark, #2538)
22
+ * Extract `RSpec.world.prepare_example_filtering` that sets up the
23
+ example filtering for custom RSpec runners. (Oleg Pudeyev, #2552)
24
+
25
+ Bug Fixes:
26
+
27
+ * Prevent an `ArgumentError` when truncating backtraces with two identical
28
+ backtraces. (Systho, #2515, Benoit Tigeot, #2539)
29
+
1
30
  ### 3.7.1 / 2018-01-02
2
31
  [Full Changelog](http://github.com/rspec/rspec-core/compare/v3.7.0...v3.7.1)
3
32
 
data/README.md CHANGED
@@ -15,7 +15,7 @@ RSpec repos as well. Add the following to your `Gemfile`:
15
15
 
16
16
  ```ruby
17
17
  %w[rspec rspec-core rspec-expectations rspec-mocks rspec-support].each do |lib|
18
- gem lib, :git => "git://github.com/rspec/#{lib}.git", :branch => 'master'
18
+ gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'master'
19
19
  end
20
20
  ```
21
21
 
@@ -1,62 +1,58 @@
1
- RSpec::Support.require_rspec_core "bisect/server"
2
- RSpec::Support.require_rspec_core "bisect/runner"
1
+ RSpec::Support.require_rspec_core "bisect/shell_command"
3
2
  RSpec::Support.require_rspec_core "bisect/example_minimizer"
3
+ RSpec::Support.require_rspec_core "bisect/utilities"
4
4
  RSpec::Support.require_rspec_core "formatters/bisect_progress_formatter"
5
5
 
6
6
  module RSpec
7
7
  module Core
8
8
  module Bisect
9
- # @private
10
9
  # The main entry point into the bisect logic. Coordinates among:
11
- # - Bisect::Server: Receives suite results.
12
- # - Bisect::Runner: Runs a set of examples and directs the results
13
- # to the server.
10
+ # - Bisect::ShellCommand: Generates shell commands to run spec subsets
14
11
  # - Bisect::ExampleMinimizer: Contains the core bisect logic.
15
- # - Formatters::BisectProgressFormatter: provides progress updates
16
- # to the user.
12
+ # - A bisect runner: runs a set of examples and returns the results.
13
+ # - A bisect formatter: provides progress updates to the user.
14
+ # @private
17
15
  class Coordinator
18
- def self.bisect_with(original_cli_args, configuration, formatter)
19
- new(original_cli_args, configuration, formatter).bisect
16
+ def self.bisect_with(spec_runner, original_cli_args, formatter)
17
+ new(spec_runner, original_cli_args, formatter).bisect
20
18
  end
21
19
 
22
- def initialize(original_cli_args, configuration, formatter)
23
- @original_cli_args = original_cli_args
24
- @configuration = configuration
25
- @formatter = formatter
20
+ def initialize(spec_runner, original_cli_args, formatter)
21
+ @spec_runner = spec_runner
22
+ @shell_command = ShellCommand.new(original_cli_args)
23
+ @notifier = Bisect::Notifier.new(formatter)
26
24
  end
27
25
 
28
26
  def bisect
29
- @configuration.add_formatter @formatter
30
-
31
- reporter.close_after do
32
- repro = Server.run do |server|
33
- runner = Runner.new(server, @original_cli_args)
34
- minimizer = ExampleMinimizer.new(runner, reporter)
27
+ repro = start_bisect_runner do |runner|
28
+ minimizer = ExampleMinimizer.new(@shell_command, runner, @notifier)
35
29
 
36
- gracefully_abort_on_sigint(minimizer)
37
- minimizer.find_minimal_repro
38
- minimizer.repro_command_for_currently_needed_ids
39
- end
40
-
41
- reporter.publish(:bisect_repro_command, :repro => repro)
30
+ gracefully_abort_on_sigint(minimizer)
31
+ minimizer.find_minimal_repro
32
+ minimizer.repro_command_for_currently_needed_ids
42
33
  end
43
34
 
35
+ @notifier.publish(:bisect_repro_command, :repro => repro)
36
+
44
37
  true
45
38
  rescue BisectFailedError => e
46
- reporter.publish(:bisect_failed, :failure_explanation => e.message)
39
+ @notifier.publish(:bisect_failed, :failure_explanation => e.message)
47
40
  false
41
+ ensure
42
+ @notifier.publish(:close)
48
43
  end
49
44
 
50
45
  private
51
46
 
52
- def reporter
53
- @configuration.reporter
47
+ def start_bisect_runner(&block)
48
+ klass = @spec_runner.configuration.bisect_runner_class
49
+ klass.start(@shell_command, @spec_runner, &block)
54
50
  end
55
51
 
56
52
  def gracefully_abort_on_sigint(minimizer)
57
53
  trap('INT') do
58
54
  repro = minimizer.repro_command_for_currently_needed_ids
59
- reporter.publish(:bisect_aborted, :repro => repro)
55
+ @notifier.publish(:bisect_aborted, :repro => repro)
60
56
  exit(1)
61
57
  end
62
58
  end
@@ -1,3 +1,5 @@
1
+ RSpec::Support.require_rspec_core "bisect/utilities"
2
+
1
3
  module RSpec
2
4
  module Core
3
5
  module Bisect
@@ -5,12 +7,13 @@ module RSpec
5
7
  # Contains the core bisect logic. Searches for examples we can ignore by
6
8
  # repeatedly running different subsets of the suite.
7
9
  class ExampleMinimizer
8
- attr_reader :runner, :reporter, :all_example_ids, :failed_example_ids
10
+ attr_reader :shell_command, :runner, :all_example_ids, :failed_example_ids
9
11
  attr_accessor :remaining_ids
10
12
 
11
- def initialize(runner, reporter)
12
- @runner = runner
13
- @reporter = reporter
13
+ def initialize(shell_command, runner, notifier)
14
+ @shell_command = shell_command
15
+ @runner = runner
16
+ @notifier = notifier
14
17
  end
15
18
 
16
19
  def find_minimal_repro
@@ -82,7 +85,7 @@ module RSpec
82
85
  end
83
86
 
84
87
  def repro_command_for_currently_needed_ids
85
- return runner.repro_command_from(currently_needed_ids) if remaining_ids
88
+ return shell_command.repro_command_from(currently_needed_ids) if remaining_ids
86
89
  "(Not yet enough information to provide any repro command)"
87
90
  end
88
91
 
@@ -108,7 +111,8 @@ module RSpec
108
111
  end
109
112
 
110
113
  def prep
111
- notify(:bisect_starting, :original_cli_args => runner.original_cli_args)
114
+ notify(:bisect_starting, :original_cli_args => shell_command.original_cli_args,
115
+ :bisect_runner => runner.class.name)
112
116
 
113
117
  _, duration = track_duration do
114
118
  original_results = runner.original_results
@@ -135,7 +139,7 @@ module RSpec
135
139
  ids_to_run = ids + failed_example_ids
136
140
  notify(
137
141
  :bisect_individual_run_start,
138
- :command => runner.repro_command_from(ids_to_run),
142
+ :command => shell_command.repro_command_from(ids_to_run),
139
143
  :ids_to_run => ids_to_run
140
144
  )
141
145
 
@@ -161,7 +165,7 @@ module RSpec
161
165
  end
162
166
 
163
167
  def notify(*args)
164
- reporter.publish(*args)
168
+ @notifier.publish(*args)
165
169
  end
166
170
  end
167
171
  end
@@ -0,0 +1,134 @@
1
+ require 'stringio'
2
+ RSpec::Support.require_rspec_core "formatters/base_bisect_formatter"
3
+ RSpec::Support.require_rspec_core "bisect/utilities"
4
+
5
+ module RSpec
6
+ module Core
7
+ module Bisect
8
+ # A Bisect runner that runs requested subsets of the suite by forking
9
+ # sub-processes. The master process bootstraps RSpec and the application
10
+ # environment (including preloading files specified via `--require`) so
11
+ # that the individual spec runs do not have to re-pay that cost. Each
12
+ # spec run happens in a forked process, ensuring that the spec files are
13
+ # not loaded in the main process.
14
+ #
15
+ # For most projects, bisections that use `ForkRunner` instead of
16
+ # `ShellRunner` will finish significantly faster, because the `ShellRunner`
17
+ # pays the cost of booting RSpec and the app environment on _every_ run of
18
+ # a subset. In contrast, `ForkRunner` pays that cost only once.
19
+ #
20
+ # However, not all projects can use `ForkRunner`. Obviously, on platforms
21
+ # that do not support forking (e.g. Windows), it cannot be used. In addition,
22
+ # it can cause problems for some projects that put side-effectful spec
23
+ # bootstrapping logic that should run on every spec run directly at the top
24
+ # level in a file loaded by `--require`, rather than in a `before(:suite)`
25
+ # hook. For example, consider a project that relies on some top-level logic
26
+ # in `spec_helper` to boot a Redis server for the test suite, intending the
27
+ # Redis bootstrapping to happen on every spec run. With `ShellRunner`, the
28
+ # bootstrapping logic will happen for each run of any subset of the suite,
29
+ # but for `ForkRunner`, such logic will only get run once, when the
30
+ # `RunDispatcher` boots the application environment. This might cause
31
+ # problems. The solution is for users to move the bootstrapping logic into
32
+ # a `before(:suite)` hook, or use the slower `ShellRunner`.
33
+ #
34
+ # @private
35
+ class ForkRunner
36
+ def self.start(shell_command, spec_runner)
37
+ instance = new(shell_command, spec_runner)
38
+ yield instance
39
+ ensure
40
+ instance.shutdown
41
+ end
42
+
43
+ def self.name
44
+ :fork
45
+ end
46
+
47
+ def initialize(shell_command, spec_runner)
48
+ @shell_command = shell_command
49
+ @channel = Channel.new
50
+ @run_dispatcher = RunDispatcher.new(spec_runner, @channel)
51
+ end
52
+
53
+ def run(locations)
54
+ run_descriptor = ExampleSetDescriptor.new(locations, original_results.failed_example_ids)
55
+ dispatch_run(run_descriptor)
56
+ end
57
+
58
+ def original_results
59
+ @original_results ||= dispatch_run(ExampleSetDescriptor.new(
60
+ @shell_command.original_locations, []))
61
+ end
62
+
63
+ def shutdown
64
+ @channel.close
65
+ end
66
+
67
+ private
68
+
69
+ def dispatch_run(run_descriptor)
70
+ @run_dispatcher.dispatch_specs(run_descriptor)
71
+ @channel.receive.tap do |result|
72
+ if result.is_a?(String)
73
+ raise BisectFailedError.for_failed_spec_run(result)
74
+ end
75
+ end
76
+ end
77
+
78
+ # @private
79
+ class RunDispatcher
80
+ def initialize(runner, channel)
81
+ @runner = runner
82
+ @channel = channel
83
+
84
+ @spec_output = StringIO.new
85
+
86
+ runner.configuration.tap do |c|
87
+ c.reset_reporter
88
+ c.output_stream = @spec_output
89
+ c.error_stream = @spec_output
90
+ end
91
+ end
92
+
93
+ def dispatch_specs(run_descriptor)
94
+ pid = fork { run_specs(run_descriptor) }
95
+ Process.waitpid(pid)
96
+ end
97
+
98
+ private
99
+
100
+ def run_specs(run_descriptor)
101
+ $stdout = $stderr = @spec_output
102
+ formatter = CaptureFormatter.new(run_descriptor.failed_example_ids)
103
+
104
+ @runner.configuration.tap do |c|
105
+ c.files_or_directories_to_run = run_descriptor.all_example_ids
106
+ c.formatter = formatter
107
+ c.load_spec_files
108
+ end
109
+
110
+ # `announce_filters` has the side effect of implementing the logic
111
+ # that honors `config.run_all_when_everything_filtered` so we need
112
+ # to call it here. When we remove `run_all_when_everything_filtered`
113
+ # (slated for RSpec 4), we can remove this call to `announce_filters`.
114
+ @runner.world.announce_filters
115
+
116
+ @runner.run_specs(@runner.world.ordered_example_groups)
117
+ latest_run_results = formatter.results
118
+
119
+ if latest_run_results.nil? || latest_run_results.all_example_ids.empty?
120
+ @channel.send(@spec_output.string)
121
+ else
122
+ @channel.send(latest_run_results)
123
+ end
124
+ end
125
+ end
126
+
127
+ class CaptureFormatter < Formatters::BaseBisectFormatter
128
+ attr_accessor :results
129
+ alias_method :notify_results, :results=
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -1,13 +1,11 @@
1
1
  require 'drb/drb'
2
2
  require 'drb/acl'
3
+ RSpec::Support.require_rspec_core "bisect/utilities"
3
4
 
4
5
  module RSpec
5
6
  module Core
6
7
  # @private
7
8
  module Bisect
8
- # @private
9
- BisectFailedError = Class.new(StandardError)
10
-
11
9
  # @private
12
10
  # A DRb server that receives run results from a separate RSpec process
13
11
  # started by the bisect process.
@@ -27,7 +25,7 @@ module RSpec
27
25
  run_output = yield
28
26
 
29
27
  if latest_run_results.nil? || latest_run_results.all_example_ids.empty?
30
- raise_bisect_failed(run_output)
28
+ raise BisectFailedError.for_failed_spec_run(run_output)
31
29
  end
32
30
 
33
31
  latest_run_results
@@ -49,21 +47,14 @@ module RSpec
49
47
  @drb_port ||= Integer(@drb.uri[/\d+$/])
50
48
  end
51
49
 
52
- # Fetched via DRb by the BisectFormatter to determine when to abort.
50
+ # Fetched via DRb by the BisectDRbFormatter to determine when to abort.
53
51
  attr_accessor :expected_failures
54
52
 
55
- # Set via DRb by the BisectFormatter with the results of the run.
53
+ # Set via DRb by the BisectDRbFormatter with the results of the run.
56
54
  attr_accessor :latest_run_results
57
55
 
58
56
  # Fetched via DRb to tell clients which files to run
59
57
  attr_accessor :files_or_directories_to_run
60
-
61
- private
62
-
63
- def raise_bisect_failed(run_output)
64
- raise BisectFailedError, "Failed to get results from the spec " \
65
- "run. Spec run output:\n\n#{run_output}"
66
- end
67
58
  end
68
59
  end
69
60
  end
@@ -1,36 +1,30 @@
1
1
  RSpec::Support.require_rspec_core "shell_escape"
2
- require 'open3'
3
2
  require 'shellwords'
4
3
 
5
4
  module RSpec
6
5
  module Core
7
6
  module Bisect
8
- # Provides an API to run the suite for a set of locations, using
9
- # the given bisect server to capture the results.
7
+ # Provides an API to generate shell commands to run the suite for a
8
+ # set of locations, using the given bisect server to capture the results.
10
9
  # @private
11
- class Runner
10
+ class ShellCommand
12
11
  attr_reader :original_cli_args
13
12
 
14
- def initialize(server, original_cli_args)
15
- @server = server
13
+ def initialize(original_cli_args)
16
14
  @original_cli_args = original_cli_args.reject { |arg| arg.start_with?("--bisect") }
17
15
  end
18
16
 
19
- def run(locations)
20
- run_locations(locations, original_results.failed_example_ids)
21
- end
22
-
23
- def command_for(locations)
17
+ def command_for(locations, server)
24
18
  parts = []
25
19
 
26
20
  parts << RUBY << load_path
27
21
  parts << open3_safe_escape(RSpec::Core.path_to_executable)
28
22
 
29
- parts << "--format" << "bisect"
30
- parts << "--drb-port" << @server.drb_port
23
+ parts << "--format" << "bisect-drb"
24
+ parts << "--drb-port" << server.drb_port
31
25
 
32
- parts.concat reusable_cli_options
33
- parts.concat locations.map { |l| open3_safe_escape(l) }
26
+ parts.concat(reusable_cli_options)
27
+ parts.concat(locations.map { |l| open3_safe_escape(l) })
34
28
 
35
29
  parts.join(" ")
36
30
  end
@@ -46,8 +40,24 @@ module RSpec
46
40
  parts.join(" ")
47
41
  end
48
42
 
49
- def original_results
50
- @original_results ||= run_locations(original_locations)
43
+ def original_locations
44
+ parsed_original_cli_options.fetch(:files_or_directories_to_run)
45
+ end
46
+
47
+ def bisect_environment_hash
48
+ if ENV.key?('SPEC_OPTS')
49
+ { 'SPEC_OPTS' => spec_opts_without_bisect }
50
+ else
51
+ {}
52
+ end
53
+ end
54
+
55
+ def spec_opts_without_bisect
56
+ Shellwords.join(
57
+ Shellwords.split(ENV.fetch('SPEC_OPTS', '')).reject do |arg|
58
+ arg =~ /^--bisect/
59
+ end
60
+ )
51
61
  end
52
62
 
53
63
  private
@@ -63,61 +73,12 @@ module RSpec
63
73
  alias open3_safe_escape escape
64
74
  end
65
75
 
66
- def run_locations(*capture_args)
67
- @server.capture_run_results(*capture_args) do
68
- run_command command_for([])
69
- end
70
- end
71
-
72
- # `Open3.capture2e` does not work on JRuby:
73
- # https://github.com/jruby/jruby/issues/2766
74
- if Open3.respond_to?(:capture2e) && !RSpec::Support::Ruby.jruby?
75
- def run_command(cmd)
76
- Open3.capture2e(bisect_environment_hash, cmd).first
77
- end
78
- else # for 1.8.7
79
- # :nocov:
80
- def run_command(cmd)
81
- out = err = nil
82
-
83
- original_spec_opts = ENV['SPEC_OPTS']
84
- ENV['SPEC_OPTS'] = spec_opts_without_bisect
85
-
86
- Open3.popen3(cmd) do |_, stdout, stderr|
87
- # Reading the streams blocks until the process is complete
88
- out = stdout.read
89
- err = stderr.read
90
- end
91
-
92
- "Stdout:\n#{out}\n\nStderr:\n#{err}"
93
- ensure
94
- ENV['SPEC_OPTS'] = original_spec_opts
95
- end
96
- # :nocov:
97
- end
98
-
99
- def bisect_environment_hash
100
- if ENV.key?('SPEC_OPTS')
101
- { 'SPEC_OPTS' => spec_opts_without_bisect }
102
- else
103
- {}
104
- end
105
- end
106
-
107
76
  def environment_repro_parts
108
77
  bisect_environment_hash.map do |k, v|
109
78
  %Q(#{k}="#{v}")
110
79
  end
111
80
  end
112
81
 
113
- def spec_opts_without_bisect
114
- Shellwords.join(
115
- Shellwords.split(ENV.fetch('SPEC_OPTS', '')).reject do |arg|
116
- arg =~ /^--bisect/
117
- end
118
- )
119
- end
120
-
121
82
  def reusable_cli_options
122
83
  @reusable_cli_options ||= begin
123
84
  opts = original_cli_args_without_locations
@@ -146,10 +107,6 @@ module RSpec
146
107
  @parsed_original_cli_options ||= Parser.parse(@original_cli_args)
147
108
  end
148
109
 
149
- def original_locations
150
- parsed_original_cli_options.fetch(:files_or_directories_to_run)
151
- end
152
-
153
110
  def load_path
154
111
  @load_path ||= "-I#{$LOAD_PATH.map { |p| open3_safe_escape(p) }.join(':')}"
155
112
  end