simplecov 0.18.5 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  ## Reporting Issues
2
2
 
3
- You can report issues at https://github.com/colszowka/simplecov/issues
3
+ You can report issues at https://github.com/simplecov-ruby/simplecov/issues
4
4
 
5
5
  Before you go ahead please search existing issues for your problem, chances are someone else already reported it.
6
6
 
@@ -10,7 +10,7 @@ To make sure that we can help you quickly please include and check the following
10
10
  - please ensure you are requiring and starting SimpleCov before requiring any application code.
11
11
  - If running via rake, please ensure you are requiring SimpleCov at the top of your Rakefile
12
12
  For example, if running via RSpec, this would be at the top of your spec_helper.
13
- - Have you tried using a [`.simplecov` file](https://github.com/colszowka/simplecov#using-simplecov-for-centralized-config)?
13
+ - Have you tried using a [`.simplecov` file](https://github.com/simplecov-ruby/simplecov#using-simplecov-for-centralized-config)?
14
14
  * Include the SimpleCov version you are running in your report.
15
15
  * If you are not running the latest version (please check), and you cannot update it,
16
16
  please specify in your report why you can't update to the latest version.
@@ -28,7 +28,7 @@ Thanks!
28
28
 
29
29
  To fetch & test the library for development, do:
30
30
 
31
- $ git clone https://github.com/colszowka/simplecov.git
31
+ $ git clone https://github.com/simplecov-ruby/simplecov.git
32
32
  $ cd simplecov
33
33
  $ bundle
34
34
  $ bundle exec rake
@@ -8,7 +8,7 @@ To make sure that we can help you quickly please include and check the following
8
8
  - please ensure you are requiring and starting SimpleCov before requiring any application code.
9
9
  - If running via rake, please ensure you are requiring SimpleCov at the top of your Rakefile
10
10
  For example, if running via RSpec, this would be at the top of your spec_helper.
11
- - Have you tried using a [`.simplecov` file](https://github.com/colszowka/simplecov#using-simplecov-for-centralized-config)?
11
+ - Have you tried using a [`.simplecov` file](https://github.com/simplecov-ruby/simplecov#using-simplecov-for-centralized-config)?
12
12
  * Include the SimpleCov version you are running in your report.
13
13
  * If you are not running the latest version (please check), and you cannot update it,
14
14
  please specify in your report why you can't update to the latest version.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- SimpleCov [![Gem Version](https://badge.fury.io/rb/simplecov.svg)](https://badge.fury.io/rb/simplecov) [![Build Status](https://github.com/colszowka/simplecov/workflows/stable/badge.svg?branch=master)][Continuous Integration] [![Code Climate](https://codeclimate.com/github/colszowka/simplecov.svg)](https://codeclimate.com/github/colszowka/simplecov) [![Inline docs](http://inch-ci.org/github/colszowka/simplecov.svg)](http://inch-ci.org/github/colszowka/simplecov)
1
+ SimpleCov [![Gem Version](https://badge.fury.io/rb/simplecov.svg)](https://badge.fury.io/rb/simplecov) [![Build Status](https://github.com/simplecov-ruby/simplecov/workflows/stable/badge.svg?branch=main)][Continuous Integration] [![Maintainability](https://api.codeclimate.com/v1/badges/c071d197d61953a7e482/maintainability)](https://codeclimate.com/github/simplecov-ruby/simplecov/maintainability) [![Inline docs](http://inch-ci.org/github/simplecov-ruby/simplecov.svg?branch=main)](http://inch-ci.org/github/simplecov-ruby/simplecov)
2
2
  =========
3
3
 
4
4
  **Code coverage for Ruby**
@@ -10,14 +10,14 @@ SimpleCov [![Gem Version](https://badge.fury.io/rb/simplecov.svg)](https://badge
10
10
  * [Continuous Integration]
11
11
 
12
12
  [Coverage]: https://ruby-doc.org/stdlib/libdoc/coverage/rdoc/Coverage.html "API doc for Ruby's Coverage library"
13
- [Source Code]: https://github.com/colszowka/simplecov "Source Code @ GitHub"
13
+ [Source Code]: https://github.com/simplecov-ruby/simplecov "Source Code @ GitHub"
14
14
  [API documentation]: http://rubydoc.info/gems/simplecov/frames "RDoc API Documentation at Rubydoc.info"
15
15
  [Configuration]: http://rubydoc.info/gems/simplecov/SimpleCov/Configuration "Configuration options API documentation"
16
- [Changelog]: https://github.com/colszowka/simplecov/blob/master/CHANGELOG.md "Project Changelog"
16
+ [Changelog]: https://github.com/simplecov-ruby/simplecov/blob/main/CHANGELOG.md "Project Changelog"
17
17
  [Rubygem]: http://rubygems.org/gems/simplecov "SimpleCov @ rubygems.org"
18
- [Continuous Integration]: https://github.com/colszowka/simplecov/actions?query=workflow%3Astable "SimpleCov is built around the clock by github.com"
19
- [Dependencies]: https://gemnasium.com/colszowka/simplecov "SimpleCov dependencies on Gemnasium"
20
- [simplecov-html]: https://github.com/colszowka/simplecov-html "SimpleCov HTML Formatter Source Code @ GitHub"
18
+ [Continuous Integration]: https://github.com/simplecov-ruby/simplecov/actions?query=workflow%3Astable "SimpleCov is built around the clock by github.com"
19
+ [Dependencies]: https://gemnasium.com/simplecov-ruby/simplecov "SimpleCov dependencies on Gemnasium"
20
+ [simplecov-html]: https://github.com/simplecov-ruby/simplecov-html "SimpleCov HTML Formatter Source Code @ GitHub"
21
21
 
22
22
  SimpleCov is a code coverage analysis tool for Ruby. It uses [Ruby's built-in Coverage][Coverage] library to gather code
23
23
  coverage data, but makes processing its results much easier by providing a clean API to filter, group, merge, format,
@@ -37,8 +37,8 @@ configured automatically when you launch SimpleCov. If you're curious, you can f
37
37
 
38
38
  *Code and Bug Reports*
39
39
 
40
- * [Issue Tracker](https://github.com/colszowka/simplecov/issues)
41
- * See [CONTRIBUTING](https://github.com/colszowka/simplecov/blob/master/CONTRIBUTING.md) for how to contribute along
40
+ * [Issue Tracker](https://github.com/simplecov-ruby/simplecov/issues)
41
+ * See [CONTRIBUTING](https://github.com/simplecov-ruby/simplecov/blob/main/CONTRIBUTING.md) for how to contribute along
42
42
  with some common problems to check out before creating an issue.
43
43
 
44
44
  *Questions, Problems, Suggestions, etc.*
@@ -167,8 +167,8 @@ to use SimpleCov with them. Here's an overview of the known ones:
167
167
  race conditions occur when results are merged.
168
168
  </td>
169
169
  <td>
170
- <a href="https://github.com/colszowka/simplecov/issues/64">#64</a> &amp;
171
- <a href="https://github.com/colszowka/simplecov/pull/185">#185</a>
170
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/64">#64</a> &amp;
171
+ <a href="https://github.com/simplecov-ruby/simplecov/pull/185">#185</a>
172
172
  </td>
173
173
  </tr>
174
174
  <tr>
@@ -192,7 +192,7 @@ to use SimpleCov with them. Here's an overview of the known ones:
192
192
  to explicitly set the output root using `SimpleCov.root('foo/bar/baz')`
193
193
  </td>
194
194
  <td>
195
- <a href="https://github.com/colszowka/simplecov/issues/95">#95</a>
195
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/95">#95</a>
196
196
  </td>
197
197
  </tr>
198
198
  <tr>
@@ -203,11 +203,11 @@ to use SimpleCov with them. Here's an overview of the known ones:
203
203
  Because of how Spork works internally (using preforking), there used to
204
204
  be trouble when using SimpleCov with it, but that has apparently been
205
205
  resolved with a specific configuration strategy. See <a
206
- href="https://github.com/colszowka/simplecov/issues/42#issuecomment-4440284">this</a>
206
+ href="https://github.com/simplecov-ruby/simplecov/issues/42#issuecomment-4440284">this</a>
207
207
  comment.
208
208
  </td>
209
209
  <td>
210
- <a href="https://github.com/colszowka/simplecov/issues/42#issuecomment-4440284">#42</a>
210
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/42#issuecomment-4440284">#42</a>
211
211
  </td>
212
212
  </tr>
213
213
  <tr>
@@ -218,7 +218,7 @@ to use SimpleCov with them. Here's an overview of the known ones:
218
218
  <a href="#want-to-use-spring-with-simplecov">See section below.</a>
219
219
  </td>
220
220
  <td>
221
- <a href="https://github.com/colszowka/simplecov/issues/381">#381</a>
221
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/381">#381</a>
222
222
  </td>
223
223
  </tr>
224
224
  <tr>
@@ -231,7 +231,7 @@ to use SimpleCov with them. Here's an overview of the known ones:
231
231
  (Dec 11th, 2011) should have this problem resolved.
232
232
  </td>
233
233
  <td>
234
- <a href="https://github.com/colszowka/simplecov/issues/45">#45</a> &amp;
234
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/45">#45</a> &amp;
235
235
  <a href="https://github.com/test-unit/test-unit/pull/12">test-unit/test-unit#12</a>
236
236
  </td>
237
237
  </tr>
@@ -429,7 +429,7 @@ end
429
429
  # :nocov:
430
430
  ```
431
431
 
432
- The name of the token can be changed to your liking. [Learn more about the nocov feature.]( https://github.com/colszowka/simplecov/blob/master/features/config_nocov_token.feature)
432
+ The name of the token can be changed to your liking. [Learn more about the nocov feature.]( https://github.com/simplecov-ruby/simplecov/blob/main/features/config_nocov_token.feature)
433
433
 
434
434
  **Note:** You shouldn't have to use the nocov token to skip private methods that are being included in your coverage. If
435
435
  you appropriately test the public interface of your classes and objects you should automatically get full coverage of
@@ -440,7 +440,7 @@ your private methods.
440
440
  By default, SimpleCov filters everything outside of the `SimpleCov.root` directory. However, sometimes you may want
441
441
  to include coverage reports for things you include as a gem, for example a Rails Engine.
442
442
 
443
- Here's an example by [@lsaffie](https://github.com/lsaffie) from [#221](https://github.com/colszowka/simplecov/issues/221)
443
+ Here's an example by [@lsaffie](https://github.com/lsaffie) from [#221](https://github.com/simplecov-ruby/simplecov/issues/221)
444
444
  that shows how you can achieve just that:
445
445
 
446
446
  ```ruby
@@ -614,6 +614,53 @@ namespace :coverage do
614
614
  end
615
615
  ```
616
616
 
617
+ ## Running simplecov against subprocesses
618
+
619
+ `SimpleCov.enable_for_subprocesses` will allow SimpleCov to observe subprocesses starting using `Process.fork`.
620
+ This modifies ruby's core Process.fork method so that SimpleCov can see into it, appending `" (subprocess #{pid})"`
621
+ to the `SimpleCov.command_name`, with results that can be merged together using SimpleCov's merging feature.
622
+
623
+ To configure this, use `.at_fork`.
624
+
625
+ ```ruby
626
+ SimpleCov.enable_for_subprocesses true
627
+ SimpleCov.at_fork do |pid|
628
+ # This needs a unique name so it won't be ovewritten
629
+ SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{pid})"
630
+ # be quiet, the parent process will be in charge of output and checking coverage totals
631
+ SimpleCov.print_error_status = false
632
+ SimpleCov.formatter SimpleCov::Formatter::SimpleFormatter
633
+ SimpleCov.minimum_coverage 0
634
+ # start
635
+ SimpleCov.start
636
+ end
637
+ ```
638
+
639
+ NOTE: SimpleCov must have already been started before `Process.fork` was called.
640
+
641
+ ### Running simplecov against spawned subprocesses
642
+
643
+ Perhaps you're testing a ruby script with `PTY.spawn` or `Open3.popen`, or `Process.spawn` or etc.
644
+ SimpleCov can cover this too.
645
+
646
+ Add a .simplecov_spawn.rb file to your project root
647
+ ```ruby
648
+ # .simplecov_spawn.rb
649
+ require 'simplecov' # this will also pick up whatever config is in .simplecov
650
+ # so ensure it just contains configuration, and doesn't call SimpleCov.start.
651
+ SimpleCov.command_name 'spawn' # As this is not for a test runner directly, script doesn't have a pre-defined base command_name
652
+ SimpleCov.at_fork.call(Process.pid) # Use the per-process setup described previously
653
+ SimpleCov.start # only now can we start.
654
+ ```
655
+ Then, instead of calling your script directly, like:
656
+ ```ruby
657
+ PTY.spawn('my_script.rb') do # ...
658
+ ```
659
+ Use bin/ruby to require the new .simplecov_spawn file, then your script
660
+ ```ruby
661
+ PTY.spawn('ruby -r./.simplecov_spawn my_script.rb') do # ...
662
+ ```
663
+
617
664
  ## Running coverage only on demand
618
665
 
619
666
  The Ruby STDLIB Coverage library that SimpleCov builds upon is *very* fast (on a ~10 min Rails test suite, the speed
@@ -794,7 +841,7 @@ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
794
841
 
795
842
  ## Ruby version compatibility
796
843
 
797
- SimpleCov is built in [Continuous Integration] on Ruby 2.4+ as well as JRuby 9.2+.
844
+ SimpleCov is built in [Continuous Integration] on Ruby 2.5+ as well as JRuby 9.2+.
798
845
 
799
846
  Note for JRuby => You need to pass JRUBY_OPTS="--debug" or create .jrubyrc and add debug.fullTrace=true
800
847
 
@@ -809,7 +856,7 @@ with them, you'll find that it often misreports coverage with the default config
809
856
  issue. Don't despair!
810
857
 
811
858
  One solution is to [explicitly call eager
812
- load](https://github.com/colszowka/simplecov/issues/381#issuecomment-347651728)
859
+ load](https://github.com/simplecov-ruby/simplecov/issues/381#issuecomment-347651728)
813
860
  in your `test_helper.rb` / `spec_helper.rb` after calling `SimpleCov.start`.
814
861
 
815
862
  ```ruby
@@ -868,7 +915,7 @@ Everyone participating in this project's development, issue trackers and other c
868
915
 
869
916
  ## Contributing
870
917
 
871
- See the [contributing guide](https://github.com/colszowka/simplecov/blob/master/CONTRIBUTING.md).
918
+ See the [contributing guide](https://github.com/simplecov-ruby/simplecov/blob/main/CONTRIBUTING.md).
872
919
 
873
920
  ## Kudos
874
921
 
@@ -1,7 +1,7 @@
1
1
  ## Alternate coverage report formatters
2
2
 
3
3
  The community around simplecov provides a whole bunch of alternate formatters beyond the official
4
- [simplecov-html](https://github.com/colszowka/simplecov-html) gem.
4
+ [simplecov-html](https://github.com/simplecov-ruby/simplecov-html) gem.
5
5
 
6
6
  If you have built or found one that is missing here, please send a Pull Request for this document!
7
7
 
@@ -15,6 +15,11 @@ A formatter that generates a coverage badge for use in your project's readme usi
15
15
 
16
16
  A formatter that generates a small coverage badge for use in your project's readme using the SVG.
17
17
 
18
+ #### [simplecov_badger](https://github.com/traels-it/simplecov_badger)
19
+ *by traels.it*
20
+
21
+ A formatter that uploads your coverage to a server, that will then host a SVG badge of the score. No need to have the badge stored in repository.
22
+
18
23
  #### [simplecov-cobertura](https://github.com/dashingrocket/simplecov-cobertura)
19
24
  *by Jesse Bowes*
20
25
 
@@ -55,7 +60,7 @@ A formatter that prints the coverage of the file under test when you run a singl
55
60
 
56
61
  t_wada AA formatter for SimpleCov
57
62
 
58
- #### [simplecov-material(https://github.com/chiefpansancolt/simplecov-material)
63
+ #### [simplecov-material](https://github.com/chiefpansancolt/simplecov-material)
59
64
  *by [Chiefpansancolt](https://github.com/chiefpansancolt)*
60
65
 
61
66
  A Material Designed HTML formatter with clean and easy search of files with a tabular left Navigation.
@@ -4,6 +4,11 @@ There is a bunch of services that offer integration with your existing CI pipeli
4
4
  reports. Please note these are not associated with the SimpleCov project itself, so please report problems with
5
5
  these integrations with their respective owners.
6
6
 
7
+ #### [Codacy](https://github.com/codacy/codacy-coverage-reporter)
8
+ *by [Codacy](https://www.codacy.com/)*
9
+
10
+ Upload coverage reports to [codacy.com](https://www.codacy.com/), a hosted (or self-hosted) software quality analysis platform that also includes coverage reporting.
11
+
7
12
  #### [codeclimate](https://github.com/codeclimate/ruby-test-reporter)
8
13
  *by [Code Climate](https://codeclimate.com/)*
9
14
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # How minitest plugins. See https://github.com/colszowka/simplecov/pull/756 for why we need this.
3
+ # How minitest plugins. See https://github.com/simplecov-ruby/simplecov/pull/756 for why we need this.
4
4
  # https://github.com/seattlerb/minitest#writing-extensions
5
5
  module Minitest
6
6
  def self.plugin_simplecov_init(_options)
@@ -7,8 +7,8 @@ if defined?(JRUBY_VERSION) && defined?(JRuby)
7
7
 
8
8
  # @see https://github.com/jruby/jruby/issues/1196
9
9
  # @see https://github.com/metricfu/metric_fu/pull/226
10
- # @see https://github.com/colszowka/simplecov/issues/420
11
- # @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
12
12
  # @see https://jira.codehaus.org/browse/JRUBY-6106
13
13
 
14
14
  unless org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED
@@ -23,9 +23,7 @@ end
23
23
  #
24
24
  module SimpleCov
25
25
  class << self
26
- attr_accessor :running
27
- attr_accessor :pid
28
- attr_reader :exit_exception
26
+ attr_accessor :running, :pid
29
27
 
30
28
  # Basically, should we take care of at_exit behavior or something else?
31
29
  # Used by the minitest plugin. See lib/minitest/simplecov_plugin.rb
@@ -52,6 +50,9 @@ module SimpleCov
52
50
  def start(profile = nil, &block)
53
51
  require "coverage"
54
52
  initial_setup(profile, &block)
53
+ require_relative "./simplecov/process" if SimpleCov.enabled_for_subprocesses?
54
+ make_parallel_tests_available
55
+
55
56
  @result = nil
56
57
  self.pid = Process.pid
57
58
 
@@ -84,13 +85,11 @@ module SimpleCov
84
85
 
85
86
  results = result_filenames.flat_map do |filename|
86
87
  # Re-create each included instance of SimpleCov::Result from the stored run data.
87
- (JSON.parse(File.read(filename)) || {}).map do |command_name, coverage|
88
- SimpleCov::Result.from_hash(command_name => coverage)
89
- end
88
+ Result.from_hash(JSON.parse(File.read(filename)) || {})
90
89
  end
91
90
 
92
91
  # Use the ResultMerger to produce a single, merged result, ready to use.
93
- @result = SimpleCov::ResultMerger.merge_and_store(*results)
92
+ @result = ResultMerger.merge_and_store(*results)
94
93
 
95
94
  run_exit_tasks!
96
95
  end
@@ -103,7 +102,6 @@ module SimpleCov
103
102
  return @result if result?
104
103
 
105
104
  # Collect our coverage result
106
-
107
105
  process_coverage_result if running
108
106
 
109
107
  # If we're using merging of results, store the current result
@@ -173,54 +171,71 @@ module SimpleCov
173
171
  @result = nil
174
172
  end
175
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
176
183
  #
177
- # Capture the current exception if it exists
178
- # This will get called inside the at_exit block
184
+ # Called from at_exit block
179
185
  #
180
- def set_exit_exception
181
- @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?
182
193
  end
183
194
 
195
+ #
196
+ # @api private
184
197
  #
185
198
  # Returns the exit status from the exit exception
186
199
  #
187
200
  def exit_status_from_exception
188
- 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
189
204
 
190
- if exit_exception.is_a?(SystemExit)
191
- exit_exception.status
205
+ if @exit_exception.is_a?(SystemExit)
206
+ @exit_exception.status
192
207
  else
193
208
  SimpleCov::ExitCodes::EXCEPTION
194
209
  end
195
210
  end
196
211
 
197
- def at_exit_behavior
198
- # If we are in a different process than called start, don't interfere.
199
- return if SimpleCov.pid != Process.pid
200
-
201
- # If SimpleCov is no longer running then don't run exit tasks
202
- SimpleCov.run_exit_tasks! if SimpleCov.running
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
203
217
  end
204
218
 
205
- # @api private
206
219
  #
207
- # Called from at_exit block
220
+ # @api private
208
221
  #
209
- def run_exit_tasks!
210
- set_exit_exception
211
-
212
- 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
213
227
 
214
- SimpleCov.at_exit.call
228
+ # @api private
229
+ def ready_to_process_results?
230
+ final_result_process? && result?
231
+ end
215
232
 
216
- # Don't modify the exit status unless the result has already been
217
- # computed
218
- exit_status = SimpleCov.process_result(SimpleCov.result, exit_status) if SimpleCov.result?
233
+ def process_results_and_report_error
234
+ exit_status = process_result(result)
219
235
 
220
236
  # Force exit with stored status (see github issue #5)
221
- # unless it's nil or 0 (see github issue #281)
222
- if exit_status&.positive?
223
- $stderr.printf("SimpleCov failed with exit %<exit_status>d\n", exit_status: exit_status) if print_error_status
237
+ if exit_status.positive?
238
+ warn("SimpleCov failed with exit #{exit_status} due to a coverage related error") if print_error_status
224
239
  Kernel.exit exit_status
225
240
  end
226
241
  end
@@ -230,55 +245,29 @@ module SimpleCov
230
245
  # Usage:
231
246
  # exit_status = SimpleCov.process_result(SimpleCov.result, exit_status)
232
247
  #
233
- def process_result(result, exit_status)
234
- return exit_status if exit_status != SimpleCov::ExitCodes::SUCCESS # Existing errors
235
-
236
- covered_percent = result.covered_percent.floor(2)
237
- result_exit_status = result_exit_status(result, covered_percent)
238
- write_last_run(covered_percent) if result_exit_status == SimpleCov::ExitCodes::SUCCESS # No result errors
239
- final_result_process? ? result_exit_status : SimpleCov::ExitCodes::SUCCESS
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
251
+ result_exit_status
240
252
  end
241
253
 
242
254
  # @api private
243
- #
244
- # rubocop:disable Metrics/MethodLength
245
- def result_exit_status(result, covered_percent)
246
- covered_percentages = result.covered_percentages.map { |percentage| percentage.floor(2) }
247
- if (minimum_violations = minimum_coverage_violated(result)).any?
248
- report_minimum_violated(minimum_violations)
249
- SimpleCov::ExitCodes::MINIMUM_COVERAGE
250
- elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file }
251
- $stderr.printf(
252
- "File (%<file>s) is only (%<least_covered_percentage>.2f%%) covered. This is below the expected minimum coverage per file of (%<min_coverage>.2f%%).\n",
253
- file: result.least_covered_file,
254
- least_covered_percentage: covered_percentages.min,
255
- min_coverage: SimpleCov.minimum_coverage_by_file
256
- )
257
- SimpleCov::ExitCodes::MINIMUM_COVERAGE
258
- elsif (last_run = SimpleCov::LastRun.read)
259
- coverage_diff = last_run[:result][:covered_percent] - covered_percent
260
- if coverage_diff > SimpleCov.maximum_coverage_drop
261
- $stderr.printf(
262
- "Coverage has dropped by %<drop_percent>.2f%% since the last time (maximum allowed: %<max_drop>.2f%%).\n",
263
- drop_percent: coverage_diff,
264
- max_drop: SimpleCov.maximum_coverage_drop
265
- )
266
- SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
267
- else
268
- SimpleCov::ExitCodes::SUCCESS
269
- end
270
- else
271
- SimpleCov::ExitCodes::SUCCESS
272
- end
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)
273
263
  end
274
- # rubocop:enable Metrics/MethodLength
275
264
 
276
265
  #
277
266
  # @api private
278
267
  #
279
268
  def final_result_process?
280
- # checking for ENV["TEST_ENV_NUMBER"] to determine if the tess are being run in parallel
281
- !defined?(ParallelTests) || !ENV["TEST_ENV_NUMBER"] || ParallelTests.number_of_running_processes <= 1
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?
282
271
  end
283
272
 
284
273
  #
@@ -293,8 +282,16 @@ module SimpleCov
293
282
  #
294
283
  # @api private
295
284
  #
296
- def write_last_run(covered_percent)
297
- SimpleCov::LastRun.write(result: {covered_percent: covered_percent})
285
+ def write_last_run(result)
286
+ SimpleCov::LastRun.write(result: {covered_percent: round_coverage(result.covered_percent)})
287
+ end
288
+
289
+ #
290
+ # @api private
291
+ #
292
+ # Rounding down to be extra strict, see #679
293
+ def round_coverage(coverage)
294
+ coverage.floor(2)
298
295
  end
299
296
 
300
297
  private
@@ -315,7 +312,7 @@ module SimpleCov
315
312
  # This blog post gives a good run down of the coverage criterias introduced
316
313
  # in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
317
314
  # There is also a nice writeup of the different coverage criteria made in this
318
- # comment https://github.com/colszowka/simplecov/pull/692#discussion_r281836176 :
315
+ # comment https://github.com/simplecov-ruby/simplecov/pull/692#discussion_r281836176 :
319
316
  # Ruby < 2.5:
320
317
  # https://github.com/ruby/ruby/blob/v1_9_3_374/ext/coverage/coverage.c
321
318
  # traditional mode (Array)
@@ -419,61 +416,50 @@ module SimpleCov
419
416
  @result = SimpleCov::Result.new(add_not_loaded_files(@result))
420
417
  end
421
418
 
422
- def minimum_coverage_violated(result)
423
- coverage_achieved = minimum_coverage.map do |criterion, percent|
424
- {
425
- criterion: criterion,
426
- minimum_expected: percent,
427
- actual: result.coverage_statistics[criterion].percent
428
- }
429
- end
419
+ # parallel_tests isn't always available, see: https://github.com/grosser/parallel_tests/issues/772
420
+ def make_parallel_tests_available
421
+ return if defined?(ParallelTests)
422
+ return unless probably_running_parallel_tests?
430
423
 
431
- coverage_achieved.select do |achieved|
432
- achieved.fetch(:actual) < achieved.fetch(:minimum_expected)
433
- end
424
+ require "parallel_tests"
425
+ rescue LoadError
426
+ warn("SimpleCov guessed you were running inside parallel tests but couldn't load it. Please file a bug report with us!")
434
427
  end
435
428
 
436
- def report_minimum_violated(violations)
437
- violations.each do |violation|
438
- $stderr.printf(
439
- "%<criterion>s coverage (%<covered>.2f%%) is below the expected minimum coverage (%<minimum_coverage>.2f%%).\n",
440
- covered: violation.fetch(:actual).floor(2),
441
- minimum_coverage: violation.fetch(:minimum_expected),
442
- criterion: violation.fetch(:criterion).capitalize
443
- )
444
- end
429
+ def probably_running_parallel_tests?
430
+ ENV["TEST_ENV_NUMBER"] && ENV["PARALLEL_TEST_GROUPS"]
445
431
  end
446
432
  end
447
433
  end
448
434
 
449
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
435
+ # requires are down here here for a load order reason I'm not sure what it is about
450
436
  require "set"
451
437
  require "forwardable"
452
- require "simplecov/configuration"
438
+ require_relative "simplecov/configuration"
453
439
  SimpleCov.extend SimpleCov::Configuration
454
- require "simplecov/coverage_statistics"
455
- require "simplecov/exit_codes"
456
- require "simplecov/profiles"
457
- require "simplecov/source_file/line"
458
- require "simplecov/source_file/branch"
459
- require "simplecov/source_file"
460
- require "simplecov/file_list"
461
- require "simplecov/result"
462
- require "simplecov/filter"
463
- require "simplecov/formatter"
464
- require "simplecov/last_run"
465
- require "simplecov/lines_classifier"
466
- require "simplecov/result_merger"
467
- require "simplecov/command_guesser"
468
- require "simplecov/version"
469
- require "simplecov/result_adapter"
470
- require "simplecov/combine"
471
- require "simplecov/combine/branches_combiner"
472
- require "simplecov/combine/files_combiner"
473
- require "simplecov/combine/lines_combiner"
474
- require "simplecov/combine/results_combiner"
475
- require "simplecov/useless_results_remover"
476
- require "simplecov/simulate_coverage"
440
+ require_relative "simplecov/coverage_statistics"
441
+ require_relative "simplecov/exit_codes"
442
+ require_relative "simplecov/profiles"
443
+ require_relative "simplecov/source_file/line"
444
+ require_relative "simplecov/source_file/branch"
445
+ require_relative "simplecov/source_file"
446
+ require_relative "simplecov/file_list"
447
+ require_relative "simplecov/result"
448
+ require_relative "simplecov/filter"
449
+ require_relative "simplecov/formatter"
450
+ require_relative "simplecov/last_run"
451
+ require_relative "simplecov/lines_classifier"
452
+ require_relative "simplecov/result_merger"
453
+ require_relative "simplecov/command_guesser"
454
+ require_relative "simplecov/version"
455
+ require_relative "simplecov/result_adapter"
456
+ require_relative "simplecov/combine"
457
+ require_relative "simplecov/combine/branches_combiner"
458
+ require_relative "simplecov/combine/files_combiner"
459
+ require_relative "simplecov/combine/lines_combiner"
460
+ require_relative "simplecov/combine/results_combiner"
461
+ require_relative "simplecov/useless_results_remover"
462
+ require_relative "simplecov/simulate_coverage"
477
463
 
478
464
  # Load default config
479
- require "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
465
+ require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]