Module: ParallelRSpec::SimpleCov

Defined in:
lib/parallel_rspec_simplecov.rb,
lib/parallel_rspec_simplecov/version.rb,
lib/parallel_rspec_simplecov/simplecov.rb

Constant Summary collapse

VERSION =
"1.0.0.rc1"

Class Method Summary collapse

Class Method Details

.collate!void

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.

This method returns an undefined value.

Merge per-worker resultsets into a single report. Called automatically from the ‘after(:suite)` hook installed by start — not intended to be called directly.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/parallel_rspec_simplecov/simplecov.rb', line 79

def self.collate!
  base_dir = @simplecov_base_dir || ::SimpleCov.coverage_dir

  # Force the server process's resultset to disk before we glob. SimpleCov's
  # own at_exit handler will harmlessly re-dump it after collation finishes.
  ::SimpleCov.result.format!

  pattern = File.join(base_dir, "rspec_*", ".resultset.json")
  resultsets = Dir.glob(pattern)

  if resultsets.empty?
    warn "[parallel_rspec] no SimpleCov resultsets found under #{pattern}; skipping collation"
    return
  end

  collate_formatter =
    case @simplecov_formatters.length
    when 0 then nil
    when 1 then @simplecov_formatters.first
    else ::SimpleCov::Formatter::MultiFormatter.new(@simplecov_formatters)
    end

  ::SimpleCov.collate(resultsets) do
    coverage_dir base_dir
    formatter collate_formatter if collate_formatter
  end
rescue => e
  warn "[parallel_rspec] simplecov collation failed: #{e.class}: #{e.message}"
  warn e.backtrace.first(5).join("\n") if e.backtrace
end

.simplecov_enabled?Boolean

Returns true once start has been called in this process.

Returns:

  • (Boolean)


13
14
15
# File 'lib/parallel_rspec_simplecov/simplecov.rb', line 13

def self.simplecov_enabled?
  @simplecov_enabled
end

.start(profile = nil, formatters: nil) { ... } ⇒ void

This method returns an undefined value.

Configure SimpleCov to merge coverage across ‘parallel_rspec` workers.

Call this in place of ‘SimpleCov.start` from your `spec_helper.rb`. It starts SimpleCov on the server process, registers an `after_fork` hook so each worker writes its own resultset under `coverage/rspec_N/`, and registers an `after(:suite)` hook to collate everything into a merged report at the end of the run.

Idempotent: subsequent calls are no-ops.

Parameters:

  • profile (String, nil) (defaults to: nil)

    SimpleCov profile name, passed through to ‘SimpleCov.start`.

  • formatters (Array<SimpleCov::Formatter>, nil) (defaults to: nil)

    formatters to apply to the merged result. Accepts formatter classes or instances. When more than one is given they are wrapped in a ‘MultiFormatter`. When omitted, SimpleCov’s default formatter is used.

Yields:

  • SimpleCov configuration block (e.g. ‘add_filter`, `enable_coverage :branch`), passed through to `SimpleCov.start`.



31
32
33
34
35
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
71
# File 'lib/parallel_rspec_simplecov/simplecov.rb', line 31

def self.start(profile = nil, formatters: nil, &block)
  return if @simplecov_enabled

  ::SimpleCov.enable_for_subprocesses true

  base_dir = ::SimpleCov.coverage_dir

  force_worker_settings = lambda do
    # Prevent forked processes races generating the HTML report; each
    # process just dumps a .resultset.json that the runner collates into
    # the user's chosen formatter(s) at the end of the run.
    ::SimpleCov.print_error_status = false
    ::SimpleCov.formatter ::SimpleCov::Formatter::SimpleFormatter
    ::SimpleCov.minimum_coverage 0
  end

  start_simplecov = lambda do |command_name, dir|
    ::SimpleCov.command_name command_name
    ::SimpleCov.coverage_dir dir
    ::SimpleCov.start(profile, &block)
  end

  ParallelRSpec::Config.after_fork do |worker_number|
    force_worker_settings.call
    start_simplecov.call(
      "RSpec Worker #{worker_number}",
      File.join(base_dir, "rspec_#{worker_number}"),
    )
  end

  RSpec.configuration.after(:suite) do
    ParallelRSpec::SimpleCov.collate!
  end

  force_worker_settings.call
  start_simplecov.call("RSpec Server", File.join(base_dir, "rspec_server"))

  @simplecov_base_dir = base_dir
  @simplecov_formatters = Array(formatters)
  @simplecov_enabled = true
end