simplecov 0.16.1 → 0.21.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +107 -407
  3. data/README.md +378 -126
  4. data/doc/alternate-formatters.md +21 -1
  5. data/doc/commercial-services.md +5 -0
  6. data/lib/minitest/simplecov_plugin.rb +15 -0
  7. data/lib/simplecov/combine/branches_combiner.rb +32 -0
  8. data/lib/simplecov/combine/files_combiner.rb +24 -0
  9. data/lib/simplecov/combine/lines_combiner.rb +43 -0
  10. data/lib/simplecov/combine/results_combiner.rb +60 -0
  11. data/lib/simplecov/combine.rb +30 -0
  12. data/lib/simplecov/command_guesser.rb +6 -3
  13. data/lib/simplecov/configuration.rb +191 -15
  14. data/lib/simplecov/coverage_statistics.rb +56 -0
  15. data/lib/simplecov/default_formatter.rb +20 -0
  16. data/lib/simplecov/defaults.rb +15 -12
  17. data/lib/simplecov/exit_codes/exit_code_handling.rb +29 -0
  18. data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +83 -0
  19. data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +54 -0
  20. data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +53 -0
  21. data/lib/simplecov/exit_codes.rb +5 -0
  22. data/lib/simplecov/file_list.rb +72 -13
  23. data/lib/simplecov/filter.rb +9 -6
  24. data/lib/simplecov/formatter/multi_formatter.rb +5 -7
  25. data/lib/simplecov/formatter/simple_formatter.rb +4 -4
  26. data/lib/simplecov/formatter.rb +2 -2
  27. data/lib/simplecov/last_run.rb +3 -1
  28. data/lib/simplecov/lines_classifier.rb +5 -5
  29. data/lib/simplecov/no_defaults.rb +1 -1
  30. data/lib/simplecov/process.rb +19 -0
  31. data/lib/simplecov/profiles/hidden_filter.rb +5 -0
  32. data/lib/simplecov/profiles/rails.rb +1 -1
  33. data/lib/simplecov/profiles.rb +9 -7
  34. data/lib/simplecov/result.rb +18 -12
  35. data/lib/simplecov/result_adapter.rb +30 -0
  36. data/lib/simplecov/result_merger.rb +130 -59
  37. data/lib/simplecov/simulate_coverage.rb +29 -0
  38. data/lib/simplecov/source_file/branch.rb +84 -0
  39. data/lib/simplecov/source_file/line.rb +72 -0
  40. data/lib/simplecov/source_file.rb +273 -127
  41. data/lib/simplecov/useless_results_remover.rb +18 -0
  42. data/lib/simplecov/version.rb +1 -1
  43. data/lib/simplecov.rb +308 -121
  44. metadata +45 -47
  45. data/CONTRIBUTING.md +0 -51
  46. data/ISSUE_TEMPLATE.md +0 -23
  47. data/lib/simplecov/jruby_fix.rb +0 -44
  48. data/lib/simplecov/railtie.rb +0 -9
  49. data/lib/simplecov/railties/tasks.rake +0 -13
  50. data/lib/simplecov/raw_coverage.rb +0 -41
data/lib/simplecov.rb CHANGED
@@ -2,29 +2,31 @@
2
2
 
3
3
  require "English"
4
4
 
5
- #
6
- # Code coverage for ruby 1.9. Please check out README for a full introduction.
7
- #
8
5
  # Coverage may be inaccurate under JRUBY.
9
- if defined?(JRUBY_VERSION) && defined?(JRuby)
6
+ if defined?(JRUBY_VERSION) && defined?(JRuby) && !org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED
10
7
 
11
8
  # @see https://github.com/jruby/jruby/issues/1196
12
9
  # @see https://github.com/metricfu/metric_fu/pull/226
13
- # @see https://github.com/colszowka/simplecov/issues/420
14
- # @see https://github.com/colszowka/simplecov/issues/86
10
+ # @see https://github.com/simplecov-ruby/simplecov/issues/420
11
+ # @see https://github.com/simplecov-ruby/simplecov/issues/86
15
12
  # @see https://jira.codehaus.org/browse/JRUBY-6106
16
13
 
17
- unless org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED
18
- warn 'Coverage may be inaccurate; set the "--debug" command line option,' \
19
- ' or do JRUBY_OPTS="--debug"' \
20
- ' or set the "debug.fullTrace=true" option in your .jrubyrc'
21
- end
14
+ warn 'Coverage may be inaccurate; set the "--debug" command line option,' \
15
+ ' or do JRUBY_OPTS="--debug"' \
16
+ ' or set the "debug.fullTrace=true" option in your .jrubyrc'
22
17
  end
18
+
19
+ #
20
+ # Code coverage for ruby. Please check out README for a full introduction.
21
+ #
23
22
  module SimpleCov
24
23
  class << self
25
- attr_accessor :running
26
- attr_accessor :pid
27
- attr_reader :exit_exception
24
+ attr_accessor :running, :pid
25
+
26
+ # Basically, should we take care of at_exit behavior or something else?
27
+ # Used by the minitest plugin. See lib/minitest/simplecov_plugin.rb
28
+ attr_accessor :external_at_exit
29
+ alias external_at_exit? external_at_exit
28
30
 
29
31
  #
30
32
  # Sets up SimpleCov to run against your project.
@@ -44,35 +46,52 @@ module SimpleCov
44
46
  # Please check out the RDoc for SimpleCov::Configuration to find about available config options
45
47
  #
46
48
  def start(profile = nil, &block)
47
- if SimpleCov.usable?
48
- load_profile(profile) if profile
49
- configure(&block) if block_given?
50
- @result = nil
51
- self.running = true
52
- self.pid = Process.pid
53
- Coverage.start
54
- else
55
- warn "WARNING: SimpleCov is activated, but you're not running Ruby 1.9+ - no coverage analysis will happen"
56
- warn "Starting with SimpleCov 1.0.0, even no-op compatibility with Ruby <= 1.8 will be entirely dropped."
57
- false
58
- end
49
+ require "coverage"
50
+ initial_setup(profile, &block)
51
+ require_relative "./simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
52
+ ::Process.respond_to?(:fork)
53
+
54
+ make_parallel_tests_available
55
+
56
+ @result = nil
57
+ self.pid = Process.pid
58
+
59
+ start_coverage_measurement
59
60
  end
60
61
 
61
62
  #
62
- # Finds files that were to be tracked but were not loaded and initializes
63
- # the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).
63
+ # Collate a series of SimpleCov result files into a single SimpleCov output.
64
64
  #
65
- def add_not_loaded_files(result)
66
- if tracked_files
67
- result = result.dup
68
- Dir[tracked_files].each do |file|
69
- absolute = File.expand_path(file)
65
+ # You can optionally specify configuration with a block:
66
+ # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"]
67
+ # OR
68
+ # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' # using rails profile
69
+ # OR
70
+ # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"] do
71
+ # add_filter 'test'
72
+ # end
73
+ # OR
74
+ # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' do
75
+ # add_filter 'test'
76
+ # end
77
+ #
78
+ # Please check out the RDoc for SimpleCov::Configuration to find about
79
+ # available config options, or checkout the README for more in-depth
80
+ # information about coverage collation
81
+ #
82
+ # By default `collate` ignores the merge_timeout so all results of all files specified will be
83
+ # merged together. If you want to honor the merge_timeout then provide the keyword argument
84
+ # `ignore_timeout: false`.
85
+ #
86
+ def collate(result_filenames, profile = nil, ignore_timeout: true, &block)
87
+ raise "There are no reports to be merged" if result_filenames.empty?
70
88
 
71
- result[absolute] ||= LinesClassifier.new.classify(File.foreach(absolute))
72
- end
73
- end
89
+ initial_setup(profile, &block)
74
90
 
75
- result
91
+ # Use the ResultMerger to produce a single, merged result, ready to use.
92
+ @result = ResultMerger.merge_and_store(*result_filenames, ignore_timeout: ignore_timeout)
93
+
94
+ run_exit_tasks!
76
95
  end
77
96
 
78
97
  #
@@ -83,13 +102,12 @@ module SimpleCov
83
102
  return @result if result?
84
103
 
85
104
  # Collect our coverage result
86
- if running
87
- @result = SimpleCov::Result.new add_not_loaded_files(Coverage.result)
88
- end
105
+ process_coverage_result if running
89
106
 
90
107
  # If we're using merging of results, store the current result
91
108
  # first (if there is one), then merge the results and return those
92
109
  if use_merging
110
+ wait_for_other_processes
93
111
  SimpleCov::ResultMerger.store_result(@result) if result?
94
112
  @result = SimpleCov::ResultMerger.merged_result
95
113
  end
@@ -146,22 +164,6 @@ module SimpleCov
146
164
  load_profile(name)
147
165
  end
148
166
 
149
- #
150
- # Checks whether we're on a proper version of Ruby (likely 1.9+) which
151
- # provides coverage support
152
- #
153
- def usable?
154
- return @usable if defined?(@usable) && !@usable.nil?
155
-
156
- @usable = begin
157
- require "coverage"
158
- require "simplecov/jruby_fix"
159
- true
160
- rescue LoadError
161
- false
162
- end
163
- end
164
-
165
167
  #
166
168
  # Clear out the previously cached .result. Primarily useful in testing
167
169
  #
@@ -169,41 +171,73 @@ module SimpleCov
169
171
  @result = nil
170
172
  end
171
173
 
174
+ def at_exit_behavior
175
+ # If we are in a different process than called start, don't interfere.
176
+ return if SimpleCov.pid != Process.pid
177
+
178
+ # If SimpleCov is no longer running then don't run exit tasks
179
+ SimpleCov.run_exit_tasks! if SimpleCov.running
180
+ end
181
+
182
+ # @api private
172
183
  #
173
- # Capture the current exception if it exists
174
- # This will get called inside the at_exit block
184
+ # Called from at_exit block
175
185
  #
176
- def set_exit_exception
177
- @exit_exception = $ERROR_INFO
186
+ def run_exit_tasks!
187
+ error_exit_status = exit_status_from_exception
188
+
189
+ at_exit.call
190
+
191
+ exit_and_report_previous_error(error_exit_status) if previous_error?(error_exit_status)
192
+ process_results_and_report_error if ready_to_process_results?
178
193
  end
179
194
 
195
+ #
196
+ # @api private
180
197
  #
181
198
  # Returns the exit status from the exit exception
182
199
  #
183
200
  def exit_status_from_exception
184
- return SimpleCov::ExitCodes::SUCCESS unless exit_exception
201
+ # Capture the current exception if it exists
202
+ @exit_exception = $ERROR_INFO
203
+ return nil unless @exit_exception
185
204
 
186
- if exit_exception.is_a?(SystemExit)
187
- exit_exception.status
205
+ if @exit_exception.is_a?(SystemExit)
206
+ @exit_exception.status
188
207
  else
189
208
  SimpleCov::ExitCodes::EXCEPTION
190
209
  end
191
210
  end
192
211
 
193
212
  # @api private
213
+ def previous_error?(error_exit_status)
214
+ # Normally it'd be enough to check for previous error but when running test_unit
215
+ # status is 0
216
+ error_exit_status && error_exit_status != SimpleCov::ExitCodes::SUCCESS
217
+ end
218
+
194
219
  #
195
- # Called from at_exit block
220
+ # @api private
196
221
  #
197
- def run_exit_tasks!
198
- exit_status = SimpleCov.exit_status_from_exception
222
+ # Thinking: Move this behavior earlier so if there was an error we do nothing?
223
+ def exit_and_report_previous_error(exit_status)
224
+ warn("Stopped processing SimpleCov as a previous error not related to SimpleCov has been detected") if print_error_status
225
+ Kernel.exit(exit_status)
226
+ end
199
227
 
200
- SimpleCov.at_exit.call
228
+ # @api private
229
+ def ready_to_process_results?
230
+ final_result_process? && result?
231
+ end
201
232
 
202
- exit_status = SimpleCov.process_result(SimpleCov.result, exit_status)
233
+ def process_results_and_report_error
234
+ exit_status = process_result(result)
203
235
 
204
236
  # Force exit with stored status (see github issue #5)
205
- # unless it's nil or 0 (see github issue #281)
206
- Kernel.exit exit_status if exit_status && exit_status > 0
237
+ if exit_status.positive?
238
+ warn("SimpleCov failed with exit #{exit_status} due to a coverage related error") if print_error_status
239
+ Kernel.exit exit_status
240
+ end
207
241
  end
208
242
 
209
243
  # @api private
@@ -211,71 +245,224 @@ module SimpleCov
211
245
  # Usage:
212
246
  # exit_status = SimpleCov.process_result(SimpleCov.result, exit_status)
213
247
  #
214
- def process_result(result, exit_status)
215
- return exit_status unless SimpleCov.result? # Result has been computed
216
- return exit_status if exit_status != SimpleCov::ExitCodes::SUCCESS # Existing errors
217
-
218
- covered_percent = result.covered_percent.round(2)
219
- result_exit_status = result_exit_status(result, covered_percent)
220
- if result_exit_status == SimpleCov::ExitCodes::SUCCESS # No result errors
221
- write_last_run(covered_percent)
222
- end
248
+ def process_result(result)
249
+ result_exit_status = result_exit_status(result)
250
+ write_last_run(result) if result_exit_status == SimpleCov::ExitCodes::SUCCESS
223
251
  result_exit_status
224
252
  end
225
253
 
226
254
  # @api private
255
+ CoverageLimits = Struct.new(:minimum_coverage, :minimum_coverage_by_file, :maximum_coverage_drop, keyword_init: true)
256
+ def result_exit_status(result)
257
+ coverage_limits = CoverageLimits.new(
258
+ minimum_coverage: minimum_coverage, minimum_coverage_by_file: minimum_coverage_by_file,
259
+ maximum_coverage_drop: maximum_coverage_drop
260
+ )
261
+
262
+ ExitCodes::ExitCodeHandling.call(result, coverage_limits: coverage_limits)
263
+ end
264
+
227
265
  #
228
- # rubocop:disable Metrics/MethodLength
229
- def result_exit_status(result, covered_percent)
230
- covered_percentages = result.covered_percentages.map { |percentage| percentage.round(2) }
231
- if covered_percent < SimpleCov.minimum_coverage
232
- $stderr.printf("Coverage (%.2f%%) is below the expected minimum coverage (%.2f%%).\n", covered_percent, SimpleCov.minimum_coverage)
233
- SimpleCov::ExitCodes::MINIMUM_COVERAGE
234
- elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file }
235
- $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)
236
- SimpleCov::ExitCodes::MINIMUM_COVERAGE
237
- elsif (last_run = SimpleCov::LastRun.read)
238
- coverage_diff = last_run["result"]["covered_percent"] - covered_percent
239
- if coverage_diff > SimpleCov.maximum_coverage_drop
240
- $stderr.printf("Coverage has dropped by %.2f%% since the last time (maximum allowed: %.2f%%).\n", coverage_diff, SimpleCov.maximum_coverage_drop)
241
- SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
242
- else
243
- SimpleCov::ExitCodes::SUCCESS
244
- end
266
+ # @api private
267
+ #
268
+ def final_result_process?
269
+ # checking for ENV["TEST_ENV_NUMBER"] to determine if the tests are being run in parallel
270
+ !defined?(ParallelTests) || !ENV["TEST_ENV_NUMBER"] || ParallelTests.last_process?
271
+ end
272
+
273
+ #
274
+ # @api private
275
+ #
276
+ def wait_for_other_processes
277
+ return unless defined?(ParallelTests) && final_result_process?
278
+
279
+ ParallelTests.wait_for_other_processes_to_finish
280
+ end
281
+
282
+ #
283
+ # @api private
284
+ #
285
+ def write_last_run(result)
286
+ SimpleCov::LastRun.write(result:
287
+ result.coverage_statistics.transform_values do |stats|
288
+ round_coverage(stats.percent)
289
+ end)
290
+ end
291
+
292
+ #
293
+ # @api private
294
+ #
295
+ # Rounding down to be extra strict, see #679
296
+ def round_coverage(coverage)
297
+ coverage.floor(2)
298
+ end
299
+
300
+ private
301
+
302
+ def initial_setup(profile, &block)
303
+ load_profile(profile) if profile
304
+ configure(&block) if block_given?
305
+ self.running = true
306
+ end
307
+
308
+ #
309
+ # Trigger Coverage.start depends on given config coverage_criterion
310
+ #
311
+ # With Positive branch it supports all coverage measurement types
312
+ # With Negative branch it supports only line coverage measurement type
313
+ #
314
+ def start_coverage_measurement
315
+ # This blog post gives a good run down of the coverage criterias introduced
316
+ # in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
317
+ # There is also a nice writeup of the different coverage criteria made in this
318
+ # comment https://github.com/simplecov-ruby/simplecov/pull/692#discussion_r281836176 :
319
+ # Ruby < 2.5:
320
+ # https://github.com/ruby/ruby/blob/v1_9_3_374/ext/coverage/coverage.c
321
+ # traditional mode (Array)
322
+ #
323
+ # Ruby 2.5:
324
+ # https://bugs.ruby-lang.org/issues/13901
325
+ # https://github.com/ruby/ruby/blob/v2_5_3/ext/coverage/coverage.c
326
+ # default: traditional/compatible mode (Array)
327
+ # :lines - like traditional mode but using Hash
328
+ # :branches
329
+ # :methods
330
+ # :all - same as lines + branches + methods
331
+ #
332
+ # Ruby >= 2.6:
333
+ # https://bugs.ruby-lang.org/issues/15022
334
+ # https://github.com/ruby/ruby/blob/v2_6_3/ext/coverage/coverage.c
335
+ # default: traditional/compatible mode (Array)
336
+ # :lines - like traditional mode but using Hash
337
+ # :branches
338
+ # :methods
339
+ # :oneshot_lines - can not be combined with lines
340
+ # :all - same as lines + branches + methods
341
+ #
342
+ if coverage_start_arguments_supported?
343
+ start_coverage_with_criteria
245
344
  else
246
- SimpleCov::ExitCodes::SUCCESS
345
+ Coverage.start
247
346
  end
248
347
  end
249
- # rubocop:enable Metrics/MethodLength
348
+
349
+ def start_coverage_with_criteria
350
+ start_arguments = coverage_criteria.map do |criterion|
351
+ [lookup_corresponding_ruby_coverage_name(criterion), true]
352
+ end.to_h
353
+
354
+ Coverage.start(start_arguments)
355
+ end
356
+
357
+ CRITERION_TO_RUBY_COVERAGE = {
358
+ branch: :branches,
359
+ line: :lines
360
+ }.freeze
361
+ def lookup_corresponding_ruby_coverage_name(criterion)
362
+ CRITERION_TO_RUBY_COVERAGE.fetch(criterion)
363
+ end
250
364
 
251
365
  #
252
- # @api private
366
+ # Finds files that were to be tracked but were not loaded and initializes
367
+ # the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).
253
368
  #
254
- def write_last_run(covered_percent)
255
- SimpleCov::LastRun.write(:result => {:covered_percent => covered_percent})
369
+ def add_not_loaded_files(result)
370
+ if tracked_files
371
+ result = result.dup
372
+ Dir[tracked_files].each do |file|
373
+ absolute_path = File.expand_path(file)
374
+ result[absolute_path] ||= SimulateCoverage.call(absolute_path)
375
+ end
376
+ end
377
+
378
+ result
379
+ end
380
+
381
+ #
382
+ # Call steps that handle process coverage result
383
+ #
384
+ # @return [Hash]
385
+ #
386
+ def process_coverage_result
387
+ adapt_coverage_result
388
+ remove_useless_results
389
+ result_with_not_loaded_files
390
+ end
391
+
392
+ #
393
+ # Unite the result so it wouldn't matter what coverage type was called
394
+ #
395
+ # @return [Hash]
396
+ #
397
+ def adapt_coverage_result
398
+ @result = SimpleCov::ResultAdapter.call(Coverage.result)
399
+ end
400
+
401
+ #
402
+ # Filter coverage result
403
+ # The result before filter also has result of coverage for files
404
+ # are not related to the project like loaded gems coverage.
405
+ #
406
+ # @return [Hash]
407
+ #
408
+ def remove_useless_results
409
+ @result = SimpleCov::UselessResultsRemover.call(@result)
410
+ end
411
+
412
+ #
413
+ # Initialize result with files that are not included by coverage
414
+ # and added inside the config block
415
+ #
416
+ # @return [Hash]
417
+ #
418
+ def result_with_not_loaded_files
419
+ @result = SimpleCov::Result.new(add_not_loaded_files(@result))
420
+ end
421
+
422
+ # parallel_tests isn't always available, see: https://github.com/grosser/parallel_tests/issues/772
423
+ def make_parallel_tests_available
424
+ return if defined?(ParallelTests)
425
+ return unless probably_running_parallel_tests?
426
+
427
+ require "parallel_tests"
428
+ rescue LoadError
429
+ warn("SimpleCov guessed you were running inside parallel tests but couldn't load it. Please file a bug report with us!")
430
+ end
431
+
432
+ def probably_running_parallel_tests?
433
+ ENV["TEST_ENV_NUMBER"] && ENV["PARALLEL_TEST_GROUPS"]
256
434
  end
257
435
  end
258
436
  end
259
437
 
260
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
261
- require "simplecov/configuration"
262
- SimpleCov.send :extend, SimpleCov::Configuration
263
- require "simplecov/exit_codes"
264
- require "simplecov/profiles"
265
- require "simplecov/source_file"
266
- require "simplecov/file_list"
267
- require "simplecov/result"
268
- require "simplecov/filter"
269
- require "simplecov/formatter"
270
- require "simplecov/last_run"
271
- require "simplecov/lines_classifier"
272
- require "simplecov/raw_coverage"
273
- require "simplecov/result_merger"
274
- require "simplecov/command_guesser"
275
- require "simplecov/version"
438
+ # requires are down here here for a load order reason I'm not sure what it is about
439
+ require "set"
440
+ require "forwardable"
441
+ require_relative "simplecov/configuration"
442
+ SimpleCov.extend SimpleCov::Configuration
443
+ require_relative "simplecov/coverage_statistics"
444
+ require_relative "simplecov/exit_codes"
445
+ require_relative "simplecov/profiles"
446
+ require_relative "simplecov/source_file/line"
447
+ require_relative "simplecov/source_file/branch"
448
+ require_relative "simplecov/source_file"
449
+ require_relative "simplecov/file_list"
450
+ require_relative "simplecov/result"
451
+ require_relative "simplecov/filter"
452
+ require_relative "simplecov/formatter"
453
+ require_relative "simplecov/last_run"
454
+ require_relative "simplecov/lines_classifier"
455
+ require_relative "simplecov/result_merger"
456
+ require_relative "simplecov/command_guesser"
457
+ require_relative "simplecov/version"
458
+ require_relative "simplecov/result_adapter"
459
+ require_relative "simplecov/combine"
460
+ require_relative "simplecov/combine/branches_combiner"
461
+ require_relative "simplecov/combine/files_combiner"
462
+ require_relative "simplecov/combine/lines_combiner"
463
+ require_relative "simplecov/combine/results_combiner"
464
+ require_relative "simplecov/useless_results_remover"
465
+ require_relative "simplecov/simulate_coverage"
276
466
 
277
467
  # Load default config
278
- require "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
279
-
280
- # Load Rails integration (only for Rails 3, see #113)
281
- require "simplecov/railtie" if defined? Rails::Railtie
468
+ require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]