Module: SimpleCov
- Extended by:
- Configuration, RunIdentity::Accessors
- 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/atomic_file.rb,
lib/simplecov/cli/dotfile.rb,
lib/simplecov/deprecation.rb,
lib/simplecov/group_names.rb,
lib/simplecov/source_file.rb,
lib/simplecov/cli/coverage.rb,
lib/simplecov/report_stamp.rb,
lib/simplecov/run_identity.rb,
lib/simplecov/cli/uncovered.rb,
lib/simplecov/configuration.rb,
lib/simplecov/coverage_json.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/report_deferral.rb,
lib/simplecov/exit_codes/check.rb,
lib/simplecov/lines_classifier.rb,
lib/simplecov/source_file/line.rb,
lib/simplecov/cli/coverage_file.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/cli/command_helpers.rb,
lib/simplecov/coverage_statistics.rb,
lib/simplecov/coverage_violations.rb,
lib/simplecov/configuration/groups.rb,
lib/simplecov/configuration/filters.rb,
lib/simplecov/configuration/merging.rb,
lib/simplecov/parallel_coordination.rb,
lib/simplecov/combine/lines_combiner.rb,
lib/simplecov/configuration/coverage.rb,
lib/simplecov/parallel_adapters/base.rb,
lib/simplecov/parallel_result_merger.rb,
lib/simplecov/source_file/statistics.rb,
lib/simplecov/unloaded_file_injector.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/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/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/configuration/eval_coverage.rb,
lib/simplecov/source_file/builder_context.rb,
lib/simplecov/combine/coverage_accumulator.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/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/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/exit_codes/maximum_coverage_drop_check.rb,
lib/simplecov/static_coverage_extractor/prism_compat.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,
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
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: AtomicFile, CLI, Color, Combine, CommandGuesser, Configuration, CoverageJSON, CoverageViolations, Deprecation, ExitCodes, Formatter, GroupNames, LastRun, ParallelAdapters, ParallelResultMerger, ProcessForkHook, ReportStamp, ResultMerger, RunIdentity, SimulateCoverage, StaticCoverageExtractor, UnloadedFileInjector, 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.startexpects. { branch: :branches, line: :lines, method: :methods, oneshot_line: :oneshot_lines }.freeze
- VERSION =
"1.1.1"
Constants included from Configuration
Configuration::COVERAGE_THRESHOLD_OPTIONS, Configuration::DEFAULT_COVERAGE_CRITERION, Configuration::IGNORABLE_BRANCH_TYPES, Configuration::IGNORABLE_METHOD_TYPES, Configuration::LINE_COVERAGE_ALTERNATIVES, Configuration::ONESHOT_LINE_COVERAGE_CRITERION, Configuration::SUPPORTED_COVERAGE_CRITERIA
Class Attribute Summary collapse
-
.external_at_exit ⇒ Boolean?
Should something external (e.g. the Minitest plugin) own the at_exit behavior instead of SimpleCov's own hook?.
-
.pid ⇒ Integer?
Returns the value of attribute pid.
-
.process_start_time ⇒ Time?
When this process started tracking coverage.
Attributes included from Configuration
#filters, #formatter, #groups, #print_error_status
Class Method Summary collapse
- .at_exit_behavior ⇒ Object
-
.clear_result ⇒ void
Clear the cached result.
-
.collate(result_filenames, profile = nil, processes: ENV.fetch("SIMPLECOV_CONCURRENCY", 1).to_i, ignore_timeout: true) ⇒ void
Collate a series of resultset files into a single merged report.
- .collating_result? ⇒ Boolean
-
.collect_own_coverage(standalone:) ⇒ void
Build this process's slice of the coverage result.
-
.coverage_statistics_key(criterion) ⇒ criterion
:oneshot_linestats are folded into the:linebucket, so use the returned criterion to look upcoverage_statistics. - .current_parallel_worker_count ⇒ Object
-
.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.
-
.existing_report_newer_than_us? ⇒ Boolean
.last_run.jsononly 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. - .exit_and_report_previous_error(exit_status) ⇒ Object private
- .exit_status_from_exception ⇒ Object
-
.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. -
.filtered(files) ⇒ FileList
Applies the configured filters to the given source files.
- .final_result_process? ⇒ Boolean private
-
.forked_subprocess? ⇒ Boolean
running (set by SimpleCov::ProcessForkHook in the child).
-
.grouped(files, groups: SimpleCov.groups) ⇒ Hash[String, FileList]
Bin the given source files by group filter.
-
.inject_unloaded_files(result, candidate_paths, synthesize: nil, lines: nil) ⇒ [Hash[String, untyped], Set[String]]
Add simulated coverage for each of
candidate_pathsthe result doesn't already carry, and return it with the set of paths added. -
.install_at_exit_hook ⇒ void
Install the at_exit hook that formats results and runs exit-code checks.
-
.load_profile(name) ⇒ void
Applies the profile of the given name to the configuration.
- .mark_forked_subprocess! ⇒ void
- .monotonic_time ⇒ Object
-
.next_subprocess_serial! ⇒ Integer
child inherits its own ordinal via copy-on-write.
-
.parallel_results_complete? ⇒ Boolean
before the wait deadline.
-
.parallel_wait_timed_out?(deadline, expected, seen) ⇒ Boolean
the first timeout so the user knows the merged total is partial.
-
.previous_error?(error_exit_status) ⇒ Boolean
accepts it.
- .process_result(result) ⇒ Object
- .process_results_and_report_error ⇒ Object
-
.ready_to_process_results? ⇒ Boolean
only one that reports against thresholds, and only when its
wait_for_other_processesconfirmed every sibling reported. -
.reset_inherited_at_exit_state! ⇒ void
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.
-
.result ⇒ Result?
The result for the current coverage run, merged across test suites when merging is active.
-
.result? ⇒ Result, ...
The memoized result, or false/nil when it has not been computed yet.
- .result_exit_status(result) ⇒ Object
-
.resultset_count_settled?(tracker, count) ⇒ Boolean
Track whether the resultset count has held steady (and positive) for
PARALLEL_RESULTS_SETTLEseconds. -
.round_coverage(coverage) ⇒ Numeric
Round coverage down to two decimals.
-
.run_exit_tasks!(error_exit_status = exit_status_from_exception) ⇒ Object
the status, see there) and by
collate(the default argument). - .run_id ⇒ String
-
.start(profile = nil) ⇒ void
Sets up SimpleCov to run against your project:.
-
.start_tracking ⇒ void
Begin coverage tracking without applying configuration.
-
.subprocess_serial ⇒ Integer
A monotonically increasing serial assigned to each forked subprocess; the default
at_forkbuilds worker command names from it. - .wait_for_other_processes ⇒ Object private
-
.wait_for_parallel_results(expected, native_wait: false) ⇒ Object
resultset it's going to get, false on timeout.
- .warn_about_deferred_report ⇒ Object
- .warn_about_incomplete_parallel_results(expected, seen) ⇒ Object private
- .warn_about_start_in_dot_simplecov ⇒ void
-
.with_dot_simplecov_autoload ⇒ void
private
Mark the duration of a
.simplecovauto-load so anySimpleCov.startcall inside the file can warn about the impending migration to a config-only file. - .worker_id ⇒ String
-
.write_last_run(result) ⇒ void
rounded down (see #679) so the next run can compute drift.
Methods included from Configuration
active_session?, add_coverage_criterion, 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, disable_eval_coverage, enable_coverage, enable_coverage_criterion, enable_coverage_for_eval, enable_eval_coverage, enable_for_subprocesses, enabled_for_subprocesses?, expected_coverage, explicit_coverage_destination?, explicit_custom_coverage_destination?, final_result_process?, 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, line_coverage?, 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, normalized_threshold, 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, resolve_criterion_variant, root, skip, source_in_json, store_minimum_per_file, store_minimum_per_group, store_overall_threshold, track_files, track_files_replacement_hint, tracked_files, use_merging, validate_coverage_criteria!, validate_per_file_key, warn_about_inferred_finalize_merge
Methods included from RunIdentity::Accessors
Class Attribute Details
.external_at_exit ⇒ Boolean?
Should something external (e.g. the Minitest plugin) own the at_exit behavior instead of SimpleCov's own hook?
61 62 63 |
# File 'lib/simplecov.rb', line 61 def external_at_exit @external_at_exit end |
.pid ⇒ Integer?
Returns the value of attribute pid.
23 24 25 |
# File 'lib/simplecov.rb', line 23 def pid @pid end |
.process_start_time ⇒ Time?
When this process started tracking coverage.
27 28 29 |
# File 'lib/simplecov.rb', line 27 def process_start_time @process_start_time end |
Class Method Details
.at_exit_behavior ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# 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? # Capture the suite's exit status 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? SimpleCov.run_exit_tasks!(error_exit_status) end |
.clear_result ⇒ void
This method returns an undefined value.
Clear the cached result. Primarily useful in testing.
123 124 125 |
# File 'lib/simplecov/result_processing.rb', line 123 def clear_result @result = nil end |
.collate(result_filenames, profile = nil, processes: ENV.fetch("SIMPLECOV_CONCURRENCY", 1).to_i, 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. processes: above 1 fans the
merge out across that many forked workers, for an identical report;
anything below 1 is taken as 1.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/simplecov/result_processing.rb', line 28 def collate(result_filenames, profile = nil, processes: ENV.fetch("SIMPLECOV_CONCURRENCY", 1).to_i, 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 = ParallelResultMerger.merge_and_store(*result_filenames, processes: [1, processes].max, ignore_timeout: ignore_timeout) @collating_result = true run_exit_tasks! ensure @collating_result = false end |
.collating_result? ⇒ Boolean
85 86 87 |
# File 'lib/simplecov/result_processing.rb', line 85 def collating_result? defined?(@collating_result) && @collating_result end |
.collect_own_coverage(standalone:) ⇒ void
This method returns an undefined value.
Build this process's slice of the coverage result. standalone is true
when no merge step follows, which makes this the final result: it is the
one that reports dropped source files, and the one that injects unloaded
files. When a merge does follow, both jobs belong to the merged result.
73 74 75 76 77 |
# File 'lib/simplecov/result_processing.rb', line 73 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 stats are folded into the :line bucket, so use
the returned criterion to look up coverage_statistics.
66 67 68 |
# File 'lib/simplecov.rb', line 66 def coverage_statistics_key(criterion) criterion == :oneshot_line ? :line : criterion end |
.current_parallel_worker_count ⇒ Object
89 90 91 92 |
# File 'lib/simplecov/parallel_coordination.rb', line 89 def current_parallel_worker_count resultset = SimpleCov::ResultMerger.read_resultset SimpleCov::ResultMerger.worker_identities_for_run(resultset, SimpleCov.run_id, SimpleCov.process_start_time).size 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 that shelled out to the test runner. See issue #581.
13 14 15 16 17 18 19 20 |
# File 'lib/simplecov/report_deferral.rb', line 13 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 (rm -rf coverage).
27 28 29 30 31 32 33 34 35 |
# File 'lib/simplecov/report_deferral.rb', line 27 def existing_report_newer_than_us? return false unless process_start_time [SimpleCov::LastRun.last_run_path, SimpleCov::ReportStamp.path].any? do |path| File.mtime(path) > process_start_time rescue SystemCallError false end 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.
68 69 70 71 72 73 74 75 76 |
# File 'lib/simplecov/exit_handling.rb', line 68 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_exception ⇒ Object
49 50 51 52 53 54 55 56 57 58 |
# File 'lib/simplecov/exit_handling.rb', line 49 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.
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.
90 91 92 93 94 95 96 |
# File 'lib/simplecov/result_processing.rb', line 90 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.
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.
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.
103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/simplecov/result_processing.rb', line 103 def grouped(files, groups: SimpleCov.groups) return {} if GroupNames.validate!(groups.keys).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[GroupNames::UNGROUPED] = SimpleCov::FileList.new(ungrouped) if ungrouped.any? grouped end |
.inject_unloaded_files(result, candidate_paths, synthesize: nil, lines: nil) ⇒ [Hash[String, untyped], Set[String]]
Add simulated coverage for each of candidate_paths the result doesn't
already carry, and return it with the set of paths added.
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/simplecov/result_processing.rb', line 146 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, which is about half the cost of simulating one. # Nothing reads those tuples when neither criterion is enabled — # `Combine::CoverageAccumulator` only combines them per criterion, and the # statistics drop them the same way — so skip the parse. 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. See #1250. UnloadedFileInjector.call( result, candidate_paths, synthesize: synthesize.nil? ? branch_coverage? || method_coverage? : synthesize, lines: lines.nil? ? line_coverage? : lines ) end |
.install_at_exit_hook ⇒ void
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.
118 119 120 |
# File 'lib/simplecov/result_processing.rb', line 118 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_time ⇒ Object
107 108 109 |
# File 'lib/simplecov/parallel_coordination.rb', line 107 def monotonic_time Process.clock_gettime(Process::CLOCK_MONOTONIC) end |
.next_subprocess_serial! ⇒ Integer
child inherits its own ordinal via copy-on-write.
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).
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.
113 114 115 116 117 118 |
# File 'lib/simplecov/parallel_coordination.rb', line 113 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".
63 64 65 |
# File 'lib/simplecov/exit_handling.rb', line 63 def previous_error?(error_exit_status) !!(error_exit_status && error_exit_status != SimpleCov::ExitCodes::SUCCESS) end |
.process_result(result) ⇒ Object
105 106 107 108 109 |
# File 'lib/simplecov/exit_handling.rb', line 105 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_error ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/simplecov/exit_handling.rb', line 90 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.
85 86 87 88 |
# File 'lib/simplecov/exit_handling.rb', line 85 def ready_to_process_results? merge_finalization_owner? && 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 |
.result ⇒ Result?
The result for the current coverage run, merged across test suites when merging is active. nil when no coverage was tracked.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/simplecov/result_processing.rb', line 49 def result return @result if result? use_merging = merging collect_own_coverage(standalone: !use_merging) # 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 merge_finalization_owner? 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.
80 81 82 |
# File 'lib/simplecov/result_processing.rb', line 80 def result? defined?(@result) && @result end |
.result_exit_status(result) ⇒ Object
111 112 113 |
# File 'lib/simplecov/exit_handling.rb', line 111 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.
97 98 99 100 101 102 103 104 105 |
# File 'lib/simplecov/parallel_coordination.rb', line 97 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.
136 137 138 |
# File 'lib/simplecov/result_processing.rb', line 136 def round_coverage(coverage) coverage.floor(2) end |
.run_exit_tasks!(error_exit_status = exit_status_from_exception) ⇒ Object
the status, see there) and by collate (the default argument).
41 42 43 44 45 46 |
# File 'lib/simplecov/exit_handling.rb', line 41 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 |
.run_id ⇒ String
47 |
# File 'sig/simplecov.rbs', line 47
def self.run_id: () -> String
|
.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
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_tracking ⇒ void
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 |
# 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 # Select the parallel adapter and generate identities before any forks. SimpleCov::RunIdentity.prepare @result = nil self.pid = Process.pid self.process_start_time = Time.now start_coverage_measurement end |
.subprocess_serial ⇒ Integer
A monotonically increasing serial assigned to each forked
subprocess; the default at_fork builds worker command names from it.
35 36 37 |
# File 'lib/simplecov.rb', line 35 def subprocess_serial @subprocess_serial ||= 0 end |
.wait_for_other_processes ⇒ 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.
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 = 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_report ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/simplecov/report_deferral.rb', line 37 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.
121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/simplecov/parallel_coordination.rb', line 121 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_simplecov ⇒ void
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_autoload ⇒ 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.
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 |
.worker_id ⇒ String
49 |
# File 'sig/simplecov.rbs', line 49
def self.worker_id: () -> String
|
.write_last_run(result) ⇒ void
This method returns an undefined value.
rounded down (see #679) so the next run can compute drift.
129 130 131 132 133 |
# File 'lib/simplecov/result_processing.rb', line 129 def write_last_run(result) SimpleCov::LastRun.write( result: result.coverage_statistics.transform_values { |stats| round_coverage(stats.percent) } ) end |