Module: RSpecTracer::RSpec::RunnerHook Private

Defined in:
lib/rspec_tracer/rspec/runner_hook.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Prepended onto ‘RSpec::Core::Runner` by `RSpecTracer::RSpec::Installation.install!`. Replaces the 1.x `RSpecTracer::RSpecRunner` singleton-class prepend that the ObjectSpace loop in `setup_rspec?` used to install.

Responsibilities, in ‘run_specs` order:

1. Early-return to `super` if the engine hasn't been set up
   (defensive; keeps the suite green under `RSPEC_TRACER_DISABLE=1`
   or when the user forgot to call `RSpecTracer.start`).
2. Partition `RSpec.world.filtered_examples` via the engine:
   tracked examples go through identity-hashing + filter decision;
   ignored examples (matched by `Configuration#ignore_spec_files`)
   pass through untouched - RSpec still runs them, but the tracer
   never sees them. Closes #41.
3. Detect duplicate example identities. `fail_on_duplicates=true`
   surfaces via `::Kernel.exit(1)` in `at_exit_behavior`; the
   hook passes `[]` to super so RSpec doesn't execute anything.
4. Overwrite `RSpec.world.@filtered_examples` +
   `@example_groups` with the filtered set, then log the run
   banner and delegate to `super`.

The user-visible log line - ‘RSpec tracer is running N examples (actual: N, skipped: N)` - is preserved byte-for-byte from 1.x so cucumber scenarios and CI log parsers keep working.

Instance Method Summary collapse

Instance Method Details

#run_specs(example_groups) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Internal method on the tracer pipeline.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rspec_tracer/rspec/runner_hook.rb', line 36

def run_specs(example_groups)
  return super unless RSpecTracer.engine

  actual_count = ::RSpec.world.example_count
  if _rspec_tracer_no_examples?(actual_count)
    super
    return
  end

  starting = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  filtered_examples_map, filtered_example_groups = _rspec_tracer_build_filter_decision

  if _rspec_tracer_duplicates_detected?
    RSpecTracer.running = true
    RSpecTracer.duplicate_examples = RSpecTracer.fail_on_duplicates
    super([])
    return
  end

  ::RSpec.world.instance_variable_set(:@filtered_examples, filtered_examples_map)
  ::RSpec.world.instance_variable_set(:@example_groups, filtered_example_groups)

  current_count = ::RSpec.world.example_count
  ending = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  elapsed = RSpecTracer::TimeFormatter.format_time(ending - starting)

  RSpecTracer.logger.info <<-EXAMPLES.strip.gsub(/\s+/, ' ')
    RSpec tracer is running #{current_count} examples (actual: #{actual_count},
    skipped: #{actual_count - current_count}) (took #{elapsed})
  EXAMPLES

  RSpecTracer.running = true

  super(filtered_example_groups)
end