simplecov 0.18.5 → 0.21.1

Sign up to get free protection for your applications and to get access to all the features.
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>
@@ -294,7 +295,6 @@ information to be lost.
294
295
  Add branch coverage measurement statistics to your results. Supported in CRuby versions 2.5+.
295
296
 
296
297
  ```ruby
297
- # or in configure or just SimpleCov.enable_coverage :branch
298
298
  SimpleCov.start do
299
299
  enable_coverage :branch
300
300
  end
@@ -340,6 +340,22 @@ Hence, we recommend looking at both metrics together. Branch coverage might also
340
340
  overall metric to look at - while you might be missing only 10% of your lines that might
341
341
  account for 50% of your branches for instance.
342
342
 
343
+ ## Primary Coverage
344
+
345
+ By default, the primary coverage type is `line`. To set the primary coverage to something else, use the following:
346
+
347
+ ```ruby
348
+ # or in configure SimpleCov.primary_coverage :branch
349
+ SimpleCov.start do
350
+ enable_coverage :branch
351
+ primary_coverage :branch
352
+ end
353
+ ```
354
+
355
+ Primary coverage determines what will come in first all output, and the type of coverage to check if you don't specify the type of coverage when customizing exit behavior (`SimpleCov.minimum_coverage 90`).
356
+
357
+ Note that coverage must first be enabled for non-default coverage types.
358
+
343
359
  ## Filters
344
360
 
345
361
  Filters can be used to remove selected files from your coverage data. By default, a filter is applied that removes all
@@ -429,7 +445,7 @@ end
429
445
  # :nocov:
430
446
  ```
431
447
 
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)
448
+ 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
449
 
434
450
  **Note:** You shouldn't have to use the nocov token to skip private methods that are being included in your coverage. If
435
451
  you appropriately test the public interface of your classes and objects you should automatically get full coverage of
@@ -440,7 +456,7 @@ your private methods.
440
456
  By default, SimpleCov filters everything outside of the `SimpleCov.root` directory. However, sometimes you may want
441
457
  to include coverage reports for things you include as a gem, for example a Rails Engine.
442
458
 
443
- Here's an example by [@lsaffie](https://github.com/lsaffie) from [#221](https://github.com/colszowka/simplecov/issues/221)
459
+ Here's an example by [@lsaffie](https://github.com/lsaffie) from [#221](https://github.com/simplecov-ruby/simplecov/issues/221)
444
460
  that shows how you can achieve just that:
445
461
 
446
462
  ```ruby
@@ -614,6 +630,53 @@ namespace :coverage do
614
630
  end
615
631
  ```
616
632
 
633
+ ## Running simplecov against subprocesses
634
+
635
+ `SimpleCov.enable_for_subprocesses` will allow SimpleCov to observe subprocesses starting using `Process.fork`.
636
+ This modifies ruby's core Process.fork method so that SimpleCov can see into it, appending `" (subprocess #{pid})"`
637
+ to the `SimpleCov.command_name`, with results that can be merged together using SimpleCov's merging feature.
638
+
639
+ To configure this, use `.at_fork`.
640
+
641
+ ```ruby
642
+ SimpleCov.enable_for_subprocesses true
643
+ SimpleCov.at_fork do |pid|
644
+ # This needs a unique name so it won't be ovewritten
645
+ SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{pid})"
646
+ # be quiet, the parent process will be in charge of output and checking coverage totals
647
+ SimpleCov.print_error_status = false
648
+ SimpleCov.formatter SimpleCov::Formatter::SimpleFormatter
649
+ SimpleCov.minimum_coverage 0
650
+ # start
651
+ SimpleCov.start
652
+ end
653
+ ```
654
+
655
+ NOTE: SimpleCov must have already been started before `Process.fork` was called.
656
+
657
+ ### Running simplecov against spawned subprocesses
658
+
659
+ Perhaps you're testing a ruby script with `PTY.spawn` or `Open3.popen`, or `Process.spawn` or etc.
660
+ SimpleCov can cover this too.
661
+
662
+ Add a .simplecov_spawn.rb file to your project root
663
+ ```ruby
664
+ # .simplecov_spawn.rb
665
+ require 'simplecov' # this will also pick up whatever config is in .simplecov
666
+ # so ensure it just contains configuration, and doesn't call SimpleCov.start.
667
+ SimpleCov.command_name 'spawn' # As this is not for a test runner directly, script doesn't have a pre-defined base command_name
668
+ SimpleCov.at_fork.call(Process.pid) # Use the per-process setup described previously
669
+ SimpleCov.start # only now can we start.
670
+ ```
671
+ Then, instead of calling your script directly, like:
672
+ ```ruby
673
+ PTY.spawn('my_script.rb') do # ...
674
+ ```
675
+ Use bin/ruby to require the new .simplecov_spawn file, then your script
676
+ ```ruby
677
+ PTY.spawn('ruby -r./.simplecov_spawn my_script.rb') do # ...
678
+ ```
679
+
617
680
  ## Running coverage only on demand
618
681
 
619
682
  The Ruby STDLIB Coverage library that SimpleCov builds upon is *very* fast (on a ~10 min Rails test suite, the speed
@@ -739,30 +802,36 @@ to help ensure coverage is relatively consistent, rather than being skewed by pa
739
802
 
740
803
  ```ruby
741
804
  SimpleCov.minimum_coverage_by_file 80
805
+ # same as above (the default is to check line coverage by file)
806
+ SimpleCov.minimum_coverage_by_file line: 80
807
+ # check for a minimum line coverage by file of 90% and minimum 80% branch coverage
808
+ SimpleCov.minimum_coverage_by_file line: 90, branch: 80
742
809
  ```
743
810
 
744
- (not yet supported for branch coverage)
745
-
746
811
  ### Maximum coverage drop
747
812
 
748
813
  You can define the maximum coverage drop percentage at once. SimpleCov will return non-zero if exceeded.
749
814
 
750
815
  ```ruby
751
816
  SimpleCov.maximum_coverage_drop 5
817
+ # same as above (the default is to check line drop)
818
+ SimpleCov.maximum_coverage_drop line: 5
819
+ # check for a maximum line drop of 5% and maximum 10% branch drop
820
+ SimpleCov.maximum_coverage_drop line: 5, branch: 10
752
821
  ```
753
822
 
754
- (not yet supported for branch coverage)
755
-
756
823
  ### Refuse dropping coverage
757
824
 
758
825
  You can also entirely refuse dropping coverage between test runs:
759
826
 
760
827
  ```ruby
761
828
  SimpleCov.refuse_coverage_drop
829
+ # same as above (the default is to only refuse line drop)
830
+ SimpleCov.refuse_coverage_drop :line
831
+ # refuse drop for line and branch
832
+ SimpleCov.refuse_coverage_drop :line, :branch
762
833
  ```
763
834
 
764
- (not yet supported for branch coverage)
765
-
766
835
  ## Using your own formatter
767
836
 
768
837
  You can use your own formatter with:
@@ -786,6 +855,20 @@ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
786
855
  ])
787
856
  ```
788
857
 
858
+ ## JSON formatter
859
+
860
+ 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.
861
+
862
+ In order to use it you will need to manually load the installed gem like so:
863
+
864
+ ```ruby
865
+ require "simplecov_json_formatter"
866
+ SimpleCov.formatter = SimpleCov::Formatter::JSONFormatter
867
+ ```
868
+
869
+ > _Note:_ In case you plan to report your coverage results to CodeClimate services, know that SimpleCov will automatically use the
870
+ > JSON formatter along with the HTML formatter when the `CC_TEST_REPORTER_ID` variable is present in the environment.
871
+
789
872
  ## Available formatters, editor integrations and hosted services
790
873
 
791
874
  * [Open Source formatter and integration plugins for SimpleCov](doc/alternate-formatters.md)
@@ -794,7 +877,7 @@ SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
794
877
 
795
878
  ## Ruby version compatibility
796
879
 
797
- SimpleCov is built in [Continuous Integration] on Ruby 2.4+ as well as JRuby 9.2+.
880
+ SimpleCov is built in [Continuous Integration] on Ruby 2.5+ as well as JRuby 9.2+.
798
881
 
799
882
  Note for JRuby => You need to pass JRUBY_OPTS="--debug" or create .jrubyrc and add debug.fullTrace=true
800
883
 
@@ -809,7 +892,7 @@ with them, you'll find that it often misreports coverage with the default config
809
892
  issue. Don't despair!
810
893
 
811
894
  One solution is to [explicitly call eager
812
- load](https://github.com/colszowka/simplecov/issues/381#issuecomment-347651728)
895
+ load](https://github.com/simplecov-ruby/simplecov/issues/381#issuecomment-347651728)
813
896
  in your `test_helper.rb` / `spec_helper.rb` after calling `SimpleCov.start`.
814
897
 
815
898
  ```ruby
@@ -868,7 +951,7 @@ Everyone participating in this project's development, issue trackers and other c
868
951
 
869
952
  ## Contributing
870
953
 
871
- See the [contributing guide](https://github.com/colszowka/simplecov/blob/master/CONTRIBUTING.md).
954
+ See the [contributing guide](https://github.com/simplecov-ruby/simplecov/blob/main/CONTRIBUTING.md).
872
955
 
873
956
  ## Kudos
874
957
 
@@ -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,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)
@@ -3,19 +3,17 @@
3
3
  require "English"
4
4
 
5
5
  # Coverage may be inaccurate under JRUBY.
6
- if defined?(JRUBY_VERSION) && defined?(JRuby)
6
+ if defined?(JRUBY_VERSION) && defined?(JRuby) && !org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED
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
- unless org.jruby.RubyInstanceConfig.FULL_TRACE_ENABLED
15
- warn 'Coverage may be inaccurate; set the "--debug" command line option,' \
16
- ' or do JRUBY_OPTS="--debug"' \
17
- ' or set the "debug.fullTrace=true" option in your .jrubyrc'
18
- 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'
19
17
  end
20
18
 
21
19
  #
@@ -23,9 +21,7 @@ end
23
21
  #
24
22
  module SimpleCov
25
23
  class << self
26
- attr_accessor :running
27
- attr_accessor :pid
28
- attr_reader :exit_exception
24
+ attr_accessor :running, :pid
29
25
 
30
26
  # Basically, should we take care of at_exit behavior or something else?
31
27
  # Used by the minitest plugin. See lib/minitest/simplecov_plugin.rb
@@ -52,6 +48,11 @@ module SimpleCov
52
48
  def start(profile = nil, &block)
53
49
  require "coverage"
54
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
+
55
56
  @result = nil
56
57
  self.pid = Process.pid
57
58
 
@@ -60,6 +61,7 @@ module SimpleCov
60
61
 
61
62
  #
62
63
  # Collate a series of SimpleCov result files into a single SimpleCov output.
64
+ #
63
65
  # You can optionally specify configuration with a block:
64
66
  # SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"]
65
67
  # OR
@@ -77,20 +79,17 @@ module SimpleCov
77
79
  # available config options, or checkout the README for more in-depth
78
80
  # information about coverage collation
79
81
  #
80
- def collate(result_filenames, profile = nil, &block)
81
- raise "There's no reports to be merged" if result_filenames.empty?
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?
82
88
 
83
89
  initial_setup(profile, &block)
84
90
 
85
- results = result_filenames.flat_map do |filename|
86
- # 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
90
- end
91
-
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(*result_filenames, ignore_timeout: ignore_timeout)
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,19 @@ 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:
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
298
  end
299
299
 
300
300
  private
@@ -315,7 +315,7 @@ module SimpleCov
315
315
  # This blog post gives a good run down of the coverage criterias introduced
316
316
  # in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
317
317
  # 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 :
318
+ # comment https://github.com/simplecov-ruby/simplecov/pull/692#discussion_r281836176 :
319
319
  # Ruby < 2.5:
320
320
  # https://github.com/ruby/ruby/blob/v1_9_3_374/ext/coverage/coverage.c
321
321
  # traditional mode (Array)
@@ -419,61 +419,50 @@ module SimpleCov
419
419
  @result = SimpleCov::Result.new(add_not_loaded_files(@result))
420
420
  end
421
421
 
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
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?
430
426
 
431
- coverage_achieved.select do |achieved|
432
- achieved.fetch(:actual) < achieved.fetch(:minimum_expected)
433
- end
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!")
434
430
  end
435
431
 
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
432
+ def probably_running_parallel_tests?
433
+ ENV["TEST_ENV_NUMBER"] && ENV["PARALLEL_TEST_GROUPS"]
445
434
  end
446
435
  end
447
436
  end
448
437
 
449
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
438
+ # requires are down here here for a load order reason I'm not sure what it is about
450
439
  require "set"
451
440
  require "forwardable"
452
- require "simplecov/configuration"
441
+ require_relative "simplecov/configuration"
453
442
  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"
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"
477
466
 
478
467
  # Load default config
479
- require "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]
468
+ require_relative "simplecov/defaults" unless ENV["SIMPLECOV_NO_DEFAULTS"]