simplecov 0.18.3 → 0.20.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.*
@@ -73,9 +73,10 @@ Getting started
73
73
  analysis to happen on. When testing a server process (e.g. a JSON API
74
74
  endpoint) via a separate test process (e.g. when using Selenium) where you
75
75
  want to see all code executed by the `rails server`, and not just code
76
- executed in your actual test files, you'll want to add something like this
76
+ executed in your actual test files, you need to require SimpleCov in the
77
+ server process. For rails for instance, you'll want to add something like this
77
78
  to the top of `bin/rails`, but below the "shebang" line (`#! /usr/bin/env
78
- ruby`):
79
+ ruby`) and after config/boot is required:
79
80
 
80
81
  ```ruby
81
82
  if ENV['RAILS_ENV'] == 'test'
@@ -167,8 +168,8 @@ to use SimpleCov with them. Here's an overview of the known ones:
167
168
  race conditions occur when results are merged.
168
169
  </td>
169
170
  <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>
171
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/64">#64</a> &amp;
172
+ <a href="https://github.com/simplecov-ruby/simplecov/pull/185">#185</a>
172
173
  </td>
173
174
  </tr>
174
175
  <tr>
@@ -192,7 +193,7 @@ to use SimpleCov with them. Here's an overview of the known ones:
192
193
  to explicitly set the output root using `SimpleCov.root('foo/bar/baz')`
193
194
  </td>
194
195
  <td>
195
- <a href="https://github.com/colszowka/simplecov/issues/95">#95</a>
196
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/95">#95</a>
196
197
  </td>
197
198
  </tr>
198
199
  <tr>
@@ -203,11 +204,11 @@ to use SimpleCov with them. Here's an overview of the known ones:
203
204
  Because of how Spork works internally (using preforking), there used to
204
205
  be trouble when using SimpleCov with it, but that has apparently been
205
206
  resolved with a specific configuration strategy. See <a
206
- href="https://github.com/colszowka/simplecov/issues/42#issuecomment-4440284">this</a>
207
+ href="https://github.com/simplecov-ruby/simplecov/issues/42#issuecomment-4440284">this</a>
207
208
  comment.
208
209
  </td>
209
210
  <td>
210
- <a href="https://github.com/colszowka/simplecov/issues/42#issuecomment-4440284">#42</a>
211
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/42#issuecomment-4440284">#42</a>
211
212
  </td>
212
213
  </tr>
213
214
  <tr>
@@ -218,7 +219,7 @@ to use SimpleCov with them. Here's an overview of the known ones:
218
219
  <a href="#want-to-use-spring-with-simplecov">See section below.</a>
219
220
  </td>
220
221
  <td>
221
- <a href="https://github.com/colszowka/simplecov/issues/381">#381</a>
222
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/381">#381</a>
222
223
  </td>
223
224
  </tr>
224
225
  <tr>
@@ -231,7 +232,7 @@ to use SimpleCov with them. Here's an overview of the known ones:
231
232
  (Dec 11th, 2011) should have this problem resolved.
232
233
  </td>
233
234
  <td>
234
- <a href="https://github.com/colszowka/simplecov/issues/45">#45</a> &amp;
235
+ <a href="https://github.com/simplecov-ruby/simplecov/issues/45">#45</a> &amp;
235
236
  <a href="https://github.com/test-unit/test-unit/pull/12">test-unit/test-unit#12</a>
236
237
  </td>
237
238
  </tr>
@@ -429,7 +430,7 @@ end
429
430
  # :nocov:
430
431
  ```
431
432
 
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)
433
+ 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
434
 
434
435
  **Note:** You shouldn't have to use the nocov token to skip private methods that are being included in your coverage. If
435
436
  you appropriately test the public interface of your classes and objects you should automatically get full coverage of
@@ -440,7 +441,7 @@ your private methods.
440
441
  By default, SimpleCov filters everything outside of the `SimpleCov.root` directory. However, sometimes you may want
441
442
  to include coverage reports for things you include as a gem, for example a Rails Engine.
442
443
 
443
- Here's an example by [@lsaffie](https://github.com/lsaffie) from [#221](https://github.com/colszowka/simplecov/issues/221)
444
+ Here's an example by [@lsaffie](https://github.com/lsaffie) from [#221](https://github.com/simplecov-ruby/simplecov/issues/221)
444
445
  that shows how you can achieve just that:
445
446
 
446
447
  ```ruby
@@ -614,6 +615,53 @@ namespace :coverage do
614
615
  end
615
616
  ```
616
617
 
618
+ ## Running simplecov against subprocesses
619
+
620
+ `SimpleCov.enable_for_subprocesses` will allow SimpleCov to observe subprocesses starting using `Process.fork`.
621
+ This modifies ruby's core Process.fork method so that SimpleCov can see into it, appending `" (subprocess #{pid})"`
622
+ to the `SimpleCov.command_name`, with results that can be merged together using SimpleCov's merging feature.
623
+
624
+ To configure this, use `.at_fork`.
625
+
626
+ ```ruby
627
+ SimpleCov.enable_for_subprocesses true
628
+ SimpleCov.at_fork do |pid|
629
+ # This needs a unique name so it won't be ovewritten
630
+ SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{pid})"
631
+ # be quiet, the parent process will be in charge of output and checking coverage totals
632
+ SimpleCov.print_error_status = false
633
+ SimpleCov.formatter SimpleCov::Formatter::SimpleFormatter
634
+ SimpleCov.minimum_coverage 0
635
+ # start
636
+ SimpleCov.start
637
+ end
638
+ ```
639
+
640
+ NOTE: SimpleCov must have already been started before `Process.fork` was called.
641
+
642
+ ### Running simplecov against spawned subprocesses
643
+
644
+ Perhaps you're testing a ruby script with `PTY.spawn` or `Open3.popen`, or `Process.spawn` or etc.
645
+ SimpleCov can cover this too.
646
+
647
+ Add a .simplecov_spawn.rb file to your project root
648
+ ```ruby
649
+ # .simplecov_spawn.rb
650
+ require 'simplecov' # this will also pick up whatever config is in .simplecov
651
+ # so ensure it just contains configuration, and doesn't call SimpleCov.start.
652
+ SimpleCov.command_name 'spawn' # As this is not for a test runner directly, script doesn't have a pre-defined base command_name
653
+ SimpleCov.at_fork.call(Process.pid) # Use the per-process setup described previously
654
+ SimpleCov.start # only now can we start.
655
+ ```
656
+ Then, instead of calling your script directly, like:
657
+ ```ruby
658
+ PTY.spawn('my_script.rb') do # ...
659
+ ```
660
+ Use bin/ruby to require the new .simplecov_spawn file, then your script
661
+ ```ruby
662
+ PTY.spawn('ruby -r./.simplecov_spawn my_script.rb') do # ...
663
+ ```
664
+
617
665
  ## Running coverage only on demand
618
666
 
619
667
  The Ruby STDLIB Coverage library that SimpleCov builds upon is *very* fast (on a ~10 min Rails test suite, the speed
@@ -786,6 +834,20 @@ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
786
834
  ])
787
835
  ```
788
836
 
837
+ ## JSON formatter
838
+
839
+ SimpleCov is packaged with a separate gem called [simplecov_json_formatter](https://github.com/codeclimate-community/simplecov_json_formatter) that provides you with a JSON formatter, this formatter could be useful for different use cases, such as for CI consumption or for reporting to external services.
840
+
841
+ In order to use it you will need to manually load the installed gem like so:
842
+
843
+ ```ruby
844
+ require "simplecov_json_formatter"
845
+ SimpleCov.formatter = SimpleCov::Formatter::JSONFormatter
846
+ ```
847
+
848
+ > _Note:_ In case you plan to report your coverage results to CodeClimate services, know that SimpleCov will automatically use the
849
+ > JSON formatter along with the HTML formatter when the `CC_TEST_REPORTER_ID` variable is present in the environment.
850
+
789
851
  ## Available formatters, editor integrations and hosted services
790
852
 
791
853
  * [Open Source formatter and integration plugins for SimpleCov](doc/alternate-formatters.md)
@@ -794,7 +856,7 @@ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
794
856
 
795
857
  ## Ruby version compatibility
796
858
 
797
- SimpleCov is built in [Continuous Integration] on Ruby 2.4+ as well as JRuby 9.2+.
859
+ SimpleCov is built in [Continuous Integration] on Ruby 2.5+ as well as JRuby 9.2+.
798
860
 
799
861
  Note for JRuby => You need to pass JRUBY_OPTS="--debug" or create .jrubyrc and add debug.fullTrace=true
800
862
 
@@ -809,7 +871,7 @@ with them, you'll find that it often misreports coverage with the default config
809
871
  issue. Don't despair!
810
872
 
811
873
  One solution is to [explicitly call eager
812
- load](https://github.com/colszowka/simplecov/issues/381#issuecomment-347651728)
874
+ load](https://github.com/simplecov-ruby/simplecov/issues/381#issuecomment-347651728)
813
875
  in your `test_helper.rb` / `spec_helper.rb` after calling `SimpleCov.start`.
814
876
 
815
877
  ```ruby
@@ -868,7 +930,7 @@ Everyone participating in this project's development, issue trackers and other c
868
930
 
869
931
  ## Contributing
870
932
 
871
- See the [contributing guide](https://github.com/colszowka/simplecov/blob/master/CONTRIBUTING.md).
933
+ See the [contributing guide](https://github.com/simplecov-ruby/simplecov/blob/main/CONTRIBUTING.md).
872
934
 
873
935
  ## Kudos
874
936
 
@@ -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,12 @@ 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-tailwindcss](https://github.com/chiefpansancolt/simplecov-tailwindcss)
64
+ *by [Chiefpansancolt](https://github.com/chiefpansancolt)*
65
+
66
+ A TailwindCSS & TailwindUI Designed HTML formatter with clean and easy search of files with a tabular left Navigation.
67
+
68
+ #### [simplecov-material](https://github.com/chiefpansancolt/simplecov-material)
59
69
  *by [Chiefpansancolt](https://github.com/chiefpansancolt)*
60
70
 
61
71
  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,11 +1,15 @@
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
- Minitest.after_run do
8
- SimpleCov.at_exit_behavior if SimpleCov.respond_to?(:at_exit_behavior)
7
+ if defined?(SimpleCov)
8
+ SimpleCov.external_at_exit = true
9
+
10
+ Minitest.after_run do
11
+ SimpleCov.at_exit_behavior
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -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,12 @@ 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
27
+
28
+ # Basically, should we take care of at_exit behavior or something else?
29
+ # Used by the minitest plugin. See lib/minitest/simplecov_plugin.rb
30
+ attr_accessor :external_at_exit
31
+ alias external_at_exit? external_at_exit
29
32
 
30
33
  #
31
34
  # Sets up SimpleCov to run against your project.
@@ -47,6 +50,11 @@ module SimpleCov
47
50
  def start(profile = nil, &block)
48
51
  require "coverage"
49
52
  initial_setup(profile, &block)
53
+ require_relative "./simplecov/process" if SimpleCov.enabled_for_subprocesses? &&
54
+ ::Process.respond_to?(:fork)
55
+
56
+ make_parallel_tests_available
57
+
50
58
  @result = nil
51
59
  self.pid = Process.pid
52
60
 
@@ -79,13 +87,11 @@ module SimpleCov
79
87
 
80
88
  results = result_filenames.flat_map do |filename|
81
89
  # Re-create each included instance of SimpleCov::Result from the stored run data.
82
- (JSON.parse(File.read(filename)) || {}).map do |command_name, coverage|
83
- SimpleCov::Result.from_hash(command_name => coverage)
84
- end
90
+ Result.from_hash(JSON.parse(File.read(filename)) || {})
85
91
  end
86
92
 
87
93
  # Use the ResultMerger to produce a single, merged result, ready to use.
88
- @result = SimpleCov::ResultMerger.merge_and_store(*results)
94
+ @result = ResultMerger.merge_and_store(*results)
89
95
 
90
96
  run_exit_tasks!
91
97
  end
@@ -98,7 +104,6 @@ module SimpleCov
98
104
  return @result if result?
99
105
 
100
106
  # Collect our coverage result
101
-
102
107
  process_coverage_result if running
103
108
 
104
109
  # If we're using merging of results, store the current result
@@ -168,54 +173,71 @@ module SimpleCov
168
173
  @result = nil
169
174
  end
170
175
 
176
+ def at_exit_behavior
177
+ # If we are in a different process than called start, don't interfere.
178
+ return if SimpleCov.pid != Process.pid
179
+
180
+ # If SimpleCov is no longer running then don't run exit tasks
181
+ SimpleCov.run_exit_tasks! if SimpleCov.running
182
+ end
183
+
184
+ # @api private
171
185
  #
172
- # Capture the current exception if it exists
173
- # This will get called inside the at_exit block
186
+ # Called from at_exit block
174
187
  #
175
- def set_exit_exception
176
- @exit_exception = $ERROR_INFO
188
+ def run_exit_tasks!
189
+ error_exit_status = exit_status_from_exception
190
+
191
+ at_exit.call
192
+
193
+ exit_and_report_previous_error(error_exit_status) if previous_error?(error_exit_status)
194
+ process_results_and_report_error if ready_to_process_results?
177
195
  end
178
196
 
197
+ #
198
+ # @api private
179
199
  #
180
200
  # Returns the exit status from the exit exception
181
201
  #
182
202
  def exit_status_from_exception
183
- return SimpleCov::ExitCodes::SUCCESS unless exit_exception
203
+ # Capture the current exception if it exists
204
+ @exit_exception = $ERROR_INFO
205
+ return nil unless @exit_exception
184
206
 
185
- if exit_exception.is_a?(SystemExit)
186
- exit_exception.status
207
+ if @exit_exception.is_a?(SystemExit)
208
+ @exit_exception.status
187
209
  else
188
210
  SimpleCov::ExitCodes::EXCEPTION
189
211
  end
190
212
  end
191
213
 
192
- def at_exit_behavior
193
- # If we are in a different process than called start, don't interfere.
194
- return if SimpleCov.pid != Process.pid
195
-
196
- # If SimpleCov is no longer running then don't run exit tasks
197
- SimpleCov.run_exit_tasks! if SimpleCov.running
214
+ # @api private
215
+ def previous_error?(error_exit_status)
216
+ # Normally it'd be enough to check for previous error but when running test_unit
217
+ # status is 0
218
+ error_exit_status && error_exit_status != SimpleCov::ExitCodes::SUCCESS
198
219
  end
199
220
 
200
- # @api private
201
221
  #
202
- # Called from at_exit block
222
+ # @api private
203
223
  #
204
- def run_exit_tasks!
205
- set_exit_exception
206
-
207
- exit_status = SimpleCov.exit_status_from_exception
224
+ # Thinking: Move this behavior earlier so if there was an error we do nothing?
225
+ def exit_and_report_previous_error(exit_status)
226
+ warn("Stopped processing SimpleCov as a previous error not related to SimpleCov has been detected") if print_error_status
227
+ Kernel.exit(exit_status)
228
+ end
208
229
 
209
- SimpleCov.at_exit.call
230
+ # @api private
231
+ def ready_to_process_results?
232
+ final_result_process? && result?
233
+ end
210
234
 
211
- # Don't modify the exit status unless the result has already been
212
- # computed
213
- exit_status = SimpleCov.process_result(SimpleCov.result, exit_status) if SimpleCov.result?
235
+ def process_results_and_report_error
236
+ exit_status = process_result(result)
214
237
 
215
238
  # Force exit with stored status (see github issue #5)
216
- # unless it's nil or 0 (see github issue #281)
217
- if exit_status&.positive?
218
- $stderr.printf("SimpleCov failed with exit %<exit_status>d\n", exit_status: exit_status) if print_error_status
239
+ if exit_status.positive?
240
+ warn("SimpleCov failed with exit #{exit_status} due to a coverage related error") if print_error_status
219
241
  Kernel.exit exit_status
220
242
  end
221
243
  end
@@ -225,55 +247,29 @@ module SimpleCov
225
247
  # Usage:
226
248
  # exit_status = SimpleCov.process_result(SimpleCov.result, exit_status)
227
249
  #
228
- def process_result(result, exit_status)
229
- return exit_status if exit_status != SimpleCov::ExitCodes::SUCCESS # Existing errors
230
-
231
- covered_percent = result.covered_percent.floor(2)
232
- result_exit_status = result_exit_status(result, covered_percent)
233
- write_last_run(covered_percent) if result_exit_status == SimpleCov::ExitCodes::SUCCESS # No result errors
234
- final_result_process? ? result_exit_status : SimpleCov::ExitCodes::SUCCESS
250
+ def process_result(result)
251
+ result_exit_status = result_exit_status(result)
252
+ write_last_run(result) if result_exit_status == SimpleCov::ExitCodes::SUCCESS
253
+ result_exit_status
235
254
  end
236
255
 
237
256
  # @api private
238
- #
239
- # rubocop:disable Metrics/MethodLength
240
- def result_exit_status(result, covered_percent)
241
- covered_percentages = result.covered_percentages.map { |percentage| percentage.floor(2) }
242
- if (minimum_violations = minimum_coverage_violated(result)).any?
243
- report_minimum_violated(minimum_violations)
244
- SimpleCov::ExitCodes::MINIMUM_COVERAGE
245
- elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file }
246
- $stderr.printf(
247
- "File (%<file>s) is only (%<least_covered_percentage>.2f%%) covered. This is below the expected minimum coverage per file of (%<min_coverage>.2f%%).\n",
248
- file: result.least_covered_file,
249
- least_covered_percentage: covered_percentages.min,
250
- min_coverage: SimpleCov.minimum_coverage_by_file
251
- )
252
- SimpleCov::ExitCodes::MINIMUM_COVERAGE
253
- elsif (last_run = SimpleCov::LastRun.read)
254
- coverage_diff = last_run[:result][:covered_percent] - covered_percent
255
- if coverage_diff > SimpleCov.maximum_coverage_drop
256
- $stderr.printf(
257
- "Coverage has dropped by %<drop_percent>.2f%% since the last time (maximum allowed: %<max_drop>.2f%%).\n",
258
- drop_percent: coverage_diff,
259
- max_drop: SimpleCov.maximum_coverage_drop
260
- )
261
- SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
262
- else
263
- SimpleCov::ExitCodes::SUCCESS
264
- end
265
- else
266
- SimpleCov::ExitCodes::SUCCESS
267
- end
257
+ CoverageLimits = Struct.new(:minimum_coverage, :minimum_coverage_by_file, :maximum_coverage_drop, keyword_init: true)
258
+ def result_exit_status(result)
259
+ coverage_limits = CoverageLimits.new(
260
+ minimum_coverage: minimum_coverage, minimum_coverage_by_file: minimum_coverage_by_file,
261
+ maximum_coverage_drop: maximum_coverage_drop
262
+ )
263
+
264
+ ExitCodes::ExitCodeHandling.call(result, coverage_limits: coverage_limits)
268
265
  end
269
- # rubocop:enable Metrics/MethodLength
270
266
 
271
267
  #
272
268
  # @api private
273
269
  #
274
270
  def final_result_process?
275
- # checking for ENV["TEST_ENV_NUMBER"] to determine if the tess are being run in parallel
276
- !defined?(ParallelTests) || !ENV["TEST_ENV_NUMBER"] || ParallelTests.number_of_running_processes <= 1
271
+ # checking for ENV["TEST_ENV_NUMBER"] to determine if the tests are being run in parallel
272
+ !defined?(ParallelTests) || !ENV["TEST_ENV_NUMBER"] || ParallelTests.last_process?
277
273
  end
278
274
 
279
275
  #
@@ -288,8 +284,16 @@ module SimpleCov
288
284
  #
289
285
  # @api private
290
286
  #
291
- def write_last_run(covered_percent)
292
- SimpleCov::LastRun.write(result: {covered_percent: covered_percent})
287
+ def write_last_run(result)
288
+ SimpleCov::LastRun.write(result: {covered_percent: round_coverage(result.covered_percent)})
289
+ end
290
+
291
+ #
292
+ # @api private
293
+ #
294
+ # Rounding down to be extra strict, see #679
295
+ def round_coverage(coverage)
296
+ coverage.floor(2)
293
297
  end
294
298
 
295
299
  private
@@ -310,7 +314,7 @@ module SimpleCov
310
314
  # This blog post gives a good run down of the coverage criterias introduced
311
315
  # in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
312
316
  # There is also a nice writeup of the different coverage criteria made in this
313
- # comment https://github.com/colszowka/simplecov/pull/692#discussion_r281836176 :
317
+ # comment https://github.com/simplecov-ruby/simplecov/pull/692#discussion_r281836176 :
314
318
  # Ruby < 2.5:
315
319
  # https://github.com/ruby/ruby/blob/v1_9_3_374/ext/coverage/coverage.c
316
320
  # traditional mode (Array)
@@ -414,61 +418,50 @@ module SimpleCov
414
418
  @result = SimpleCov::Result.new(add_not_loaded_files(@result))
415
419
  end
416
420
 
417
- def minimum_coverage_violated(result)
418
- coverage_achieved = minimum_coverage.map do |criterion, percent|
419
- {
420
- criterion: criterion,
421
- minimum_expected: percent,
422
- actual: result.coverage_statistics[criterion].percent
423
- }
424
- end
421
+ # parallel_tests isn't always available, see: https://github.com/grosser/parallel_tests/issues/772
422
+ def make_parallel_tests_available
423
+ return if defined?(ParallelTests)
424
+ return unless probably_running_parallel_tests?
425
425
 
426
- coverage_achieved.select do |achieved|
427
- achieved.fetch(:actual) < achieved.fetch(:minimum_expected)
428
- end
426
+ require "parallel_tests"
427
+ rescue LoadError
428
+ warn("SimpleCov guessed you were running inside parallel tests but couldn't load it. Please file a bug report with us!")
429
429
  end
430
430
 
431
- def report_minimum_violated(violations)
432
- violations.each do |violation|
433
- $stderr.printf(
434
- "%<criterion>s coverage (%<covered>.2f%%) is below the expected minimum coverage (%<minimum_coverage>.2f%%).\n",
435
- covered: violation.fetch(:actual).floor(2),
436
- minimum_coverage: violation.fetch(:minimum_expected),
437
- criterion: violation.fetch(:criterion).capitalize
438
- )
439
- end
431
+ def probably_running_parallel_tests?
432
+ ENV["TEST_ENV_NUMBER"] && ENV["PARALLEL_TEST_GROUPS"]
440
433
  end
441
434
  end
442
435
  end
443
436
 
444
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
437
+ # requires are down here here for a load order reason I'm not sure what it is about
445
438
  require "set"
446
439
  require "forwardable"
447
- require "simplecov/configuration"
440
+ require_relative "simplecov/configuration"
448
441
  SimpleCov.extend SimpleCov::Configuration
449
- require "simplecov/coverage_statistics"
450
- require "simplecov/exit_codes"
451
- require "simplecov/profiles"
452
- require "simplecov/source_file/line"
453
- require "simplecov/source_file/branch"
454
- require "simplecov/source_file"
455
- require "simplecov/file_list"
456
- require "simplecov/result"
457
- require "simplecov/filter"
458
- require "simplecov/formatter"
459
- require "simplecov/last_run"
460
- require "simplecov/lines_classifier"
461
- require "simplecov/result_merger"
462
- require "simplecov/command_guesser"
463
- require "simplecov/version"
464
- require "simplecov/result_adapter"
465
- require "simplecov/combine"
466
- require "simplecov/combine/branches_combiner"
467
- require "simplecov/combine/files_combiner"
468
- require "simplecov/combine/lines_combiner"
469
- require "simplecov/combine/results_combiner"
470
- require "simplecov/useless_results_remover"
471
- require "simplecov/simulate_coverage"
442
+ require_relative "simplecov/coverage_statistics"
443
+ require_relative "simplecov/exit_codes"
444
+ require_relative "simplecov/profiles"
445
+ require_relative "simplecov/source_file/line"
446
+ require_relative "simplecov/source_file/branch"
447
+ require_relative "simplecov/source_file"
448
+ require_relative "simplecov/file_list"
449
+ require_relative "simplecov/result"
450
+ require_relative "simplecov/filter"
451
+ require_relative "simplecov/formatter"
452
+ require_relative "simplecov/last_run"
453
+ require_relative "simplecov/lines_classifier"
454
+ require_relative "simplecov/result_merger"
455
+ require_relative "simplecov/command_guesser"
456
+ require_relative "simplecov/version"
457
+ require_relative "simplecov/result_adapter"
458
+ require_relative "simplecov/combine"
459
+ require_relative "simplecov/combine/branches_combiner"
460
+ require_relative "simplecov/combine/files_combiner"
461
+ require_relative "simplecov/combine/lines_combiner"
462
+ require_relative "simplecov/combine/results_combiner"
463
+ require_relative "simplecov/useless_results_remover"
464
+ require_relative "simplecov/simulate_coverage"
472
465
 
473
466
  # Load default config
474
- require "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
467
+ require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]