class Mutant::Integration::Rspec

rubocop:disable Metrics/ClassLength
for unique reference.
Is NOT enough. It would not be unique. So we add an “example index”
* location
* full description
For that reason identifying examples by:
aside the instances of ‘RSpec::Core::Example` objects itself.
* Does not maintain a unique identification for an example,
data structure
need to be selected in-place via mutating the `RSpec.filtered_examples`
* There is no API to “just run a subset of examples”, the examples
* Keeps its state global in RSpec.world and lots of other places
This looks so complicated, because rspec:
Rspec integration

def all_examples

def all_examples
  @rspec_world.example_groups.flat_map(&:descendants).flat_map(&:examples)
end

def all_tests

Returns:
  • (Enumerable) -
def all_tests
  all_tests_index.keys
end

def all_tests_index

def all_tests_index
  all_examples.each_with_index.with_object({}) do |(example, example_index), index|
    index[parse_example(example, example_index)] = example
  end
end

def available_tests

Returns:
  • (Enumerable) -
def available_tests
  all_tests_index.select { |_test, example| example.metadata.fetch(:mutant, true) }.keys
end

def call(tests)

Returns:
  • (Result::Test) -

Parameters:
  • tests (Enumerable) --
def call(tests)
  reset_examples
  setup_examples(tests.map(&all_tests_index))
  @runner.configuration.start_time = world.time.now - @setup_elapsed
  start = timer.now
  passed = @runner.run_specs(@rspec_world.ordered_example_groups).equal?(EXIT_SUCCESS)
  @runner.configuration.reset_reporter
  Result::Test.new(
    job_index: nil,
    output:    '',
    passed:,
    runtime:   timer.now - start
  )
end

def effective_arguments

def effective_arguments
  arguments.empty? ? DEFAULT_CLI_OPTIONS : arguments
end

def example_group_map

def example_group_map
  @rspec_world.example_groups.flat_map(&:descendants).each_with_object({}) do |example_group, map|
    example_group.examples.each do |example|
      map[example] = example_group
    end
  end
end

def freeze

def freeze
  super if @setup_elapsed
  self
end

def initialize(*)

Returns:
  • (undefined) -
def initialize(*)
  super
  @runner      = RSpec::Core::Runner.new(RSpec::Core::ConfigurationOptions.new(effective_arguments))
  @rspec_world = RSpec.world
end

def parse_example(example, index)

def parse_example(example, index)
  metadata = example.metadata
  id = TEST_ID_FORMAT % {
    index:,
    location:    metadata.fetch(:location),
    description: metadata.fetch(:full_description)
  }
  Test.new(
    expressions: parse_metadata(metadata),
    id:
  )
end

def parse_expression(input, &)

def parse_expression(input, &)
  expression_parser.call(input).from_right(&)
end

def parse_metadata(metadata)

mutant:disable -- 3.3 specific mutation on match.captures -> match
def parse_metadata(metadata)
  if metadata.key?(:mutant_expression)
    expression = metadata.fetch(:mutant_expression)
    expressions =
      expression.instance_of?(Array) ? expression : [expression]
    expressions.map(&method(:parse_expression))
  else
    match = EXPRESSION_CANDIDATE.match(metadata.fetch(:full_description)) or return [ALL_EXPRESSION]
    [parse_expression(Util.one(match.captures)) { ALL_EXPRESSION }]
  end
end

def reset_examples

def reset_examples
  @rspec_world.filtered_examples.each_value(&:clear)
end

def rspec_is_quitting?

def rspec_is_quitting?
  @rspec_world.respond_to?(:rspec_is_quitting) && @rspec_world.rspec_is_quitting
end

def rspec_setup_failure?

def rspec_setup_failure?
  @rspec_world.wants_to_quit || rspec_is_quitting?
end

def setup

Returns:
  • (self) -
def setup
  @setup_elapsed = timer.elapsed do
    @runner.setup(world.stderr, world.stdout)
    fail 'RSpec setup failure' if rspec_setup_failure?
    example_group_map
  end
  @runner.configuration.force(color_mode: :on)
  @runner.configuration.reporter
  reset_examples
  freeze
end

def setup_examples(examples)

def setup_examples(examples)
  examples.each do |example|
    @rspec_world.filtered_examples.fetch(example_group_map.fetch(example)) << example
  end
end