Module: SimpleCov

Extended by:
Configuration
Defined in:
lib/simplecov.rb,
lib/simplecov/cli.rb,
lib/simplecov/color.rb,
lib/simplecov/filter.rb,
lib/simplecov/result.rb,
lib/simplecov/cli/run.rb,
lib/simplecov/combine.rb,
lib/simplecov/process.rb,
lib/simplecov/version.rb,
lib/simplecov/cli/diff.rb,
lib/simplecov/cli/open.rb,
lib/simplecov/last_run.rb,
lib/simplecov/profiles.rb,
lib/simplecov/cli/clean.rb,
lib/simplecov/cli/merge.rb,
lib/simplecov/cli/serve.rb,
lib/simplecov/directive.rb,
lib/simplecov/file_list.rb,
lib/simplecov/formatter.rb,
lib/simplecov/cli/report.rb,
lib/simplecov/exit_codes.rb,
lib/simplecov/cli/dotfile.rb,
lib/simplecov/deprecation.rb,
lib/simplecov/source_file.rb,
lib/simplecov/cli/coverage.rb,
lib/simplecov/cli/uncovered.rb,
lib/simplecov/configuration.rb,
lib/simplecov/exit_handling.rb,
lib/simplecov/result_merger.rb,
lib/simplecov/formatter/base.rb,
lib/simplecov/result_adapter.rb,
lib/simplecov/command_guesser.rb,
lib/simplecov/lines_classifier.rb,
lib/simplecov/source_file/line.rb,
lib/simplecov/parallel_adapters.rb,
lib/simplecov/result_processing.rb,
lib/simplecov/simulate_coverage.rb,
lib/simplecov/source_file/branch.rb,
lib/simplecov/source_file/method.rb,
lib/simplecov/coverage_statistics.rb,
lib/simplecov/coverage_violations.rb,
lib/simplecov/configuration/filters.rb,
lib/simplecov/configuration/merging.rb,
lib/simplecov/parallel_coordination.rb,
lib/simplecov/combine/files_combiner.rb,
lib/simplecov/combine/lines_combiner.rb,
lib/simplecov/configuration/coverage.rb,
lib/simplecov/parallel_adapters/base.rb,
lib/simplecov/source_file/statistics.rb,
lib/simplecov/source_file/skip_chunks.rb,
lib/simplecov/useless_results_remover.rb,
lib/simplecov/combine/methods_combiner.rb,
lib/simplecov/combine/results_combiner.rb,
lib/simplecov/configuration/formatting.rb,
lib/simplecov/configuration/thresholds.rb,
lib/simplecov/formatter/html_formatter.rb,
lib/simplecov/formatter/json_formatter.rb,
lib/simplecov/source_file/line_builder.rb,
lib/simplecov/combine/branches_combiner.rb,
lib/simplecov/formatter/multi_formatter.rb,
lib/simplecov/parallel_adapters/generic.rb,
lib/simplecov/source_file/source_loader.rb,
lib/simplecov/static_coverage_extractor.rb,
lib/simplecov/formatter/simple_formatter.rb,
lib/simplecov/result/source_file_builder.rb,
lib/simplecov/source_file/branch_builder.rb,
lib/simplecov/source_file/method_builder.rb,
lib/simplecov/source_file/builder_context.rb,
lib/simplecov/result_merger/resultset_file.rb,
lib/simplecov/source_file/ruby_data_parser.rb,
lib/simplecov/configuration/ignored_entries.rb,
lib/simplecov/exit_codes/exit_code_handling.rb,
lib/simplecov/result_merger/resultset_store.rb,
lib/simplecov/configuration/coverage_criteria.rb,
lib/simplecov/parallel_adapters/parallel_tests.rb,
lib/simplecov/static_coverage_extractor/visitor.rb,
lib/simplecov/result_merger/legacy_format_adapter.rb,
lib/simplecov/result/missing_source_files_reporter.rb,
lib/simplecov/exit_codes/maximum_coverage_drop_check.rb,
lib/simplecov/exit_codes/maximum_overall_coverage_check.rb,
lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb,
lib/simplecov/exit_codes/minimum_overall_coverage_check.rb,
lib/simplecov/formatter/json_formatter/errors_formatter.rb,
lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb,
lib/simplecov/static_coverage_extractor/method_collector.rb,
lib/simplecov/formatter/json_formatter/result_hash_formatter.rb,
lib/simplecov/formatter/json_formatter/source_file_formatter.rb,
lib/simplecov/static_coverage_extractor/location_conventions.rb,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs,
sig/simplecov.rbs

Overview

Coverage threshold configuration: minimum_coverage, maximum_coverage, expected_coverage, maximum_coverage_drop, refuse_coverage_drop, and the deprecated by-file / by-group forms.

Defined Under Namespace

Modules: CLI, Color, Combine, CommandGuesser, Configuration, CoverageViolations, Deprecation, ExitCodes, Formatter, LastRun, ParallelAdapters, ProcessForkHook, ResultMerger, SimulateCoverage, StaticCoverageExtractor, UselessResultsRemover Classes: ArrayFilter, BlockFilter, ConfigurationError, CoverageLimits, CoverageStatistics, Directive, FileList, Filter, GlobFilter, LinesClassifier, Profiles, RegexFilter, Result, ResultAdapter, SourceFile, StringFilter

Constant Summary collapse

CRITERION_TO_RUBY_COVERAGE =

Maps SimpleCov's criterion names to the keys Coverage.start expects.

Returns:

  • (Hash[Symbol, Symbol])
{
  branch: :branches,
  line: :lines,
  method: :methods,
  oneshot_line: :oneshot_lines
}.freeze
VERSION =

Returns:

  • (String)
"1.0.1"

Constants included from Configuration

Configuration::COVERAGE_THRESHOLD_OPTIONS, Configuration::DEFAULT_COVERAGE_CRITERION, Configuration::IGNORABLE_BRANCH_TYPES, Configuration::IGNORABLE_METHOD_TYPES, Configuration::ONESHOT_LINE_COVERAGE_CRITERION, Configuration::SUPPORTED_COVERAGE_CRITERIA

Class Attribute Summary collapse

Attributes included from Configuration

#filters, #formatter, #groups, #print_error_status

Class Method Summary collapse

Methods included from Configuration

active_session?, add_filter, add_group, apply_threshold_options, at_exit, at_fork, branch_coverage?, branch_coverage_supported?, build_cover_filter, clear_coverage_criteria, clear_filters, collating_result?, collect_cover_globs, color, command_name, configure, cover, cover_filters, cover_globs, coverage, coverage_criteria, coverage_criterion_enabled?, coverage_criterion_supported?, coverage_dir, coverage_for_eval_enabled?, coverage_for_eval_supported?, coverage_path, current_nocov_token, default_primary_coverage, disable_coverage, enable_coverage, enable_coverage_criterion, enable_coverage_for_eval, enable_eval_coverage, enable_eval_coverage_criterion, enable_for_subprocesses, enable_oneshot_line, enabled_for_subprocesses?, expected_coverage, explicit_coverage_destination?, explicit_custom_coverage_destination?, finalize_merge, finalize_merge?, formatters, formatters=, group, ignore_branches, ignore_methods, ignored_branch?, ignored_branches, ignored_method?, ignored_methods, inferred_finalize_merge?, inferred_finalize_merge_warning, maximum_coverage, maximum_coverage_drop, merge_finalization_owner?, merge_subprocesses, merge_timeout, merging, method_coverage?, method_coverage_supported?, minimum_coverage, minimum_coverage_by_file, minimum_coverage_by_file_overrides, minimum_coverage_by_group, minimum_possible_coverage_exceeded, no_default_skips, nocov_token, parallel_tests, parallel_wait_timeout, parallel_worker_environment?, parse_filter, partition_per_file_thresholds, per_file_coverage_replacement, per_group_coverage_replacement, primary_coverage, print_errors, profiles, project_name, raise_if_branch_type_unsupported, raise_if_criterion_disabled, raise_if_criterion_unsupported, raise_if_method_type_unsupported, raise_on_invalid_coverage, refuse_coverage_drop, remove_filter, render_coverage_blocks, restore_ivars, root, skip, source_in_json, store_minimum_per_file, store_minimum_per_group, store_overall_threshold, swap_ivars_from, track_files, track_files_replacement_hint, tracked_files, use_merging, validate_coverage_criteria!, validate_per_file_key, warn_about_inferred_finalize_merge

Class Attribute Details

.external_at_exitBoolean?

Should something external (e.g. the Minitest plugin) own the at_exit behavior instead of SimpleCov's own hook?

Returns:

  • (Boolean, nil)


61
62
63
# File 'lib/simplecov.rb', line 61

def external_at_exit
  @external_at_exit
end

.pidInteger?

Returns the value of attribute pid.

Returns:

  • (Integer, nil)


23
24
25
# File 'lib/simplecov.rb', line 23

def pid
  @pid
end

.process_start_timeTime?

When this process started tracking coverage.

Returns:

  • (Time, nil)


27
28
29
# File 'lib/simplecov.rb', line 27

def process_start_time
  @process_start_time
end

Class Method Details

.at_exit_behaviorObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/simplecov/exit_handling.rb', line 20

def at_exit_behavior
  # If we are in a different process than called start, don't interfere.
  return if SimpleCov.pid != Process.pid

  # If Coverage is no longer running (e.g. someone manually stopped it
  # or a test consumed the result) then don't run exit tasks.
  return unless Coverage.running?

  # Stand down when we'd only clobber a fresher report. See
  # `defer_to_existing_report?` and issue #581.
  return if defer_to_existing_report?

  SimpleCov.run_exit_tasks!
end

.clear_resultvoid

This method returns an undefined value.

Clear the cached result. Primarily useful in testing.



101
102
103
# File 'lib/simplecov/result_processing.rb', line 101

def clear_result
  @result = nil
end

.collate(result_filenames, profile = nil, ignore_timeout: true) ⇒ void

This method returns an undefined value.

Collate a series of resultset files into a single merged report. By default ignores merge_timeout so every listed resultset merges; pass ignore_timeout: false to honor it.

Parameters:

  • result_filenames (Array[String])
  • profile (?(String | Symbol), nil) (defaults to: nil)
  • ignore_timeout: (Boolean) (defaults to: true)


16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/simplecov/result_processing.rb', line 16

def collate(result_filenames, profile = nil, ignore_timeout: true, &)
  raise ArgumentError, "There are no reports to be merged" if result_filenames.empty?

  initial_setup(profile, &)

  # Use the ResultMerger to produce a single, merged result, ready to use.
  @result = ResultMerger.merge_and_store(*result_filenames, ignore_timeout: ignore_timeout)

  @collating_result = true
  run_exit_tasks!
ensure
  @collating_result = false
end

.collating_result?Boolean

Returns:

  • (Boolean)


63
64
65
# File 'lib/simplecov/result_processing.rb', line 63

def collating_result?
  defined?(@collating_result) && @collating_result
end

.coverage_statistics_key(criterion) ⇒ criterion

:oneshot_line stats are folded into the :line bucket, so use the returned criterion to look up coverage_statistics.

Parameters:

  • criterion (criterion, :oneshot_line)

Returns:

  • (criterion)


66
67
68
# File 'lib/simplecov.rb', line 66

def coverage_statistics_key(criterion)
  criterion == :oneshot_line ? :line : criterion
end

.defer_to_existing_report?Boolean

Returns true when our process has no coverage data to contribute (after the resultset merge) and a newer report already exists on disk. Typically fires when SimpleCov.start ran in a parent process — e.g. a Rakefile or Rails' Bundler.require — that shelled out to the test runner. See issue #581.

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
# File 'lib/simplecov/exit_handling.rb', line 40

def defer_to_existing_report?
  return false unless existing_report_newer_than_us?

  res = result
  empty = res.nil? || res.files.empty?
  warn_about_deferred_report if empty
  empty
end

.existing_report_newer_than_us?Boolean

Returns:

  • (Boolean)


49
50
51
52
53
54
# File 'lib/simplecov/exit_handling.rb', line 49

def existing_report_newer_than_us?
  return false unless process_start_time

  last_run_path = File.join(coverage_path, ".last_run.json")
  File.exist?(last_run_path) && File.mtime(last_run_path) > process_start_time
end

.exit_and_report_previous_error(exit_status) ⇒ 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.



98
99
100
101
102
103
104
105
106
# File 'lib/simplecov/exit_handling.rb', line 98

def exit_and_report_previous_error(exit_status)
  if print_errors
    ExitCodes.print_error SimpleCov::Color.colorize(
      "Stopped processing SimpleCov as a previous error not related to SimpleCov has been detected",
      :yellow
    )
  end
  Kernel.exit(exit_status)
end

.exit_status_from_exceptionObject



79
80
81
82
83
84
85
86
87
88
# File 'lib/simplecov/exit_handling.rb', line 79

def exit_status_from_exception
  @exit_exception = $ERROR_INFO
  return nil unless @exit_exception

  if @exit_exception.is_a?(SystemExit)
    @exit_exception.status
  else
    SimpleCov::ExitCodes::EXCEPTION
  end
end

.external_at_exit?Boolean

Coerce to a proper boolean so rspec-mocks 4's predicate matcher (expect(...).not_to be_external_at_exit) accepts the result.

Returns:

  • (Boolean)


72
73
74
# File 'lib/simplecov.rb', line 72

def external_at_exit?
  !!@external_at_exit
end

.filtered(files) ⇒ FileList

Applies the configured filters to the given source files.

Parameters:

Returns:



68
69
70
71
72
73
74
# File 'lib/simplecov/result_processing.rb', line 68

def filtered(files)
  result = files.to_a.dup
  filters.each do |filter|
    result = result.reject { |source_file| filter.matches?(source_file) }
  end
  SimpleCov::FileList.new result
end

.final_result_process?Boolean

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.

Returns:

  • (Boolean)


12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/simplecov/parallel_coordination.rb', line 12

def final_result_process?
  adapter = SimpleCov::ParallelAdapters.current
  # No recognized parallel-test adapter. A subprocess forked while
  # coverage was running is never the final reporter — the process that
  # spawned it merges every slice and produces the report. Without this,
  # fork-based runners that don't set TEST_ENV_NUMBER (e.g. Minitest's
  # `parallelize`) have every worker produce the final report and its
  # warnings. See issue #1171.
  return !forked_subprocess? unless adapter

  adapter.first_worker?
end

.forked_subprocess?Boolean

running (set by SimpleCov::ProcessForkHook in the child). Such a child stores its own slice but must not act as the final-result process: the process that forked it merges every slice and produces the report. Only consulted when no parallel-test adapter is active, since adapters answer first_worker? themselves. See issue #1171.

Returns:

  • (Boolean)


51
52
53
# File 'lib/simplecov.rb', line 51

def forked_subprocess?
  !!(defined?(@forked_subprocess) && @forked_subprocess)
end

.grouped(files, groups: SimpleCov.groups) ⇒ Hash[String, FileList]

Bin the given source files by group filter. Files matched by no group fall into the implicit "Ungrouped" bucket.

Parameters:

Returns:



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/simplecov/result_processing.rb', line 81

def grouped(files, groups: SimpleCov.groups)
  return {} if groups.empty?

  grouped = groups.transform_values do |filter|
    SimpleCov::FileList.new(files.select { |source_file| filter.matches?(source_file) })
  end

  in_group  = grouped_file_set(grouped)
  ungrouped = files.reject { |source_file| in_group.include?(source_file) }
  grouped["Ungrouped"] = SimpleCov::FileList.new(ungrouped) if ungrouped.any?

  grouped
end

.install_at_exit_hookvoid

This method returns an undefined value.

Install the at_exit hook that formats results and runs exit-code checks. Idempotent; SimpleCov.start calls this automatically.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/simplecov.rb', line 129

def install_at_exit_hook
  return if @at_exit_hook_installed

  @at_exit_hook_installed = true
  # Never defer in a forked child: Minitest pins its after_run at_exit
  # to the pid that armed autorun, so the deferral target can't fire
  # there and the child's resultset would be silently dropped. See
  # issue #1227.
  defer_to_minitest_after_run if minitest_autorun_pending? && !forked_subprocess?
  Kernel.at_exit do
    next if SimpleCov.external_at_exit?

    SimpleCov.at_exit_behavior
  end
end

.load_profile(name) ⇒ void

This method returns an undefined value.

Applies the profile of the given name to the configuration.

Parameters:

  • name (String, Symbol)


96
97
98
# File 'lib/simplecov/result_processing.rb', line 96

def load_profile(name)
  profiles.load(name)
end

.mark_forked_subprocess!void

This method returns an undefined value.



56
57
58
# File 'lib/simplecov.rb', line 56

def mark_forked_subprocess!
  @forked_subprocess = true
end

.monotonic_timeObject



102
103
104
# File 'lib/simplecov/parallel_coordination.rb', line 102

def monotonic_time
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
end

.next_subprocess_serial!Integer

child inherits its own ordinal via copy-on-write.

Returns:

  • (Integer)


41
42
43
# File 'lib/simplecov.rb', line 41

def next_subprocess_serial!
  @subprocess_serial = subprocess_serial + 1
end

.parallel_results_complete?Boolean

before the wait deadline. Defaults to true outside a parallel run (when wait_for_other_processes is a no-op).

Returns:

  • (Boolean)


49
50
51
# File 'lib/simplecov/parallel_coordination.rb', line 49

def parallel_results_complete?
  defined?(@parallel_results_complete) ? @parallel_results_complete : true
end

.parallel_wait_timed_out?(deadline, expected, seen) ⇒ Boolean

the first timeout so the user knows the merged total is partial.

Returns:

  • (Boolean)


108
109
110
111
112
113
# File 'lib/simplecov/parallel_coordination.rb', line 108

def parallel_wait_timed_out?(deadline, expected, seen)
  return false unless monotonic_time > deadline

  warn_about_incomplete_parallel_results(expected, seen)
  true
end

.previous_error?(error_exit_status) ⇒ Boolean

accepts it. test_unit sets status 0 on success, so SUCCESS must also be treated as "not a previous error".

Returns:

  • (Boolean)


93
94
95
# File 'lib/simplecov/exit_handling.rb', line 93

def previous_error?(error_exit_status)
  !!(error_exit_status && error_exit_status != SimpleCov::ExitCodes::SUCCESS)
end

.process_result(result) ⇒ Object



135
136
137
138
139
# File 'lib/simplecov/exit_handling.rb', line 135

def process_result(result)
  result_exit_status = result_exit_status(result)
  write_last_run(result) if result_exit_status == SimpleCov::ExitCodes::SUCCESS
  result_exit_status
end

.process_results_and_report_errorObject



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/simplecov/exit_handling.rb', line 120

def process_results_and_report_error
  exit_status = process_result(result)

  # Force exit with stored status (see github issue #5)
  return unless exit_status.positive?

  if print_errors
    ExitCodes.print_error SimpleCov::Color.colorize(
      "SimpleCov failed with exit #{exit_status} due to a coverage related error", :red
    )
  end
  Kernel.exit exit_status
end

.ready_to_process_results?Boolean

only one that reports against thresholds, and only when its wait_for_other_processes confirmed every sibling reported. When the wait times out, the merged total is partial and comparing it against minimum_coverage / maximum_coverage would surface a spurious "below minimum" violation about the missing slice rather than a real shortfall.

Returns:

  • (Boolean)


115
116
117
118
# File 'lib/simplecov/exit_handling.rb', line 115

def ready_to_process_results?
  merge_finalization_owner? && final_result_process? && result? &&
    (collating_result? || parallel_results_complete?)
end

.reset_inherited_at_exit_state!void

This method returns an undefined value.

Reset at_exit state a forked child inherits from its parent (a possibly consumed hook and a Minitest deferral pid-pinned to the parent), so the child re-arms a hook that fires at its own exit. Called by the fork hook; see issue #1227.



24
25
26
27
# File 'lib/simplecov/process.rb', line 24

def reset_inherited_at_exit_state!
  @at_exit_hook_installed = false
  self.external_at_exit = false
end

.resultResult?

The result for the current coverage run, merged across test suites when merging is active. nil when no coverage was tracked.

Returns:



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/simplecov/result_processing.rb', line 34

def result
  return @result if result?

  use_merging = merging

  # Collect our coverage result. When merging is off there is no merge
  # step, so this per-process result is the final one and reports any
  # dropped source files; otherwise the merged result does the reporting.
  process_coverage_result(report: !use_merging) if defined?(Coverage) && Coverage.running?

  # If we're using merging of results, store the current result
  # first (if there is one), then merge the results and return those
  if use_merging
    SimpleCov::ResultMerger.store_result(@result) if result?
    return @result unless finalize_merge?

    wait_for_other_processes
    @result = SimpleCov::ResultMerger.merged_result
  end

  @result
end

.result?Result, ...

The memoized result, or false/nil when it has not been computed yet.

Returns:



58
59
60
# File 'lib/simplecov/result_processing.rb', line 58

def result?
  defined?(@result) && @result
end

.result_exit_status(result) ⇒ Object



141
142
143
# File 'lib/simplecov/exit_handling.rb', line 141

def result_exit_status(result)
  ExitCodes::ExitCodeHandling.call(result, coverage_limits: build_coverage_limits)
end

.resultset_count_settled?(tracker, count) ⇒ Boolean

Track whether the resultset count has held steady (and positive) for PARALLEL_RESULTS_SETTLE seconds. tracker carries the last count and the time it last changed across poll iterations.

Returns:

  • (Boolean)


92
93
94
95
96
97
98
99
100
# File 'lib/simplecov/parallel_coordination.rb', line 92

def resultset_count_settled?(tracker, count)
  if count > tracker[:count]
    tracker[:count] = count
    tracker[:since] = monotonic_time
    return false
  end

  count.positive? && (monotonic_time - tracker[:since]) >= PARALLEL_RESULTS_SETTLE
end

.round_coverage(coverage) ⇒ Numeric

Round coverage down to two decimals.

Parameters:

  • coverage (Numeric)

Returns:

  • (Numeric)


114
115
116
# File 'lib/simplecov/result_processing.rb', line 114

def round_coverage(coverage)
  coverage.floor(2)
end

.run_exit_tasks!Object



69
70
71
72
73
74
75
76
# File 'lib/simplecov/exit_handling.rb', line 69

def run_exit_tasks!
  error_exit_status = exit_status_from_exception

  at_exit.call

  exit_and_report_previous_error(error_exit_status) if previous_error?(error_exit_status)
  process_results_and_report_error if ready_to_process_results?
end

.start(profile = nil) ⇒ void

This method returns an undefined value.

Sets up SimpleCov to run against your project:

SimpleCov.start
SimpleCov.start 'rails'           # using a profile
SimpleCov.start { skip 'test' }   # with a config block

Parameters:

  • profile (?(String | Symbol), nil) (defaults to: nil)


84
85
86
87
88
89
90
# File 'lib/simplecov.rb', line 84

def start(profile = nil, &)
  warn_about_start_in_dot_simplecov if @autoloading_dot_simplecov

  initial_setup(profile, &)
  start_tracking
  install_at_exit_hook
end

.start_trackingvoid

This method returns an undefined value.

Begin coverage tracking without applying configuration. Pairs with SimpleCov.configure { ... }.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/simplecov.rb', line 152

def start_tracking
  require "coverage"
  warn_if_jruby_full_trace_disabled
  validate_coverage_criteria!
  # simplecov:disable — fork-hook is enabled via SimpleCov.enable_for_subprocesses, off by default
  require_relative "simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
                                          ::Process.respond_to?(:_fork)
  # simplecov:enable

  # Trigger adapter selection now so the (possibly lazy) parallel_tests
  # gem load happens at start_tracking time rather than mid-suite.
  # `current` is memoized; subsequent calls are cheap.
  SimpleCov::ParallelAdapters.current

  @result = nil
  self.pid = Process.pid
  self.process_start_time = Time.now

  start_coverage_measurement
end

.subprocess_serialInteger

A monotonically increasing serial assigned to each forked subprocess; the default at_fork builds worker command names from it.

Returns:

  • (Integer)


35
36
37
# File 'lib/simplecov.rb', line 35

def subprocess_serial
  @subprocess_serial ||= 0
end

.wait_for_other_processesObject

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.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/simplecov/parallel_coordination.rb', line 26

def wait_for_other_processes
  adapter = SimpleCov::ParallelAdapters.current
  return unless adapter && final_result_process?

  # Native synchronization first (adapters that wrap a runner with a
  # real "wait" primitive — parallel_tests'
  # `wait_for_other_processes_to_finish` — implement this; adapters
  # without a native API no-op and rely on the polling fallback below).
  adapter.wait_for_siblings

  # The native wait can return before sibling at_exit handlers finish
  # writing resultsets, and adapters without a native wait have
  # nothing else. Either way, poll the resultset cache until all
  # expected workers have reported or a timeout is reached. Capture
  # the outcome so `ready_to_process_results?` can suppress min/max
  # threshold checks against a partial total.
  @parallel_results_complete =
    wait_for_parallel_results(adapter.expected_worker_count, native_wait: adapter.native_wait?)
end

.wait_for_parallel_results(expected, native_wait: false) ⇒ Object

resultset it's going to get, false on timeout. Single-process runs (expected <= 1) short-circuit to true with no waiting.

Normally we poll until expected (= PARALLEL_TEST_GROUPS) workers have reported or SimpleCov.parallel_wait_timeout elapses; raise that setting when a slow worker routinely finishes well after the others.

When a native wait already confirmed every sibling PROCESS exited (native_wait), no further resultset will appear, so a count below expected just means some workers produced none — e.g. parallel_test groups that got no spec file on a machine with more cores than files. Once the count then holds steady for PARALLEL_RESULTS_SETTLE we accept it as final rather than blocking for the whole timeout. Without a native wait (GenericAdapter) we can't tell an idle worker from a slow one, so we keep waiting the full timeout.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/simplecov/parallel_coordination.rb', line 74

def wait_for_parallel_results(expected, native_wait: false)
  return true unless expected > 1 # simplecov:disable branch — only false in real parallel runs

  deadline = monotonic_time + parallel_wait_timeout
  tracker = {count: 0, since: monotonic_time}
  loop do
    seen = SimpleCov::ResultMerger.read_resultset.size
    return true if seen >= expected
    return true if native_wait && resultset_count_settled?(tracker, seen)
    return false if parallel_wait_timed_out?(deadline, expected, seen)

    sleep 0.1
  end
end

.warn_about_deferred_reportObject



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/simplecov/exit_handling.rb', line 56

def warn_about_deferred_report
  return unless print_errors

  ExitCodes.print_error SimpleCov::Color.colorize(
    "Skipping SimpleCov report — this process tracked no application code and a newer " \
    "report already exists at #{coverage_path}. This usually means SimpleCov.start ran in a " \
    "parent process (e.g. a Rakefile or Rails' Bundler.require) that shelled out to the test " \
    "runner. See https://github.com/simplecov-ruby/simplecov/issues/581.",
    :yellow
  )
end

.warn_about_incomplete_parallel_results(expected, seen) ⇒ 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.



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/simplecov/parallel_coordination.rb', line 116

def warn_about_incomplete_parallel_results(expected, seen)
  return unless print_errors

  warn SimpleCov::Color.colorize(
    "Only #{seen} of #{expected} parallel-test workers reported within " \
    "#{parallel_wait_timeout}s, so coverage totals are partial and minimum / " \
    "maximum coverage checks are skipped for this run. Increase " \
    "SimpleCov.parallel_wait_timeout if a worker routinely needs longer.",
    :yellow
  )
end

.warn_about_start_in_dot_simplecovvoid

This method returns an undefined value.



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/simplecov.rb', line 110

def warn_about_start_in_dot_simplecov
  return if @dot_simplecov_start_warned

  @dot_simplecov_start_warned = true
  warn "[DEPRECATION] Calling `SimpleCov.start` from `.simplecov` is deprecated and will " \
       "be removed in a future release. `.simplecov` should contain configuration only; " \
       "move the `SimpleCov.start` call into your `spec_helper.rb` / `test_helper.rb`. " \
       "Coverage tracking still begins for backward compatibility, but a future release " \
       "will require the explicit `SimpleCov.start` from a test helper. " \
       "See https://github.com/simplecov-ruby/simplecov/issues/581."
end

.with_dot_simplecov_autoloadvoid

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.

Mark the duration of a .simplecov auto-load so any SimpleCov.start call inside the file can warn about the impending migration to a config-only file. Tracking still begins for backward compatibility; the warning is the cue to move SimpleCov.start into a test helper. See #581.



99
100
101
102
103
104
105
106
107
108
# File 'lib/simplecov.rb', line 99

def with_dot_simplecov_autoload
  # Read in the ensure clause, where flow analysis cannot see the
  # assignment above; anchor the type here.
  previous = @autoloading_dot_simplecov # : bool?
  @autoloading_dot_simplecov = true
  yield
ensure
  # @type var previous: bool?
  @autoloading_dot_simplecov = previous
end

.write_last_run(result) ⇒ void

This method returns an undefined value.

rounded down (see #679) so the next run can compute drift.

Parameters:



107
108
109
110
111
# File 'lib/simplecov/result_processing.rb', line 107

def write_last_run(result)
  SimpleCov::LastRun.write(
    result: result.coverage_statistics.transform_values { |stats| round_coverage(stats.percent) }
  )
end