Module: SimpleCov

Defined in:
lib/simplecov.rb,
lib/simplecov/filter.rb,
lib/simplecov/result.rb,
lib/simplecov/combine.rb,
lib/simplecov/version.rb,
lib/simplecov/last_run.rb,
lib/simplecov/profiles.rb,
lib/simplecov/file_list.rb,
lib/simplecov/formatter.rb,
lib/simplecov/exit_codes.rb,
lib/simplecov/source_file.rb,
lib/simplecov/configuration.rb,
lib/simplecov/result_merger.rb,
lib/simplecov/result_adapter.rb,
lib/simplecov/command_guesser.rb,
lib/simplecov/lines_classifier.rb,
lib/simplecov/source_file/line.rb,
lib/simplecov/default_formatter.rb,
lib/simplecov/simulate_coverage.rb,
lib/simplecov/source_file/branch.rb,
lib/simplecov/coverage_statistics.rb,
lib/simplecov/combine/files_combiner.rb,
lib/simplecov/combine/lines_combiner.rb,
lib/simplecov/useless_results_remover.rb,
lib/simplecov/combine/results_combiner.rb,
lib/simplecov/combine/branches_combiner.rb,
lib/simplecov/formatter/multi_formatter.rb,
lib/simplecov/formatter/simple_formatter.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

Overview

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

Defined Under Namespace

Modules: Combine, CommandGuesser, Configuration, ExitCodes, Formatter, LastRun, ResultMerger, SimulateCoverage, UselessResultsRemover Classes: ArrayFilter, BlockFilter, CoverageLimits, CoverageStatistics, FileList, Filter, LinesClassifier, Profiles, RegexFilter, Result, ResultAdapter, SourceFile, StringFilter

Constant Summary collapse

VERSION =
"0.20.0"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

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


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

def external_at_exit
  @external_at_exit
end

.pidObject

Returns the value of attribute pid


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

def pid
  @pid
end

.runningObject

Returns the value of attribute running


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

def running
  @running
end

Class Method Details

.at_exit_behaviorObject


176
177
178
179
180
181
182
# File 'lib/simplecov.rb', line 176

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_resultObject

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


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

def clear_result
  @result = nil
end

.collate(result_filenames, profile = nil, &block) ⇒ Object

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


83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/simplecov.rb', line 83

def collate(result_filenames, profile = nil, &block)
  raise "There's no reports to be merged" if result_filenames.empty?

  initial_setup(profile, &block)

  results = result_filenames.flat_map do |filename|
    # Re-create each included instance of SimpleCov::Result from the stored run data.
    Result.from_hash(JSON.parse(File.read(filename)) || {})
  end

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

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

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


225
226
227
228
# File 'lib/simplecov.rb', line 225

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

Returns the exit status from the exit exception


202
203
204
205
206
207
208
209
210
211
212
# File 'lib/simplecov.rb', line 202

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

.filtered(files) ⇒ Object

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


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

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

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

270
271
272
273
# File 'lib/simplecov.rb', line 270

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

.grouped(files) ⇒ Object

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


144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/simplecov.rb', line 144

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

.load_adapter(name) ⇒ Object


164
165
166
167
# File 'lib/simplecov.rb', line 164

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

.load_profile(name) ⇒ Object

Applies the profile of given name on SimpleCov configuration


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

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

.previous_error?(error_exit_status) ⇒ 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)

215
216
217
218
219
# File 'lib/simplecov.rb', line 215

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_result(result) ⇒ 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.

Usage:

exit_status = SimpleCov.process_result(SimpleCov.result, exit_status)

250
251
252
253
254
# File 'lib/simplecov.rb', line 250

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

.process_results_and_report_errorObject


235
236
237
238
239
240
241
242
243
# File 'lib/simplecov.rb', line 235

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

.ready_to_process_results?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)

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

def ready_to_process_results?
  final_result_process? && result?
end

.resultObject

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


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/simplecov.rb', line 103

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

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

Returns:

  • (Boolean)

126
127
128
# File 'lib/simplecov.rb', line 126

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

.result_exit_status(result) ⇒ Object


258
259
260
261
262
263
264
265
# File 'lib/simplecov.rb', line 258

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

.round_coverage(coverage) ⇒ 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.

Rounding down to be extra strict, see #679


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

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

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

Called from at_exit block


188
189
190
191
192
193
194
195
# File 'lib/simplecov.rb', line 188

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) ⇒ Object

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


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

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

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


278
279
280
281
282
# File 'lib/simplecov.rb', line 278

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

  ParallelTests.wait_for_other_processes_to_finish
end

.write_last_run(result) ⇒ 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.


287
288
289
# File 'lib/simplecov.rb', line 287

def write_last_run(result)
  SimpleCov::LastRun.write(result: {covered_percent: round_coverage(result.covered_percent)})
end