123456789_123456789_123456789_123456789_123456789_

Class: RSpec::Core::Bisect::ForkRunner Private

Do not use. This class is for internal use only.
Relationships & Source Files
Namespace Children
Classes:
Inherits: Object
Defined in: rspec-core/lib/rspec/core/bisect/fork_runner.rb

Overview

A Bisect runner that runs requested subsets of the suite by forking sub-processes. The main process bootstraps ::RSpec and the application environment (including preloading files specified via ‘–require`) so that the individual spec runs do not have to re-pay that cost. Each spec run happens in a forked process, ensuring that the spec files are not loaded in the main process.

For most projects, bisections that use ‘ForkRunner` instead of ShellRunner will finish significantly faster, because the ShellRunner pays the cost of booting ::RSpec and the app environment on every run of a subset. In contrast, ForkRunner pays that cost only once.

However, not all projects can use ‘ForkRunner`. Obviously, on platforms that do not support forking (e.g. Windows), it cannot be used. In addition, it can cause problems for some projects that put side-effectful spec bootstrapping logic that should run on every spec run directly at the top level in a file loaded by –require, rather than in a before(:suite) hook. For example, consider a project that relies on some top-level logic in spec_helper to boot a Redis server for the test suite, intending the Redis bootstrapping to happen on every spec run. With ShellRunner, the bootstrapping logic will happen for each run of any subset of the suite, but for ForkRunner, such logic will only get run once, when the RunDispatcher boots the application environment. This might cause problems. The solution is for users to move the bootstrapping logic into a before(:suite) hook, or use the slower ShellRunner.

Class Method Summary

Instance Method Summary

Class Method Details

.name

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/fork_runner.rb', line 43

def self.name
  :fork
end

.start(shell_command, spec_runner)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/fork_runner.rb', line 36

def self.start(shell_command, spec_runner)
  instance = new(shell_command, spec_runner)
  yield instance
ensure
  instance.shutdown
end

Instance Method Details

#dispatch_run(run_descriptor) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/fork_runner.rb', line 69

def dispatch_run(run_descriptor)
  @run_dispatcher.dispatch_specs(run_descriptor)
  @channel.receive.tap do |result|
    if result.is_a?(String)
      raise BisectFailedError.for_failed_spec_run(result)
    end
  end
end

#original_results

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/fork_runner.rb', line 58

def original_results
  @original_results ||= dispatch_run(ExampleSetDescriptor.new(
    @shell_command.original_locations, []))
end

#run(locations)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/fork_runner.rb', line 53

def run(locations)
  run_descriptor = ExampleSetDescriptor.new(locations, original_results.failed_example_ids)
  dispatch_run(run_descriptor)
end

#shutdown

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/fork_runner.rb', line 63

def shutdown
  @channel.close
end