123456789_123456789_123456789_123456789_123456789_

Class: RSpec::Core::Bisect::ExampleMinimizer 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/example_minimizer.rb

Overview

Contains the core bisect logic. Searches for examples we can ignore by repeatedly running different subsets of the suite.

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Instance Attribute Details

#all_example_ids (readonly)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 10

attr_reader :shell_command, :runner, :all_example_ids, :failed_example_ids

#failed_example_ids (readonly)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 10

attr_reader :shell_command, :runner, :all_example_ids, :failed_example_ids

#remaining_ids (rw)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 11

attr_accessor :remaining_ids

#runner (readonly)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 10

attr_reader :shell_command, :runner, :all_example_ids, :failed_example_ids

#shell_command (readonly)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 10

attr_reader :shell_command, :runner, :all_example_ids, :failed_example_ids

Instance Method Details

#abort_if_ordering_inconsistent(results) (private)

Raises:

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 158

def abort_if_ordering_inconsistent(results)
  expected_order = all_example_ids & results.all_example_ids
  return if expected_order == results.all_example_ids

  raise BisectFailedError, "\n\nThe example ordering is inconsistent. " \
        "`--bisect` relies upon consistent ordering (e.g. by passing " \
        "`--seed` if you're using random ordering) to work properly."
end

#bisect(candidate_ids)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 33

def bisect(candidate_ids)
  notify(:bisect_dependency_check_started)
  if get_expected_failures_for?([])
    notify(:bisect_dependency_check_failed)
    self.remaining_ids = []
    return
  end
  notify(:bisect_dependency_check_passed)

  bisect_over(candidate_ids)
end

#bisect_over(candidate_ids)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 45

def bisect_over(candidate_ids)
  return if candidate_ids.one?

  notify(
    :bisect_round_started,
    :candidate_range => example_range(candidate_ids),
    :candidates_count => candidate_ids.size
  )

  slice_size = (candidate_ids.length / 2.0).ceil
  lhs, rhs = candidate_ids.each_slice(slice_size).to_a

  ids_to_ignore, duration = track_duration do
    [lhs, rhs].find do |ids|
      get_expected_failures_for?(remaining_ids - ids)
    end
  end

  if ids_to_ignore
    self.remaining_ids -= ids_to_ignore
    notify(
      :bisect_round_ignoring_ids,
      :ids_to_ignore => ids_to_ignore,
      :ignore_range => example_range(ids_to_ignore),
      :remaining_ids => remaining_ids,
      :duration => duration
    )
    bisect_over(candidate_ids - ids_to_ignore)
  else
    notify(
      :bisect_round_detected_multiple_culprits,
      :duration => duration
    )
    bisect_over(lhs)
    bisect_over(rhs)
  end
end

#currently_needed_ids

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 83

def currently_needed_ids
  remaining_ids + failed_example_ids
end

#example_range(ids) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 106

def example_range(ids)
  ExampleRange.new(
    non_failing_example_ids.find_index(ids.first) + 1,
    non_failing_example_ids.find_index(ids.last) + 1
  )
end

#find_minimal_repro

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 19

def find_minimal_repro
  prep

  _, duration = track_duration do
    bisect(non_failing_example_ids)
  end

  notify(:bisect_complete, :duration => duration,
                           :original_non_failing_count => non_failing_example_ids.size,
                           :remaining_count => remaining_ids.size)

  remaining_ids + failed_example_ids
end

#get_expected_failures_for?(ids) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 138

def get_expected_failures_for?(ids)
  ids_to_run = ids + failed_example_ids
  notify(
    :bisect_individual_run_start,
    :command => shell_command.repro_command_from(ids_to_run),
    :ids_to_run => ids_to_run
  )

  results, duration = track_duration { runner.run(ids_to_run) }
  notify(:bisect_individual_run_complete, :duration => duration, :results => results)

  abort_if_ordering_inconsistent(results)
  (failed_example_ids & results.failed_example_ids) == failed_example_ids
end

#non_failing_example_ids (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 134

def non_failing_example_ids
  @non_failing_example_ids ||= all_example_ids - failed_example_ids
end

#notify(*args) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 167

def notify(*args)
  @notifier.publish(*args)
end

#prep (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 113

def prep
  notify(:bisect_starting, :original_cli_args => shell_command.original_cli_args,
                           :bisect_runner => runner.class.name)

  _, duration = track_duration do
    original_results    = runner.original_results
    @all_example_ids    = original_results.all_example_ids
    @failed_example_ids = original_results.failed_example_ids
    @remaining_ids      = non_failing_example_ids
  end

  if @failed_example_ids.empty?
    raise BisectFailedError, "\n\nNo failures found. Bisect only works " \
          "in the presence of one or more failing examples."
  else
    notify(:bisect_original_run_complete, :failed_example_ids => failed_example_ids,
                                          :non_failing_example_ids => non_failing_example_ids,
                                          :duration => duration)
  end
end

#repro_command_for_currently_needed_ids

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 87

def repro_command_for_currently_needed_ids
  return shell_command.repro_command_from(currently_needed_ids) if remaining_ids
  "(Not yet enough information to provide any repro command)"
end

#track_duration (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/bisect/example_minimizer.rb', line 153

def track_duration
  start = ::RSpec::Core::Time.now
  [yield, ::RSpec::Core::Time.now - start]
end