Module: SimpleCov

Defined in:
lib/simplecov/profiles.rb,
lib/simplecov.rb,
lib/simplecov/filter.rb,
lib/simplecov/result.rb,
lib/simplecov/railtie.rb,
lib/simplecov/version.rb,
lib/simplecov/last_run.rb,
lib/simplecov/file_list.rb,
lib/simplecov/formatter.rb,
lib/simplecov/exit_codes.rb,
lib/simplecov/source_file.rb,
lib/simplecov/raw_coverage.rb,
lib/simplecov/configuration.rb,
lib/simplecov/result_merger.rb,
lib/simplecov/command_guesser.rb,
lib/simplecov/lines_classifier.rb,
lib/simplecov/formatter/multi_formatter.rb,
lib/simplecov/formatter/simple_formatter.rb

Overview

A ridiculously simple formatter for SimpleCov results.

Defined Under Namespace

Modules: CommandGuesser, Configuration, ExitCodes, Formatter, LastRun, RawCoverage, ResultMerger Classes: ArrayFilter, BlockFilter, FileList, Filter, LinesClassifier, Profiles, Railtie, RegexFilter, Result, SourceFile, StringFilter

Constant Summary collapse

VERSION =
"0.17.1".freeze

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.exit_exceptionObject (readonly)

Returns the value of attribute exit_exception


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

def exit_exception
  @exit_exception
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


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

def running
  @running
end

Class Method Details

.add_not_loaded_files(result) ⇒ Object

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


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

def add_not_loaded_files(result)
  if tracked_files
    result = result.dup
    Dir[tracked_files].each do |file|
      absolute = File.expand_path(file)

      result[absolute] ||= LinesClassifier.new.classify(File.foreach(absolute))
    end
  end

  result
end

.clear_resultObject

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


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

def clear_result
  @result = nil
end

.exit_status_from_exceptionObject

Returns the exit status from the exit exception


184
185
186
187
188
189
190
191
192
# File 'lib/simplecov.rb', line 184

def exit_status_from_exception
  return SimpleCov::ExitCodes::SUCCESS 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


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

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.


259
260
261
262
# File 'lib/simplecov.rb', line 259

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

.grouped(files) ⇒ Object

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


125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/simplecov.rb', line 125

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


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

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


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

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

.process_result(result, 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.

Usage:

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

220
221
222
223
224
225
226
227
228
229
# File 'lib/simplecov.rb', line 220

def process_result(result, exit_status)
  return exit_status if exit_status != SimpleCov::ExitCodes::SUCCESS # Existing errors

  covered_percent = result.covered_percent.round(2)
  result_exit_status = result_exit_status(result, covered_percent)
  if result_exit_status == SimpleCov::ExitCodes::SUCCESS # No result errors
    write_last_run(covered_percent)
  end
  final_result_process? ? result_exit_status : SimpleCov::ExitCodes::SUCCESS
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)


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

def result
  return @result if result?

  # Collect our coverage result
  if running
    @result = SimpleCov::Result.new add_not_loaded_files(Coverage.result)
  end

  # 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


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

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

.result_exit_status(result, covered_percent) ⇒ 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.

rubocop:disable Metrics/MethodLength


234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/simplecov.rb', line 234

def result_exit_status(result, covered_percent)
  covered_percentages = result.covered_percentages.map { |percentage| percentage.round(2) }
  if covered_percent < SimpleCov.minimum_coverage
    $stderr.printf("Coverage (%.2f%%) is below the expected minimum coverage (%.2f%%).\n", covered_percent, SimpleCov.minimum_coverage)
    SimpleCov::ExitCodes::MINIMUM_COVERAGE
  elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file }
    $stderr.printf("File (%s) is only (%.2f%%) covered. This is below the expected minimum coverage per file of (%.2f%%).\n", result.least_covered_file, covered_percentages.min, SimpleCov.minimum_coverage_by_file)
    SimpleCov::ExitCodes::MINIMUM_COVERAGE
  elsif (last_run = SimpleCov::LastRun.read)
    coverage_diff = last_run["result"]["covered_percent"] - covered_percent
    if coverage_diff > SimpleCov.maximum_coverage_drop
      $stderr.printf("Coverage has dropped by %.2f%% since the last time (maximum allowed: %.2f%%).\n", coverage_diff, SimpleCov.maximum_coverage_drop)
      SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
    else
      SimpleCov::ExitCodes::SUCCESS
    end
  else
    SimpleCov::ExitCodes::SUCCESS
  end
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


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

def run_exit_tasks!
  exit_status = SimpleCov.exit_status_from_exception

  SimpleCov.at_exit.call

  # Don't modify the exit status unless the result has already been
  # computed
  exit_status = SimpleCov.process_result(SimpleCov.result, exit_status) if SimpleCov.result?

  # Force exit with stored status (see github issue #5)
  # unless it's nil or 0 (see github issue #281)
  if exit_status && exit_status > 0
    $stderr.printf("SimpleCov failed with exit %d", exit_status)
    Kernel.exit exit_status
  end
end

.set_exit_exceptionObject

Capture the current exception if it exists This will get called inside the at_exit block


177
178
179
# File 'lib/simplecov.rb', line 177

def set_exit_exception
  @exit_exception = $ERROR_INFO
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


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

def start(profile = nil, &block)
  if SimpleCov.usable?
    load_profile(profile) if profile
    configure(&block) if block_given?
    @result = nil
    self.running = true
    self.pid = Process.pid
    Coverage.start
  else
    warn "WARNING: SimpleCov is activated, but you're not running Ruby 1.9+ - no coverage analysis will happen"
    warn "Starting with SimpleCov 1.0.0, even no-op compatibility with Ruby <= 1.8 will be entirely dropped."
    false
  end
end

.usable?Boolean

Checks whether we're on a proper version of Ruby (likely 1.9+) which provides coverage support


154
155
156
157
158
159
160
161
162
163
164
# File 'lib/simplecov.rb', line 154

def usable?
  return @usable if defined?(@usable) && !@usable.nil?

  @usable = begin
    require "coverage"
    require "simplecov/jruby_fix"
    true
  rescue LoadError
    false
  end
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.


267
268
269
270
# File 'lib/simplecov.rb', line 267

def wait_for_other_processes
  return unless defined?(ParallelTests) && final_result_process?
  ParallelTests.wait_for_other_processes_to_finish
end

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


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

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