123456789_123456789_123456789_123456789_123456789_

Module: SimpleCov

Relationships & Source Files
Namespace Children
Modules:
Classes:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
Defined in: lib/simplecov.rb,
lib/simplecov/combine.rb,
lib/simplecov/command_guesser.rb,
lib/simplecov/configuration.rb,
lib/simplecov/coverage_statistics.rb,
lib/simplecov/default_formatter.rb,
lib/simplecov/exit_codes.rb,
lib/simplecov/file_list.rb,
lib/simplecov/filter.rb,
lib/simplecov/formatter.rb,
lib/simplecov/last_run.rb,
lib/simplecov/lines_classifier.rb,
lib/simplecov/profiles.rb,
lib/simplecov/result.rb,
lib/simplecov/result_adapter.rb,
lib/simplecov/result_merger.rb,
lib/simplecov/simulate_coverage.rb,
lib/simplecov/source_file.rb,
lib/simplecov/useless_results_remover.rb,
lib/simplecov/version.rb,
lib/simplecov/combine/branches_combiner.rb,
lib/simplecov/combine/files_combiner.rb,
lib/simplecov/combine/lines_combiner.rb,
lib/simplecov/combine/results_combiner.rb,
lib/simplecov/exit_codes/exit_code_handling.rb,
lib/simplecov/exit_codes/maximum_coverage_drop_check.rb,
lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb,
lib/simplecov/exit_codes/minimum_overall_coverage_check.rb,
lib/simplecov/formatter/multi_formatter.rb,
lib/simplecov/formatter/simple_formatter.rb,
lib/simplecov/source_file/branch.rb,
lib/simplecov/source_file/line.rb

Overview

Code coverage for ruby. Please check out README for a full introduction.

Constant Summary

Class Attribute Summary

Configuration - Extended

branch_coverage?, branch_coverage_supported?, coverage_for_eval_enabled?, coverage_for_eval_supported?, coverage_start_arguments_supported?,
enabled_for_subprocesses?

gets the enabled_for_subprocess configuration.

filters

Returns the list of configured filters.

filters=,
formatter

Gets or sets the configured formatter.

formatter=,
formatters

Gets the configured formatters.

formatters=

Sets the configured formatters.

groups

Returns the configured groups.

groups=,
print_error_status

Whether we should print non-success status codes.

print_error_status=

Class Method Summary

Configuration - Extended

adapters,
add_filter

Add a filter to the processing chain.

add_group

Define a group for files.

at_exit

Gets or sets the behavior to process coverage results.

at_fork

Gets or sets the behavior to start a new forked ::Process.

clear_coverage_criteria,
command_name

The name of the command (a.k.a. Test Suite) currently running.

configure

Allows you to configure simplecov in a block instead of prepending SimpleCov to all config methods you’re calling.

coverage_criteria,
coverage_criterion

Define which coverage criterion should be evaluated.

coverage_criterion_enabled?,
coverage_dir

The name of the output and cache directory.

coverage_path

Returns the full path to the output directory using SimpleCov.root and SimpleCov.coverage_dir, so you can adjust this by configuring those values.

enable_coverage, enable_coverage_for_eval,
enable_for_subprocesses

gets or sets the enabled_for_subprocess configuration when true, this will inject SimpleCov code into Process.fork

maximum_coverage_drop

Defines the maximum coverage drop at once allowed for the testsuite to pass.

merge_timeout

Defines the maximum age (in seconds) of a resultset to still be included in merged results.

minimum_coverage

Defines the minimum overall coverage required for the testsuite to pass.

minimum_coverage_by_file

Defines the minimum coverage per file required for the testsuite to pass.

nocov_token

Certain code blocks (i.e. Ruby-implementation specific code) can be excluded from the coverage metrics by wrapping it inside # :nocov: comment blocks.

primary_coverage,
profiles

Returns the hash of available profiles.

project_name

Returns the project name - currently assuming the last dirname in the SimpleCov.root is this.

raise_on_invalid_coverage,
refuse_coverage_drop

Refuses any coverage drop.

root

The root for the project.

skip_token
track_files

Coverage results will always include files matched by this glob, whether or not they were explicitly required.

tracked_files

Returns the glob that will be used to include files that were not explicitly required.

use_merging

Defines whether to use result merging so all your test suites (test:units, test:functionals, cucumber, …) are joined and combined into a single coverage report.

minimum_possible_coverage_exceeded,
parse_filter

The actual filter processor.

raise_if_criterion_disabled, raise_if_criterion_unsupported

Class Attribute Details

.coverage_running?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/simplecov.rb', line 359

def coverage_running?
  # for ruby versions which do not implement Coverage.running?,
  # Coverage.start may be called multiple times without raising.
  Coverage.respond_to?(:running?) && Coverage.running?
end

.external_at_exit? (rw)

Alias for .external_at_exit.

[ GitHub ]

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

alias external_at_exit? external_at_exit

.final_result_process?Boolean (readonly)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/simplecov.rb', line 268

def final_result_process?
  # checking for ENV["TEST_ENV_NUMBER"] to determine if the tests are being run in parallel
  !defined?(ParallelTests) || !ENV["TEST_ENV_NUMBER"] || ParallelTests.last_process?
end

.pid (rw)

[ GitHub ]

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

attr_accessor :running, :pid

.probably_running_parallel_tests?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/simplecov.rb', line 440

def probably_running_parallel_tests?
  ENV.fetch("TEST_ENV_NUMBER", nil) && ENV.fetch("PARALLEL_TEST_GROUPS", nil)
end

.ready_to_process_results?Boolean (readonly)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/simplecov.rb', line 229

def ready_to_process_results?
  final_result_process? && result?
end

.result (readonly)

Returns the result for the current coverage run, merging it across test suites from cache using ::SimpleCov::ResultMerger if use_merging is activated (default)

[ GitHub ]

  
# File 'lib/simplecov.rb', line 101

def result
  return @result if result?

  # Collect our coverage result
  process_coverage_result if 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
    wait_for_other_processes
    SimpleCov::ResultMerger.store_result(@result) if result?
    @result = SimpleCov::ResultMerger.merged_result
  end

  @result
ensure
  self.running = false
end

.result?Boolean (readonly)

Returns nil if the result has not been computed Otherwise, returns the result

[ GitHub ]

  
# File 'lib/simplecov.rb', line 124

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

.running (rw)

[ GitHub ]

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

attr_accessor :running, :pid

Class Method Details

.adapt_coverage_resultHash (private)

Unite the result so it wouldn’t matter what coverage type was called

[ GitHub ]

  
# File 'lib/simplecov.rb', line 405

def adapt_coverage_result
  @result = SimpleCov::ResultAdapter.call(Coverage.result)
end

.add_not_loaded_files(result) (private)

Finds files that were to be tracked but were not loaded and initializes the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).

[ GitHub ]

  
# File 'lib/simplecov.rb', line 377

def add_not_loaded_files(result)
  if tracked_files
    result = result.dup
    Dir[tracked_files].each do |file|
      absolute_path = File.expand_path(file)
      result[absolute_path] ||= SimulateCoverage.call(absolute_path)
    end
  end

  result
end

.at_exit_behavior

[ GitHub ]

  
# File 'lib/simplecov.rb', line 174

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

  # If SimpleCov is no longer running then don't run exit tasks
  SimpleCov.run_exit_tasks! if SimpleCov.running
end

.clear_result

Clear out the previously cached .result. Primarily useful in testing

[ GitHub ]

  
# File 'lib/simplecov.rb', line 170

def clear_result
  @result = nil
end

.collate(result_filenames, profile = nil, ignore_timeout: true, &block)

Collate a series of SimpleCov result files into a single SimpleCov output.

You can optionally specify configuration with a block:

SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"]
 OR
SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' # using rails profile
 OR
SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"] do
  add_filter 'test'
end
 OR
SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' do
  add_filter 'test'
end

Please check out the RDoc for ::SimpleCov::Configuration to find about available config options, or checkout the README for more in-depth information about coverage collation

By default collate ignores the merge_timeout so all results of all files specified will be merged together. If you want to honor the merge_timeout then provide the keyword argument ignore_timeout: false.

[ GitHub ]

  
# File 'lib/simplecov.rb', line 86

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

  initial_setup(profile, &block)

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

  run_exit_tasks!
end

.exit_and_report_previous_error(exit_status)

This method is for internal use only.

Thinking: Move this behavior earlier so if there was an error we do nothing?

[ GitHub ]

  
# File 'lib/simplecov.rb', line 223

def exit_and_report_previous_error(exit_status)
  warn("Stopped processing SimpleCov as a previous error not related to SimpleCov has been detected") if print_error_status
  Kernel.exit(exit_status)
end

.exit_status_from_exception

This method is for internal use only.

Returns the exit status from the exit exception

[ GitHub ]

  
# File 'lib/simplecov.rb', line 200

def exit_status_from_exception
  # Capture the current exception if it exists
  @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 (rw) Also known as: .external_at_exit?

Basically, should we take care of at_exit behavior or something else? Used by the minitest plugin. See lib/minitest/simplecov_plugin.rb

[ GitHub ]

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

attr_accessor :external_at_exit

.filtered(files)

Applies the configured filters to the given array of ::SimpleCov::SourceFile items

[ GitHub ]

  
# File 'lib/simplecov.rb', line 131

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

.grouped(files)

Applies the configured groups to the given array of ::SimpleCov::SourceFile items

[ GitHub ]

  
# File 'lib/simplecov.rb', line 142

def grouped(files)
  grouped = {}
  grouped_files = []
  groups.each do |name, filter|
    grouped[name] = SimpleCov::FileList.new(files.select { |source_file| filter.matches?(source_file) })
    grouped_files += grouped[name]
  end
  if !groups.empty? && !(other_files = files.reject { |source_file| grouped_files.include?(source_file) }).empty?
    grouped["Ungrouped"] = SimpleCov::FileList.new(other_files)
  end
  grouped
end

.initial_setup(profile, &block) (private)

[ GitHub ]

  
# File 'lib/simplecov.rb', line 302

def initial_setup(profile, &block)
  load_profile(profile) if profile
  configure(&block) if block
  self.running = true
end

.load_adapter(name)

[ GitHub ]

  
# File 'lib/simplecov.rb', line 162

def load_adapter(name)
  warn "#{Kernel.caller.first}: [DEPRECATION] #load_adapter is deprecated. Use #load_profile instead."
  load_profile(name)
end

.load_profile(name)

Applies the profile of given name on SimpleCov configuration

[ GitHub ]

  
# File 'lib/simplecov.rb', line 158

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

.lookup_corresponding_ruby_coverage_name(criterion) (private)

[ GitHub ]

  
# File 'lib/simplecov.rb', line 369

def lookup_corresponding_ruby_coverage_name(criterion)
  CRITERION_TO_RUBY_COVERAGE.fetch(criterion)
end

.make_parallel_tests_available (private)

parallel_tests isn’t always available, see: github.com/grosser/parallel_tests/issues/772

[ GitHub ]

  
# File 'lib/simplecov.rb', line 431

def make_parallel_tests_available
  return if defined?(ParallelTests)
  return unless probably_running_parallel_tests?

  require "parallel_tests"
rescue LoadError
  warn("SimpleCov guessed you were running inside parallel tests but couldn't load it. Please file a bug report with us!")
end

.previous_error?(error_exit_status) ⇒ Boolean

This method is for internal use only.
[ GitHub ]

  
# File 'lib/simplecov.rb', line 213

def previous_error?(error_exit_status)
  # Normally it'd be enough to check for previous error but when running test_unit
  # status is 0
  error_exit_status && error_exit_status != SimpleCov::ExitCodes::SUCCESS
end

.process_coverage_resultHash (private)

Call steps that handle process coverage result

[ GitHub ]

  
# File 'lib/simplecov.rb', line 394

def process_coverage_result
  adapt_coverage_result
  remove_useless_results
  result_with_not_loaded_files
end

.process_result(result)

This method is for internal use only.

Usage:

exit_status = SimpleCov.process_result(SimpleCov.result, exit_status)
[ GitHub ]

  
# File 'lib/simplecov.rb', line 248

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

[ GitHub ]

  
# File 'lib/simplecov.rb', line 233

def process_results_and_report_error
  exit_status = process_result(result)

  # Force exit with stored status (see github issue #5)
  if exit_status.positive?
    warn("SimpleCov failed with exit #{exit_status} due to a coverage related error") if print_error_status
    Kernel.exit exit_status
  end
end

.remove_useless_resultsHash (private)

::SimpleCov::Filter coverage result The result before filter also has result of coverage for files are not related to the project like loaded gems coverage.

[ GitHub ]

  
# File 'lib/simplecov.rb', line 416

def remove_useless_results
  @result = SimpleCov::UselessResultsRemover.call(@result)
end

.result_exit_status(result)

[ GitHub ]

  
# File 'lib/simplecov.rb', line 256

def result_exit_status(result)
  coverage_limits = CoverageLimits.new(
    minimum_coverage: minimum_coverage, minimum_coverage_by_file: minimum_coverage_by_file,
    maximum_coverage_drop: maximum_coverage_drop
  )

  ExitCodes::ExitCodeHandling.call(result, coverage_limits: coverage_limits)
end

.result_with_not_loaded_filesHash (private)

Initialize result with files that are not included by coverage and added inside the config block

[ GitHub ]

  
# File 'lib/simplecov.rb', line 426

def result_with_not_loaded_files
  @result = SimpleCov::Result.new(add_not_loaded_files(@result))
end

.round_coverage(coverage)

This method is for internal use only.

Rounding down to be extra strict, see #679

[ GitHub ]

  
# File 'lib/simplecov.rb', line 296

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

.run_exit_tasks!

This method is for internal use only.

Called from at_exit block

[ GitHub ]

  
# File 'lib/simplecov.rb', line 186

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, &block)

Sets up SimpleCov to run against your project. You can optionally specify a profile to use as well as configuration with a block:

SimpleCov.start
 OR
SimpleCov.start 'rails' # using rails profile
 OR
SimpleCov.start do
  add_filter 'test'
end
  OR
SimpleCov.start 'rails' do
  add_filter 'test'
end

Please check out the RDoc for ::SimpleCov::Configuration to find about available config options

[ GitHub ]

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

def start(profile = nil, &block)
  require "coverage"
  initial_setup(profile, &block)
  require_relative "simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
                                          ::Process.respond_to?(:fork)

  make_parallel_tests_available

  @result = nil
  self.pid = Process.pid

  start_coverage_measurement
end

.start_coverage_measurement (private)

Trigger Coverage.start depends on given config coverage_criterion

With Positive branch it supports all coverage measurement types With Negative branch it supports only line coverage measurement type

[ GitHub ]

  
# File 'lib/simplecov.rb', line 314

def start_coverage_measurement
  # This blog post gives a good run down of the coverage criterias introduced
  # in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
  # There is also a nice writeup of the different coverage criteria made in this
  # comment  https://github.com/simplecov-ruby/simplecov/pull/692#discussion_r281836176 :
  # Ruby < 2.5:
  # https://github.com/ruby/ruby/blob/v1_9_3_374/ext/coverage/coverage.c
  # traditional mode (Array)
  #
  # Ruby 2.5:
  # https://bugs.ruby-lang.org/issues/13901
  # https://github.com/ruby/ruby/blob/v2_5_3/ext/coverage/coverage.c
  # default: traditional/compatible mode (Array)
  # :lines - like traditional mode but using Hash
  # :branches
  # :methods
  # :all - same as lines + branches + methods
  #
  # Ruby >= 2.6:
  # https://bugs.ruby-lang.org/issues/15022
  # https://github.com/ruby/ruby/blob/v2_6_3/ext/coverage/coverage.c
  # default: traditional/compatible mode (Array)
  # :lines - like traditional mode but using Hash
  # :branches
  # :methods
  # :oneshot_lines - can not be combined with lines
  # :all - same as lines + branches + methods
  #
  if coverage_start_arguments_supported?
    start_coverage_with_criteria
  else
    Coverage.start unless coverage_running?
  end
end

.start_coverage_with_criteria (private)

[ GitHub ]

  
# File 'lib/simplecov.rb', line 349

def start_coverage_with_criteria
  start_arguments = coverage_criteria.map do |criterion|
    [lookup_corresponding_ruby_coverage_name(criterion), true]
  end.to_h

  start_arguments[:eval] = true if coverage_for_eval_enabled?

  Coverage.start(start_arguments) unless coverage_running?
end

.wait_for_other_processes

This method is for internal use only.
[ GitHub ]

  
# File 'lib/simplecov.rb', line 276

def wait_for_other_processes
  return unless defined?(ParallelTests) && final_result_process?

  ParallelTests.wait_for_other_processes_to_finish
end

.write_last_run(result)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/simplecov.rb', line 285

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