Module: SimpleCov

Extended by:
Configuration, RunIdentity::Accessors, TestTracker::Accessors, SingleForwardable
Defined in:
lib/simplecov/production.rb,
lib/simplecov.rb,
lib/simplecov/cli.rb,
lib/simplecov/color.rb,
lib/simplecov/filter.rb,
lib/simplecov/result.rb,
lib/simplecov/cli/git.rb,
lib/simplecov/cli/run.rb,
lib/simplecov/combine.rb,
lib/simplecov/history.rb,
lib/simplecov/process.rb,
lib/simplecov/version.rb,
lib/simplecov/baseline.rb,
lib/simplecov/cli/diff.rb,
lib/simplecov/cli/open.rb,
lib/simplecov/cli/show.rb,
lib/simplecov/last_run.rb,
lib/simplecov/profiles.rb,
lib/simplecov/cli/badge.rb,
lib/simplecov/cli/clean.rb,
lib/simplecov/cli/merge.rb,
lib/simplecov/cli/patch.rb,
lib/simplecov/cli/serve.rb,
lib/simplecov/cli/tests.rb,
lib/simplecov/cli/usage.rb,
lib/simplecov/cli/watch.rb,
lib/simplecov/directive.rb,
lib/simplecov/file_list.rb,
lib/simplecov/formatter.rb,
lib/simplecov/cli/report.rb,
lib/simplecov/cli/status.rb,
lib/simplecov/exit_codes.rb,
lib/simplecov/atomic_file.rb,
lib/simplecov/cli/dotfile.rb,
lib/simplecov/cli/history.rb,
lib/simplecov/cli/ratchet.rb,
lib/simplecov/context_map.rb,
lib/simplecov/current_run.rb,
lib/simplecov/deprecation.rb,
lib/simplecov/group_names.rb,
lib/simplecov/source_file.rb,
lib/simplecov/cli/affected.rb,
lib/simplecov/cli/coverage.rb,
lib/simplecov/report_stamp.rb,
lib/simplecov/run_identity.rb,
lib/simplecov/test_tracker.rb,
lib/simplecov/cli/badge/svg.rb,
lib/simplecov/cli/dead_code.rb,
lib/simplecov/cli/uncovered.rb,
lib/simplecov/configuration.rb,
lib/simplecov/coverage_json.rb,
lib/simplecov/directive/erb.rb,
lib/simplecov/exit_handling.rb,
lib/simplecov/result_merger.rb,
lib/simplecov/view_coverage.rb,
lib/simplecov/cli/show/sweep.rb,
lib/simplecov/directive/haml.rb,
lib/simplecov/directive/slim.rb,
lib/simplecov/formatter/base.rb,
lib/simplecov/result_adapter.rb,
lib/simplecov/baseline/parser.rb,
lib/simplecov/cli/annotations.rb,
lib/simplecov/cli/completions.rb,
lib/simplecov/cli/diff/output.rb,
lib/simplecov/command_guesser.rb,
lib/simplecov/report_deferral.rb,
lib/simplecov/cli/patch/output.rb,
lib/simplecov/cli/status/facts.rb,
lib/simplecov/cli/watch/poller.rb,
lib/simplecov/exit_codes/check.rb,
lib/simplecov/lines_classifier.rb,
lib/simplecov/production/error.rb,
lib/simplecov/source_file/line.rb,
lib/simplecov/cli/coverage_file.rb,
lib/simplecov/cli/watch/session.rb,
lib/simplecov/context_map/union.rb,
lib/simplecov/parallel_adapters.rb,
lib/simplecov/result_processing.rb,
lib/simplecov/simulate_coverage.rb,
lib/simplecov/cli/history/output.rb,
lib/simplecov/cli/ratchet/output.rb,
lib/simplecov/cli/show/annotator.rb,
lib/simplecov/cli/watch/narrator.rb,
lib/simplecov/directive/template.rb,
lib/simplecov/source_file/branch.rb,
lib/simplecov/source_file/method.rb,
lib/simplecov/test_tracker/delta.rb,
lib/simplecov/cli/command_helpers.rb,
lib/simplecov/cli/watch/test_plan.rb,
lib/simplecov/configuration_error.rb,
lib/simplecov/coverage_statistics.rb,
lib/simplecov/coverage_violations.rb,
lib/simplecov/cli/dead_code/output.rb,
lib/simplecov/cli/tests/redundancy.rb,
lib/simplecov/cli/uncovered/misses.rb,
lib/simplecov/configuration/groups.rb,
lib/simplecov/production/file_sink.rb,
lib/simplecov/result/filter_config.rb,
lib/simplecov/result/serialization.rb,
lib/simplecov/cli/watch/live_report.rb,
lib/simplecov/configuration/filters.rb,
lib/simplecov/configuration/history.rb,
lib/simplecov/configuration/merging.rb,
lib/simplecov/parallel_coordination.rb,
lib/simplecov/cli/affected/selection.rb,
lib/simplecov/combine/lines_combiner.rb,
lib/simplecov/configuration/baseline.rb,
lib/simplecov/configuration/coverage.rb,
lib/simplecov/parallel_adapters/base.rb,
lib/simplecov/parallel_result_merger.rb,
lib/simplecov/result_merger/contexts.rb,
lib/simplecov/source_file/statistics.rb,
lib/simplecov/test_tracker/accessors.rb,
lib/simplecov/unloaded_file_injector.rb,
lib/simplecov/cli/completions/scripts.rb,
lib/simplecov/cli/patch/changed_lines.rb,
lib/simplecov/combine/interned_counts.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/production.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/cli/serve/report_preparer.rb,
lib/simplecov/combine/branches_combiner.rb,
lib/simplecov/combine/identity_interner.rb,
lib/simplecov/configuration/missed_caps.rb,
lib/simplecov/exit_codes/baseline_check.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/cli/affected/changed_files.rb,
lib/simplecov/configuration/deprecations.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/configuration/eval_coverage.rb,
lib/simplecov/configuration/test_tracking.rb,
lib/simplecov/configuration/view_coverage.rb,
lib/simplecov/directive/indented_template.rb,
lib/simplecov/source_file/builder_context.rb,
lib/simplecov/test_tracker/constant_watch.rb,
lib/simplecov/combine/coverage_accumulator.rb,
lib/simplecov/formatter/baseline_formatter.rb,
lib/simplecov/result_merger/resultset_file.rb,
lib/simplecov/result_merger/unloaded_files.rb,
lib/simplecov/source_file/ruby_data_parser.rb,
lib/simplecov/test_tracker/framework_hooks.rb,
lib/simplecov/cli/serve/static_file_handler.rb,
lib/simplecov/configuration/ignored_entries.rb,
lib/simplecov/exit_codes/exit_code_handling.rb,
lib/simplecov/result_merger/resultset_store.rb,
lib/simplecov/formatter/coverage_json_writer.rb,
lib/simplecov/configuration/coverage_criteria.rb,
lib/simplecov/exit_codes/maximum_missed_check.rb,
lib/simplecov/view_coverage/template_compiler.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/result_merger/resultset_run_identity.rb,
lib/simplecov/parallel_result_merger/worker_payload.rb,
lib/simplecov/exit_codes/maximum_coverage_drop_check.rb,
lib/simplecov/static_coverage_extractor/prism_compat.rb,
lib/simplecov/exit_codes/maximum_missed_per_file_check.rb,
lib/simplecov/static_coverage_extractor/value_position.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/static_coverage_extractor/condition_folding.rb,
lib/simplecov/formatter/html_formatter/viewer_data_validator.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,
lib/simplecov/formatter/json_formatter/production_section_formatter.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,
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

simplecov:disable Methods below only fire under a parallel test runner; not reachable from a single-process rspec run. Cucumber's test_projects exercise the parallel_tests integration end-to-end in subprocesses, but those subprocesses don't merge their Coverage data back into the parent this dogfood report measures.

Defined Under Namespace

Modules: AtomicFile, CLI, Color, Combine, CommandGuesser, Configuration, CoverageJSON, CoverageViolations, Deprecation, ExitCodes, Formatter, GroupNames, History, LastRun, ParallelAdapters, ParallelResultMerger, ProcessForkHook, Production, ReportStamp, ResultMerger, RunIdentity, SimulateCoverage, StaticCoverageExtractor, UnloadedFileInjector, UselessResultsRemover, ViewCoverage Classes: ArrayFilter, Baseline, BlockFilter, ConfigurationError, ContextMap, CoverageLimits, CoverageStatistics, CurrentRun, Directive, FileList, Filter, GlobFilter, LinesClassifier, Profiles, RegexFilter, Result, ResultAdapter, SourceFile, StringFilter, TestTracker

Constant Summary collapse

CRITERION_TO_RUBY_COVERAGE =

At module scope rather than inside class << self so it can be declared in the RBS signatures; lexical scoping keeps references inside the singleton class working.

Returns:

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

Returns:

  • (String)
"1.3.0"

Constants included from Configuration

Configuration::BUILT_IN_FORMATS, Configuration::COVERAGE_THRESHOLD_OPTIONS, Configuration::DEFAULT_COVERAGE_CRITERION, Configuration::DEFAULT_VIEW_GLOBS, Configuration::DEPRECATION_MODES, Configuration::DROP_BASELINES, Configuration::IGNORABLE_BRANCH_TYPES, Configuration::IGNORABLE_METHOD_TYPES, Configuration::LAZY_FORMAT_REQUIRES, Configuration::LINE_COVERAGE_ALTERNATIVES, Configuration::ONESHOT_LINE_COVERAGE_CRITERION, Configuration::SUPPORTED_COVERAGE_CRITERIA, Configuration::TRACK_TESTS_GRANULARITIES

Class Attribute Summary collapse

Attributes included from Configuration

#filters, #formatter, #groups, #print_error_status

Class Method Summary collapse

Methods included from Configuration

__send__, active_session?, add_coverage_criterion, add_filter, add_group, apply_threshold_options, at_exit, at_fork, baseline, baseline_file, baseline_file=, branch_coverage?, branch_coverage_supported?, build_cover_filter, clear_coverage_criteria, clear_filters, collating_result?, collect_cover_globs, color, color=, combined_formatter, command_name, command_name=, configure, cover, cover_filters, cover_globs, cover_views, coverage, coverage_criteria, coverage_criterion_enabled?, coverage_criterion_supported?, coverage_dir, coverage_dir=, coverage_for_eval_enabled?, coverage_for_eval_supported?, coverage_path, coverage_path=, coverage_running?, current_nocov_token, default_groups, default_primary_coverage, deprecations, disable_coverage, disable_eval_coverage, drop_baseline, enable_coverage, enable_coverage_criterion, enable_coverage_for_eval, enable_eval_coverage, enable_for_subprocesses, enabled_for_subprocesses?, env_merge_timeout, expected_coverage, explicit_coverage_destination?, explicit_custom_coverage_destination?, final_result_process?, finalize_merge, finalize_merge=, finalize_merge?, formats, formatters, formatters=, group, history_limit, history_limit=, ignore_branches, ignore_methods, ignored_branch?, ignored_branches, ignored_method?, ignored_methods, inferred_finalize_merge?, inferred_finalize_merge_warning, line_coverage?, load_coverage, maximum_coverage, maximum_coverage_drop, maximum_missed, maximum_missed_per_file, maximum_missed_per_file_overrides, merge_finalization_owner?, merge_subprocesses, merge_subprocesses=, merge_timeout, merge_timeout=, merging, 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, missed_per_file_replacement, no_default_skips, nocov_token, normalized_missed_caps, normalized_threshold, parallel_tests, parallel_tests=, parallel_wait_timeout, parallel_wait_timeout=, parallel_worker_environment?, parse_filter, partition_per_file_thresholds, per_file_coverage_replacement, per_group_coverage_replacement, primary_coverage, primary_coverage=, print_errors, print_errors=, production_coverage, production_coverage=, 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, raise_on_invalid_missed_cap, refuse_coverage_drop, remove_filter, render_coverage_blocks, require_html_formatter, resolve_criterion_variant, resolve_format, root, root=, skip, source_in_json, source_in_json=, store_ignored_branches, store_ignored_methods, store_maximum_missed_per_file, store_minimum_per_file, store_minimum_per_group, store_missed_cap, store_overall_threshold, track_files, track_files_replacement_hint, track_tests, track_tests?, track_tests_granularity, tracked_files, use_merging, validate_coverage_criteria!, validate_per_file_key, validate_test_tracking!, view_coverage?, view_globs, warn_about_inferred_finalize_merge

Methods included from TestTracker::Accessors

start_test_tracking, test_tracker, track_test

Methods included from RunIdentity::Accessors

run_id, worker_id

Class Attribute Details

.current_runCurrentRun

Returns:



29
30
31
# File 'lib/simplecov.rb', line 29

def current_run
  @current_run ||= CurrentRun.new
end

.external_at_exitBoolean?

Returns the value of attribute external_at_exit.

Returns:

  • (Boolean, nil)


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

def external_at_exit
  @external_at_exit
end

.pidInteger?

Returns the value of attribute pid.

Returns:

  • (Integer, nil)


36
37
38
# File 'sig/simplecov.rbs', line 36

def pid
  @pid
end

.process_start_timeTime?

Returns the value of attribute process_start_time.

Returns:

  • (Time, nil)


38
39
40
# File 'sig/simplecov.rbs', line 38

def process_start_time
  @process_start_time
end

Class Method Details

.at_exit_behaviorObject



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

def at_exit_behavior
  # A different process than the one that called start; don't interfere.
  return unless started_in_this_process?

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

  # Captured BEFORE the deferral probe: its freshness check rescues
  # filesystem errors, and completing any rescue inside an at_exit handler
  # resets $ERROR_INFO to nil.
  error_exit_status = exit_status_from_exception

  # Stand down when we'd only clobber a fresher report (#581).
  return if defer_to_existing_report?

  run_exit_tasks!(error_exit_status)
end

.clear_resultvoid

This method returns an undefined value.



83
84
85
# File 'lib/simplecov/result_processing.rb', line 83

def clear_result
  current_run.result = nil
end

.collate(result_filenames, profile = nil, processes: ENV["SIMPLECOV_CONCURRENCY"].to_i, ignore_timeout: true) ⇒ void

This method returns an undefined value.

By default collate ignores the merge_timeout so all results in all files specified will be merged. Pass ignore_timeout: false to honor it.

processes: above 1 fans the merge out across that many forked workers. The report is identical either way, not merely equivalent. The count is deliberately not clamped to the machine's core count nor gated on a minimum number of resultsets: what a collate job can afford is the caller's call. Anything below 1 is taken as 1, so an unset SIMPLECOV_CONCURRENCY needs no default of its own.

Parameters:

  • result_filenames (Array[String])
  • profile (?(String | Symbol), nil) (defaults to: nil)
  • processes: (Integer) (defaults to: ENV["SIMPLECOV_CONCURRENCY"].to_i)
  • ignore_timeout: (Boolean) (defaults to: true)


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

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

  initial_setup(profile, &)

  current_run.result = ParallelResultMerger.merge_and_store(*result_filenames, processes: [1, processes].max,
    ignore_timeout: ignore_timeout)

  current_run.collating_result = true
  run_exit_tasks!
ensure
  current_run.collating_result = false
end

.collating_result?boolish

Returns:

  • (boolish)


104
# File 'sig/simplecov.rbs', line 104

def self.collating_result?: () -> boolish

.collect_own_coverage(standalone:) ⇒ void

This method returns an undefined value.

standalone is true when no merge step follows, which makes this the final result: the one that reports dropped source files and injects unloaded files. When a merge does follow, both jobs belong to the merge.

Parameters:

  • standalone: (Boolean)


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

def collect_own_coverage(standalone:)
  return unless defined?(Coverage) && Coverage.running?

  process_coverage_result(report: standalone, inject_unloaded: standalone)
end

.coverage_statistics_key(criterion) ⇒ criterion

:oneshot_line data is folded into the :line bucket of coverage_statistics by ResultAdapter. The cast is steep's: it narrows a union on == but not on equal?.

Parameters:

  • criterion (criterion, :oneshot_line)

Returns:

  • (criterion)


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

def coverage_statistics_key(criterion)
  criterion.equal?(:oneshot_line) ? :line : _ = criterion
end

.current_parallel_worker_countObject



78
79
80
81
# File 'lib/simplecov/parallel_coordination.rb', line 78

def current_parallel_worker_count
  resultset = ResultMerger.read_resultset
  ResultMerger.worker_identities_for_run(resultset, run_id, process_start_time).size
end

.defer_to_existing_report?Boolean

Returns:

  • (Boolean)


10
11
12
13
14
15
16
17
# File 'lib/simplecov/report_deferral.rb', line 10

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

.last_run.json only exists after fully successful runs, so alone it left the backstop inert when the child run failed, the case where clobbering its report hurts most. The report stamp is touched by every formatting process regardless of exit status. The rescue covers a file vanishing mid-at_exit.

Returns:

  • (Boolean)


23
24
25
26
27
28
29
30
31
# File 'lib/simplecov/report_deferral.rb', line 23

def existing_report_newer_than_us?
  return false unless process_start_time

  [LastRun.last_run_path, ReportStamp.path].any? do |path|
    File.mtime(path) > process_start_time
  rescue SystemCallError
    false
  end
end

.exit_status_from_exceptionObject

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.



72
73
74
75
76
77
78
79
80
81
# File 'lib/simplecov/exit_handling.rb', line 72

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

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

.external_at_exit?Boolean

Coerced so rspec-mocks 4's predicate matcher accepts the result.

Returns:

  • (Boolean)


46
47
48
# File 'lib/simplecov.rb', line 46

def external_at_exit?
  !!@external_at_exit
end

.filtered(files) ⇒ FileList

Parameters:

Returns:



55
56
57
58
59
60
61
# File 'lib/simplecov/result_processing.rb', line 55

def filtered(files)
  result = files.to_a
  filters.each do |filter|
    result = result.reject { |source_file| filter.matches?(source_file) }
  end
  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
# File 'lib/simplecov/parallel_coordination.rb', line 12

def final_result_process?
  adapter = ParallelAdapters.current
  # 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 (Minitest's `parallelize`) have every worker produce
  # the final report and its warnings (#1171).
  return !forked_subprocess? unless adapter

  adapter.first_worker?
end

.forked_subprocess?Boolean

Returns:

  • (Boolean)


58
# File 'sig/simplecov.rbs', line 58

def self.forked_subprocess?: () -> bool

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

Files matched by no group fall into the implicit "Ungrouped" bucket. Any group left empty, Ungrouped included, is dropped so a profile's unused groups (#1293) don't pad the report as 100% covered.

Parameters:

Returns:



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/simplecov/result_processing.rb', line 66

def grouped(files, groups: default_groups)
  return {} if GroupNames.validate!(groups.keys).empty?

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

  in_group = grouped_file_set(grouped)
  grouped[GroupNames::UNGROUPED] = FileList.new(files.reject { |source_file| in_group.include?(source_file) })

  grouped.reject { |_name, group_files| group_files.empty? }
end

.inject_unloaded_files(result, candidate_paths, synthesize: nil, lines: nil) ⇒ [Hash[String, untyped], Set[String]]

only because the merge runs in another object, on behalf of processes whose configuration it may not share, so it supplies the paths itself.

Parameters:

  • result (Hash[String, untyped])
  • candidate_paths (Array[String])
  • synthesize: (Boolean, nil) (defaults to: nil)
  • lines: (Boolean, nil) (defaults to: nil)

Returns:

  • ([Hash[String, untyped], Set[String]])


102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/simplecov/result_processing.rb', line 102

def inject_unloaded_files(result, candidate_paths, synthesize: nil, lines: nil)
  return [result, Set.new] if candidate_paths.empty?

  # Synthesizing branch and method tuples means parsing every tracked file
  # that wasn't loaded, about half the cost of simulating one, and nothing
  # reads those tuples when neither criterion is enabled. The same goes for
  # line data, which a branch-only or method-only run neither reports nor
  # receives from `Coverage` for the files it loaded (#1250).
  UnloadedFileInjector.call(
    result, candidate_paths,
    synthesize: synthesize.nil? ? branch_coverage? || method_coverage? : synthesize,
    lines: lines.nil? ? line_coverage? : lines
  )
end

.install_at_exit_hookvoid

This method returns an undefined value.



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

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 (#1227).
  defer_to_minitest_after_run if minitest_autorun_pending? && !forked_subprocess?
  Kernel.at_exit do
    next if external_at_exit?

    at_exit_behavior
  end
end

.load_profile(name) ⇒ void

This method returns an undefined value.

Parameters:

  • name (String, Symbol)


79
80
81
# File 'lib/simplecov/result_processing.rb', line 79

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

.mark_forked_subprocess!void

This method returns an undefined value.



60
# File 'sig/simplecov.rbs', line 60

def self.mark_forked_subprocess!: () -> void

.merge_own_sliceObject

Returns:

  • (Object)


38
39
40
41
42
43
44
# File 'lib/simplecov/result_processing.rb', line 38

def merge_own_slice
  ResultMerger.store_result(result) if result?
  return unless merge_finalization_owner?

  wait_for_other_processes
  current_run.result = ResultMerger.merged_result
end

.monotonic_timeObject



97
98
99
# File 'lib/simplecov/parallel_coordination.rb', line 97

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

.next_subprocess_serial!Integer

Returns:

  • (Integer)


56
# File 'sig/simplecov.rbs', line 56

def self.next_subprocess_serial!: () -> Integer

.parallel_results_complete?Boolean

wait deadline. Defaults to true outside a parallel run.

Returns:

  • (Boolean)


44
45
46
# File 'lib/simplecov/parallel_coordination.rb', line 44

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

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

total is partial.

Returns:

  • (Boolean)


103
104
105
106
107
108
# File 'lib/simplecov/parallel_coordination.rb', line 103

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)


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

def previous_error?(error_exit_status)
  return false unless error_exit_status

  !successful?(error_exit_status)
end

.process_result(result) ⇒ Object

condition .last_run.json uses, so a run that failed its thresholds becomes neither the drop baseline nor a data point in the trend.



127
128
129
130
131
132
133
134
# File 'lib/simplecov/exit_handling.rb', line 127

def process_result(result)
  result_exit_status = result_exit_status(result)
  if successful?(result_exit_status)
    write_last_run(result)
    History.record(result)
  end
  result_exit_status
end

.ready_to_process_results?Boolean

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 the thresholds would surface a spurious violation about the missing slice.

Returns:

  • (Boolean)


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

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

.report_previous_errorObject

caller's to answer with.



94
95
96
97
98
99
100
101
# File 'lib/simplecov/exit_handling.rb', line 94

def report_previous_error
  return unless print_errors

  ExitCodes.print_error Color.colorize(
    "Stopped processing SimpleCov as a previous error not related to SimpleCov has been detected",
    :yellow
  )
end

.report_processing_failure(exit_status) ⇒ Object

it is a coverage failure worth explaining.



115
116
117
118
119
120
121
122
# File 'lib/simplecov/exit_handling.rb', line 115

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

.reset_inherited_at_exit_state!void

This method returns an undefined value.

Forked children inherit at_exit state that is wrong for them: before forking (Minitest autorun runs the suite inside the parent's at_exit), and external_at_exit may point at a Minitest.after_run deferral that is pid-pinned to the parent. Resetting both is what lets the at_fork proc's SimpleCov.start install a hook that actually fires (#1227).



11
12
13
14
# File 'lib/simplecov/process.rb', line 11

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

.resultResult?

Returns:



29
30
31
32
33
34
35
36
# File 'lib/simplecov/result_processing.rb', line 29

def result
  return current_run.result if result?

  merge = merging
  collect_own_coverage(standalone: !merge)
  merge_own_slice if merge
  current_run.result
end

.result?Result, ...

Returns:



102
# File 'sig/simplecov.rbs', line 102

def self.result?: () -> (Result | false | nil)

.result_exit_status(result) ⇒ Object



149
150
151
# File 'lib/simplecov/exit_handling.rb', line 149

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

.resultset_count_settled?(tracker, count) ⇒ Boolean

tracker carries the last count and the time it last changed across poll iterations. Answered through an if/else rather than an early return because falling through after a climb would read the clock a second time and answer the same false anyway.

Returns:

  • (Boolean)


87
88
89
90
91
92
93
94
95
# File 'lib/simplecov/parallel_coordination.rb', line 87

def resultset_count_settled?(tracker, count)
  if count > tracker.fetch(:count)
    tracker[:count] = count
    tracker[:since] = monotonic_time
    false
  else
    count.positive? && (monotonic_time - tracker.fetch(:since)) >= PARALLEL_RESULTS_SETTLE
  end
end

.round_coverage(coverage) ⇒ Numeric

Parameters:

  • coverage (Numeric)

Returns:

  • (Numeric)


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

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

.run_exit_tasks(error_exit_status = exit_status_from_exception) ⇒ Object

exit status the process should end with rather than performed as an exit. The one side effect left to the caller is ending the process, which is what makes this whole path answerable from inside a test.



49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/simplecov/exit_handling.rb', line 49

def run_exit_tasks(error_exit_status = exit_status_from_exception)
  at_exit.call

  if previous_error?(error_exit_status)
    report_previous_error
    error_exit_status
  elsif ready_to_process_results?
    report_processing_failure(process_result(result))
  else
    ExitCodes::SUCCESS
  end
end

.run_exit_tasks!(error_exit_status = exit_status_from_exception) ⇒ Object

at_exit block (which pre-captures the status, see there) and by collate.



64
65
66
67
68
69
# File 'lib/simplecov/exit_handling.rb', line 64

def run_exit_tasks!(error_exit_status = exit_status_from_exception)
  status = run_exit_tasks(error_exit_status)

  # Force exit with stored status (#5).
  Kernel.exit(status) unless successful?(status)
end

.run_idString

Returns:

  • (String)


40
# File 'sig/simplecov.rbs', line 40

def self.run_id: () -> String

.start(profile = nil) ⇒ void

This method returns an undefined value.

Parameters:

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


50
51
52
53
54
55
56
# File 'lib/simplecov.rb', line 50

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_test_trackingvoid

This method returns an undefined value.



48
# File 'sig/simplecov.rbs', line 48

def self.start_test_tracking: () -> void

.start_trackingvoid

This method returns an undefined value.



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

def start_tracking
  require "coverage"
  warn_if_jruby_full_trace_disabled
  validate_coverage_criteria!
  require_relative "simplecov/process" if enabled_for_subprocesses? && Process.respond_to?(:_fork)

  # Must happen before any forks.
  RunIdentity.prepare

  self.current_run = current_run.successor
  self.pid = Process.pid
  self.process_start_time = Time.now

  start_coverage_measurement
end

.started_in_this_process?Boolean

mutant:disable -- a pid is an Integer, and Integers answer ==, eql? and equal? alike for the same value.

Returns:

  • (Boolean)


138
139
140
# File 'lib/simplecov/exit_handling.rb', line 138

def started_in_this_process?
  SimpleCov.pid == Process.pid
end

.subprocess_serialInteger

Returns:

  • (Integer)


54
# File 'sig/simplecov.rbs', line 54

def self.subprocess_serial: () -> Integer

.successful?(status) ⇒ Boolean

Asked as a predicate rather than compared against ExitCodes::SUCCESS, because two equal Integers are equal through every spelling of the comparison.

Returns:

  • (Boolean)


145
146
147
# File 'lib/simplecov/exit_handling.rb', line 145

def successful?(status)
  status.zero?
end

.test_trackerTestTracker?

Returns:



46
# File 'sig/simplecov.rbs', line 46

def self.test_tracker: () -> TestTracker?

.track_testvoid

This method returns an undefined value.



44
# File 'sig/simplecov.rbs', line 44

def self.track_test: [T] (String test_id) { () -> T } -> T

.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.



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

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

  # Adapters that wrap a runner with a real "wait" primitive implement
  # this; the rest 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. The outcome is captured so
  # threshold checks can be suppressed 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

going to get, false on timeout. Single-process runs short-circuit.

Normally we poll until expected workers have reported or SimpleCov.parallel_wait_timeout elapses. When a native wait already confirmed every sibling process exited, no further resultset will appear, so a count below expected just means some workers produced none, and once the count holds steady for PARALLEL_RESULTS_SETTLE we accept it as final. Without a native wait we can't tell an idle worker from a slow one, so we keep waiting the full timeout.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/simplecov/parallel_coordination.rb', line 63

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 = current_parallel_worker_count
    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



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/simplecov/report_deferral.rb', line 33

def warn_about_deferred_report
  return unless print_errors

  ExitCodes.print_error 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.



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

def warn_about_incomplete_parallel_results(expected, seen)
  return unless print_errors

  warn 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.



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

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.



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

def with_dot_simplecov_autoload
  previous = @autoloading_dot_simplecov # : bool?
  @autoloading_dot_simplecov = true
  yield
ensure
  # @type var previous: bool?
  @autoloading_dot_simplecov = previous
end

.worker_idString

Returns:

  • (String)


42
# File 'sig/simplecov.rbs', line 42

def self.worker_id: () -> String

.write_last_run(result) ⇒ void

This method returns an undefined value.

Parameters:



88
89
90
91
92
# File 'lib/simplecov/result_processing.rb', line 88

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