simplecov 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -7
  2. data/.rspec +3 -1
  3. data/.rubocop.yml +6 -5
  4. data/CHANGELOG.md +16 -2
  5. data/Gemfile +14 -14
  6. data/README.md +28 -12
  7. data/Rakefile +5 -8
  8. data/features/config_formatters.feature +1 -1
  9. data/features/config_tracked_files.feature +29 -0
  10. data/features/step_definitions/transformers.rb +1 -1
  11. data/features/support/env.rb +6 -3
  12. data/lib/simplecov.rb +19 -2
  13. data/lib/simplecov/configuration.rb +24 -4
  14. data/lib/simplecov/defaults.rb +28 -5
  15. data/lib/simplecov/file_list.rb +11 -0
  16. data/lib/simplecov/filter.rb +1 -1
  17. data/lib/simplecov/formatter/multi_formatter.rb +17 -13
  18. data/lib/simplecov/result.rb +1 -1
  19. data/lib/simplecov/source_file.rb +6 -3
  20. data/lib/simplecov/version.rb +1 -1
  21. data/spec/1_8_fallbacks_spec.rb +29 -0
  22. data/spec/command_guesser_spec.rb +46 -0
  23. data/spec/deleted_source_spec.rb +12 -0
  24. data/{test → spec}/faked_project/Gemfile +0 -0
  25. data/{test → spec}/faked_project/Rakefile +0 -0
  26. data/{test → spec}/faked_project/cucumber.yml +0 -0
  27. data/{test → spec}/faked_project/features/step_definitions/my_steps.rb +0 -0
  28. data/{test → spec}/faked_project/features/support/env.rb +0 -0
  29. data/{test → spec}/faked_project/features/test_stuff.feature +0 -0
  30. data/{test → spec}/faked_project/lib/faked_project.rb +1 -1
  31. data/{test → spec}/faked_project/lib/faked_project/framework_specific.rb +0 -0
  32. data/{test → spec}/faked_project/lib/faked_project/meta_magic.rb +0 -0
  33. data/{test → spec}/faked_project/lib/faked_project/some_class.rb +0 -0
  34. data/spec/faked_project/lib/faked_project/untested_class.rb +11 -0
  35. data/{test → spec}/faked_project/spec/faked_spec.rb +0 -0
  36. data/{test → spec}/faked_project/spec/forking_spec.rb +0 -0
  37. data/{test → spec}/faked_project/spec/meta_magic_spec.rb +0 -0
  38. data/{test → spec}/faked_project/spec/some_class_spec.rb +0 -0
  39. data/{test → spec}/faked_project/spec/spec_helper.rb +0 -0
  40. data/{test → spec}/faked_project/test/faked_test.rb +0 -0
  41. data/{test → spec}/faked_project/test/meta_magic_test.rb +0 -0
  42. data/{test → spec}/faked_project/test/some_class_test.rb +0 -0
  43. data/{test → spec}/faked_project/test/test_helper.rb +0 -0
  44. data/spec/file_list_spec.rb +48 -0
  45. data/spec/filters_spec.rb +96 -0
  46. data/{test → spec}/fixtures/app/controllers/sample_controller.rb +0 -0
  47. data/{test → spec}/fixtures/app/models/user.rb +0 -0
  48. data/{test → spec}/fixtures/deleted_source_sample.rb +0 -0
  49. data/{test → spec}/fixtures/frameworks/rspec_bad.rb +0 -0
  50. data/{test → spec}/fixtures/frameworks/rspec_good.rb +0 -0
  51. data/{test → spec}/fixtures/frameworks/testunit_bad.rb +0 -0
  52. data/{test → spec}/fixtures/frameworks/testunit_good.rb +0 -0
  53. data/{test → spec}/fixtures/iso-8859.rb +0 -0
  54. data/{test → spec}/fixtures/resultset1.rb +0 -0
  55. data/{test → spec}/fixtures/resultset2.rb +0 -0
  56. data/{test → spec}/fixtures/sample.rb +0 -0
  57. data/{test → spec}/fixtures/utf-8.rb +0 -0
  58. data/{test → spec}/helper.rb +3 -7
  59. data/spec/merge_helpers_spec.rb +108 -0
  60. data/spec/result_spec.rb +207 -0
  61. data/spec/return_codes_spec.rb +37 -0
  62. data/spec/source_file_line_spec.rb +153 -0
  63. data/spec/source_file_spec.rb +75 -0
  64. metadata +163 -149
  65. data/test/shoulda_macros.rb +0 -19
  66. data/test/test_1_8_fallbacks.rb +0 -31
  67. data/test/test_command_guesser.rb +0 -19
  68. data/test/test_deleted_source.rb +0 -14
  69. data/test/test_file_list.rb +0 -23
  70. data/test/test_filters.rb +0 -94
  71. data/test/test_merge_helpers.rb +0 -112
  72. data/test/test_result.rb +0 -175
  73. data/test/test_return_codes.rb +0 -41
  74. data/test/test_source_file.rb +0 -73
  75. data/test/test_source_file_line.rb +0 -106
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA512:
3
- metadata.gz: 48711e9d1476719d339f0086b8f35b64be59364bbbf5c0d3c767c56a7857dd1afa576b05278a1c74aa8a346d97817676eef1d48f3f10ec1e8b4e452fc4445f56
4
- data.tar.gz: 88dad87cce15389b66baa7d2bb73f675fe168e2dd4168fef863310b053cf989a10a1fdced39b2d10616e8187c48d342236da8e0e17e915d34b4588da949737a2
5
- SHA1:
6
- metadata.gz: ce56b638173500ad25afd14ce524ff192753fc7e
7
- data.tar.gz: 5279e97dae54994a96c976917ce820c5af60cbcb
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bcd3fcd0c8e30121cc9f50e81b8b756f1153e8a3
4
+ data.tar.gz: 58d53aacce8c59039020aa58c651c6c66b04c414
5
+ SHA512:
6
+ metadata.gz: 8edc40314d68f3964d6cdba4d99a9afb07f15e7bafdc5ecccdeda85ce2d662ff5016ccc0b5e78edf5668ca40c92bf168d2f3b031ca08b541a18f15d717354f69
7
+ data.tar.gz: 60b3f714f8701072f44186639a4915aae3b8fdd8341e31ad41b2bde07961917052c012106fccad8b2a54ced75be9f84f7f1f743b3ef64a7b7bd0671c906eea83
data/.rspec CHANGED
@@ -1 +1,3 @@
1
- --require rspec/legacy_formatters
1
+ --color
2
+ --order random
3
+ --warning
@@ -1,13 +1,13 @@
1
1
  AllCops:
2
2
  Exclude:
3
- - 'test/fixtures/iso-8859.rb'
3
+ - 'spec/fixtures/iso-8859.rb'
4
4
  - 'tmp/**/*'
5
5
  - 'vendor/bundle/**/*'
6
6
 
7
7
  Lint/AmbiguousRegexpLiteral:
8
8
  Exclude:
9
9
  - 'features/**/*_steps.rb'
10
- - 'test/**/*_steps.rb'
10
+ - 'spec/**/*_steps.rb'
11
11
  - 'tmp/**/*_steps.rb'
12
12
 
13
13
  Metrics/AbcSize:
@@ -55,15 +55,16 @@ Style/SpaceInsideHashLiteralBraces:
55
55
 
56
56
  Style/SpecialGlobalVars:
57
57
  Exclude:
58
- - 'test/test_deleted_source.rb'
59
- - 'test/test_return_codes.rb'
58
+ - 'spec/deleted_source_spec.rb'
59
+ - 'spec/return_codes_spec.rb'
60
+ - 'lib/simplecov/defaults.rb'
60
61
 
61
62
  Style/StringLiterals:
62
63
  EnforcedStyle: double_quotes
63
64
 
64
65
  Style/FileName:
65
66
  Exclude:
66
- - 'test/fixtures/utf-8.rb'
67
+ - 'spec/fixtures/utf-8.rb'
67
68
 
68
69
  Style/TrailingComma:
69
70
  EnforcedStyleForMultiline: 'comma'
@@ -1,11 +1,25 @@
1
- Unreleased ([changes](https://github.com/colszowka/simplecov/compare/v0.10.0...master))
1
+ Unreleased ([changes](https://github.com/colszowka/simplecov/compare/v0.11.0...master))
2
2
  =================
3
3
 
4
4
  ## Enhancements
5
5
 
6
6
  ## Bugfixes
7
7
 
8
- 0.10.0 2015-04-18 ([changes](https://github.com/colszowka/simplecov/compare/v0.9.2...0.10.0))
8
+ 0.11.0 2015-11-29 ([changes](https://github.com/colszowka/simplecov/compare/v0.10.0...v0.10.11))
9
+ =================
10
+
11
+ ## Enhancements
12
+
13
+ * Added `SimpleCov.minimum_coverage_by_file` for per-file coverage thresholds. See [#392](https://github.com/colszowka/simplecov/pull/392) (thanks @ptashman)
14
+ * Added `track_files` configuration option to specify a glob to always include in coverage results, whether or not those files are required. See [#422](https://github.com/colszowka/simplecov/pull/422) (thanks @hugopeixoto)
15
+ * Speed up `root_filter` by an order of magnitude. See [#396](https://github.com/colszowka/simplecov/pull/396) (thanks @raszi)
16
+
17
+ ## Bugfixes
18
+
19
+ * Fix warning about global variable `$ERROR_INFO`. See [#400](https://github.com/colszowka/simplecov/pull/400) (thanks @amatsuda)
20
+ * Actually recurse upward looking for `.simplecov`, as claimed by the documentation, rather than only the working directory. See [#423](https://github.com/colszowka/simplecov/pull/423) (thanks @alexdowad)
21
+
22
+ 0.10.0 2015-04-18 ([changes](https://github.com/colszowka/simplecov/compare/v0.9.2...v0.10.0))
9
23
  =================
10
24
 
11
25
  ## Enhancements
data/Gemfile CHANGED
@@ -9,26 +9,26 @@ source "https://rubygems.org"
9
9
  gem "rake", ">= 10.3"
10
10
 
11
11
  group :test do
12
+ gem "rspec", ">= 3.2"
12
13
  # Older versions of some gems required for Ruby 1.8.7 support
13
14
  platform :ruby_18 do
14
15
  gem "activesupport", "~> 3.2.21"
15
- gem "shoulda-matchers", "~> 2.0.0"
16
16
  gem "i18n", "~> 0.6.11"
17
17
  end
18
- gem "rubocop", ">= 0.30", :platforms => [:ruby_19, :ruby_20, :ruby_21, :ruby_22]
19
- gem "minitest", ">= 5.5"
20
- gem "rspec", ">= 3.0"
21
- gem "rspec-legacy_formatters", ">= 1.0"
22
- gem "shoulda", ">= 3.5"
23
- end
18
+ platform :jruby, :ruby_19, :ruby_20, :ruby_21, :ruby_22 do
19
+ gem "aruba", "~> 0.7.4"
20
+ gem "capybara", "~> 2.4"
21
+
22
+ # Hack until Capybara fixes its gemspec. 3.0 removed 1.9 support.
23
+ # See https://github.com/jnicklas/capybara/issues/1615
24
+ gem "mime-types", "~> 2.0.0"
24
25
 
25
- platform :jruby, :ruby_19, :ruby_20, :ruby_21, :ruby_22 do
26
- gem "aruba", "~> 0.6"
27
- gem "capybara", "~> 2.0.0"
28
- gem "cucumber", "~> 2.0"
29
- gem "phantomjs", "~> 1.9"
30
- gem "poltergeist", "~> 1.1"
31
- gem "test-unit", "~> 3.0"
26
+ gem "cucumber", "~> 2.0"
27
+ gem "phantomjs", "~> 1.9"
28
+ gem "poltergeist", "~> 1.1"
29
+ gem "rubocop", ">= 0.30"
30
+ gem "test-unit", "~> 3.0"
31
+ end
32
32
  end
33
33
 
34
34
  gemspec
data/README.md CHANGED
@@ -145,8 +145,8 @@ to use SimpleCov with them. Here's an overview of the known ones:
145
145
  <td>
146
146
  As of 0.8.0, SimpleCov should correctly recognize parallel_tests and
147
147
  supplement your test suite names with their corresponding test env
148
- numbers. Locking of the resultset cache should ensure no race conditions
149
- occur when results are merged.
148
+ numbers. SimpleCov locks the resultset cache while merging, ensuring no
149
+ race conditions occur when results are merged.
150
150
  </td>
151
151
  <td>
152
152
  <a href="https://github.com/colszowka/simplecov/issues/64">#64</a> &amp;
@@ -391,17 +391,17 @@ There are two things to note here though:
391
391
 
392
392
  ### Test suite names
393
393
 
394
- SimpleCov tries to guess the name of the currently running test suite based upon the shell command the tests are running
395
- on. This should work fine for Unit Tests, RSpec, and Cucumber. If it fails, it will use the shell command
396
- that invoked the test suite as a command name.
394
+ SimpleCov tries to guess the name of the currently running test suite based upon the shell command the tests
395
+ are running on. This should work fine for Unit Tests, RSpec, and Cucumber. If it fails, it will use the shell
396
+ command that invoked the test suite as a command name.
397
397
 
398
- If you have some non-standard setup and still want nicely labeled test suites, you have to give Simplecov a cue as to what the
399
- name of the currently running test suite is. You can do so by specifying `SimpleCov.command_name` in one test file that is
400
- part of your specific suite.
398
+ If you have some non-standard setup and still want nicely labeled test suites, you have to give Simplecov a
399
+ cue as to what the name of the currently running test suite is. You can do so by specifying
400
+ `SimpleCov.command_name` in one test file that is part of your specific suite.
401
401
 
402
402
  To customize the suite names on a Rails app (yeah, sorry for being Rails-biased, but everyone knows what
403
- the structure of those projects is. You can apply this accordingly to the RSpecs in your Outlook-WebDAV-Calendar-Sync gem),
404
- you could do something like this:
403
+ the structure of those projects is. You can apply this accordingly to the RSpecs in your
404
+ Outlook-WebDAV-Calendar-Sync gem), you could do something like this:
405
405
 
406
406
  ```ruby
407
407
  # test/unit/some_test.rb
@@ -417,8 +417,8 @@ SimpleCov.command_name "test:integration"
417
417
  SimpleCov.command_name "features"
418
418
  ```
419
419
 
420
- Note that this only has to be invoked ONCE PER TEST SUITE, so even if you have 200 unit test files, specifying it in
421
- some_test.rb is enough.
420
+ Note that this only has to be invoked ONCE PER TEST SUITE, so even if you have 200 unit test files,
421
+ specifying it in `some_test.rb` is enough.
422
422
 
423
423
  Last but not least **if multiple suites resolve to the same `command_name`** be aware that the coverage results **will
424
424
  clobber each other instead of being merged**. SimpleCov is smart enough to detect unique names for the most common
@@ -431,6 +431,14 @@ If you are relying on the default `command_name` then SimpleCov will attempt to
431
431
  parallel test runner does not set one or both of these then *you must* set a `command_name` and ensure that it is unique
432
432
  per process (eg. `command_name "Unit Tests PID #{$$}"`).
433
433
 
434
+ If you are using parallel_tests, you must incorporate `TEST_ENV_NUMBER` into the command name yourself, in
435
+ order for SimpleCov to merge the results correctly. For example:
436
+
437
+ ```ruby
438
+ # spec/spec_helper.rb
439
+ SimpleCov.command_name "features" + (ENV['TEST_ENV_NUMBER'] || '')
440
+ ```
441
+
434
442
  [simplecov-html] prints the used test suites in the footer of the generated coverage report.
435
443
 
436
444
  ### Timeout for merge
@@ -539,6 +547,14 @@ You can define the minimum coverage percentage expected. SimpleCov will return n
539
547
  SimpleCov.minimum_coverage 90
540
548
  ```
541
549
 
550
+ ### Minimum coverage by file
551
+
552
+ You can define the minimum coverage by file percentage expected. SimpleCov will return non-zero if unmet. This is useful to help ensure coverage is relatively consistent, rather than being skewed by particularly good or bad areas of the code.
553
+
554
+ ```ruby
555
+ SimpleCov.minimum_coverage_by_file 80
556
+ ```
557
+
542
558
  ### Maximum coverage drop
543
559
 
544
560
  You can define the maximum coverage drop percentage at once. SimpleCov will return non-zero if exceeded.
data/Rakefile CHANGED
@@ -12,12 +12,9 @@ end
12
12
  # Enforce proper permissions on each build
13
13
  Rake::Task[:build].prerequisites.unshift :fix_permissions
14
14
 
15
- require "rake/testtask"
16
- Rake::TestTask.new(:test) do |test|
17
- test.libs << "lib" << "test"
18
- test.test_files = FileList["test/test_*.rb"]
19
- test.verbose = true
20
- test.warning = true
15
+ require "rspec/core/rake_task"
16
+ RSpec::Core::RakeTask.new(:spec) do |spec|
17
+ spec.pattern = FileList["spec/*_spec.rb"]
21
18
  end
22
19
 
23
20
  begin
@@ -33,7 +30,7 @@ end
33
30
  if RUBY_VERSION >= "1.9"
34
31
  require "cucumber/rake/task"
35
32
  Cucumber::Rake::Task.new
36
- task :default => [:test, :cucumber, :rubocop]
33
+ task :default => [:spec, :cucumber, :rubocop]
37
34
  else
38
- task :default => [:test]
35
+ task :default => [:spec]
39
36
  end
@@ -30,7 +30,7 @@ Feature:
30
30
  Given SimpleCov for Test/Unit is configured with:
31
31
  """
32
32
  require 'simplecov'
33
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
33
+ SimpleCov.formatters = [
34
34
  SimpleCov::Formatter::SimpleFormatter,
35
35
  Class.new do
36
36
  def format(result)
@@ -0,0 +1,29 @@
1
+ @test_unit
2
+ Feature:
3
+
4
+ Using the setting `tracked_files` should add files that were not
5
+ required to the report.
6
+
7
+ Scenario:
8
+ Given SimpleCov for Test/Unit is configured with:
9
+ """
10
+ require 'simplecov'
11
+ SimpleCov.start do
12
+ track_files "lib/**/*.rb"
13
+ end
14
+ """
15
+
16
+ When I open the coverage report generated with `bundle exec rake test`
17
+ Then I should see the groups:
18
+ | name | coverage | files |
19
+ | All Files | 76.81% | 7 |
20
+
21
+ And I should see the source files:
22
+ | name | coverage |
23
+ | lib/faked_project.rb | 100.0 % |
24
+ | lib/faked_project/untested_class.rb | 0.0 % |
25
+ | lib/faked_project/some_class.rb | 80.0 % |
26
+ | lib/faked_project/framework_specific.rb | 75.0 % |
27
+ | lib/faked_project/meta_magic.rb | 100.0 % |
28
+ | test/meta_magic_test.rb | 100.0 % |
29
+ | test/some_class_test.rb | 100.0 % |
@@ -8,6 +8,6 @@
8
8
  #
9
9
  Transform "bundle exec rspec spec" do |_|
10
10
  files = nil # Avoid shadowing
11
- in_current_dir { files = Dir["spec/**/*_spec.rb"] }
11
+ in_current_directory { files = Dir["spec/**/*_spec.rb"] }
12
12
  "bundle exec rspec #{files.sort.join(' ')}"
13
13
  end
@@ -8,7 +8,6 @@ Bundler.setup
8
8
  require "aruba/cucumber"
9
9
  require "aruba/jruby" if RUBY_ENGINE == "jruby"
10
10
  require "capybara/cucumber"
11
- require "minitest/autorun"
12
11
  require "phantomjs/poltergeist"
13
12
 
14
13
  # Fake rack app for capybara that just returns the latest coverage report from aruba temp project dir
@@ -24,6 +23,10 @@ Capybara.app = lambda { |env|
24
23
 
25
24
  Capybara.default_driver = Capybara.javascript_driver = :poltergeist
26
25
 
26
+ Capybara.configure do |config|
27
+ config.ignore_hidden_elements = false
28
+ end
29
+
27
30
  Before do
28
31
  # JRuby takes it's time... See https://github.com/cucumber/aruba/issues/134
29
32
  @aruba_timeout_seconds = RUBY_ENGINE == "jruby" ? 60 : 20
@@ -31,9 +34,9 @@ Before do
31
34
  this_dir = File.dirname(__FILE__)
32
35
 
33
36
  # Clean up and create blank state for fake project
34
- in_current_dir do
37
+ in_current_directory do
35
38
  FileUtils.rm_rf "project"
36
- FileUtils.cp_r File.join(this_dir, "../../test/faked_project/"), "project"
39
+ FileUtils.cp_r File.join(this_dir, "../../spec/faked_project/"), "project"
37
40
  end
38
41
 
39
42
  step 'I cd to "project"'
@@ -48,12 +48,29 @@ module SimpleCov
48
48
  end
49
49
  end
50
50
 
51
+ #
52
+ # Finds files that were to be tracked but were not loaded and initializes
53
+ # their coverage to zero.
54
+ #
55
+ def add_not_loaded_files(result)
56
+ if @track_files_glob
57
+ result = result.dup
58
+ Dir[@track_files_glob].each do |file|
59
+ absolute = File.expand_path(file)
60
+
61
+ result[absolute] ||= [0] * File.foreach(absolute).count
62
+ end
63
+ end
64
+
65
+ result
66
+ end
67
+
51
68
  #
52
69
  # Returns the result for the current coverage run, merging it across test suites
53
70
  # from cache using SimpleCov::ResultMerger if use_merging is activated (default)
54
71
  #
55
72
  def result
56
- @result ||= SimpleCov::Result.new(Coverage.result) if running
73
+ @result ||= SimpleCov::Result.new(add_not_loaded_files(Coverage.result)) if running
57
74
  # If we're using merging of results, store the current result
58
75
  # first, then merge the results and return those
59
76
  if use_merging
@@ -109,7 +126,7 @@ module SimpleCov
109
126
  end
110
127
 
111
128
  def load_adapter(name)
112
- warn "method load_adapter is deprecated. use load_profile instead"
129
+ warn "#{Kernel.caller.first}: [DEPRECATION] #load_adapter is deprecated. Use #load_profile instead."
113
130
  load_profile(name)
114
131
  end
115
132
 
@@ -7,7 +7,7 @@ require "simplecov/formatter/multi_formatter"
7
7
  # SimpleCov documentation for further info.
8
8
  #
9
9
  module SimpleCov
10
- module Configuration
10
+ module Configuration # rubocop:disable ModuleLength
11
11
  attr_writer :filters, :groups, :formatter
12
12
 
13
13
  #
@@ -42,6 +42,15 @@ module SimpleCov
42
42
  coverage_path
43
43
  end
44
44
 
45
+ #
46
+ # Coverage results will always include files matched by this glob, whether
47
+ # or not they were explicitly required. Without this, un-required files
48
+ # will not be present in the final report.
49
+ #
50
+ def track_files(glob)
51
+ @track_files_glob = glob
52
+ end
53
+
45
54
  #
46
55
  # Returns the list of configured filters. Add filters using SimpleCov.add_filter.
47
56
  #
@@ -80,7 +89,7 @@ module SimpleCov
80
89
  # Sets the configured formatters.
81
90
  #
82
91
  def formatters=(formatters)
83
- @formatter = SimpleCov::Formatter::MultiFormatter[*formatters]
92
+ @formatter = SimpleCov::Formatter::MultiFormatter.new(formatters)
84
93
  end
85
94
 
86
95
  #
@@ -122,7 +131,7 @@ module SimpleCov
122
131
  end
123
132
 
124
133
  def adapters
125
- warn "method adapters is deprecated. use profiles instead"
134
+ warn "#{Kernel.caller.first}: [DEPRECATION] #adapters is deprecated. Use #profiles instead."
126
135
  profiles
127
136
  end
128
137
 
@@ -166,7 +175,7 @@ module SimpleCov
166
175
  def project_name(new_name = nil)
167
176
  return @project_name if defined?(@project_name) && @project_name && new_name.nil?
168
177
  @project_name = new_name if new_name.is_a?(String)
169
- @project_name ||= File.basename(root.split("/").last).capitalize.gsub("_", " ")
178
+ @project_name ||= File.basename(root.split("/").last).capitalize.tr("_", " ")
170
179
  end
171
180
 
172
181
  #
@@ -215,6 +224,17 @@ module SimpleCov
215
224
  @maximum_coverage_drop ||= (coverage_drop || 100).to_f.round(2)
216
225
  end
217
226
 
227
+ #
228
+ # Defines the minimum coverage per file required for the testsuite to pass.
229
+ # SimpleCov will return non-zero if the current coverage of the least covered file
230
+ # is below this threshold.
231
+ #
232
+ # Default is 0% (disabled)
233
+ #
234
+ def minimum_coverage_by_file(coverage = nil)
235
+ @minimum_coverage_by_file ||= (coverage || 0).to_f.round(2)
236
+ end
237
+
218
238
  #
219
239
  # Refuses any coverage drop. That is, coverage is only allowed to increase.
220
240
  # SimpleCov will return non-zero if the coverage decreases.
@@ -1,10 +1,12 @@
1
1
  # Load default formatter gem
2
2
  require "simplecov-html"
3
+ require "pathname"
3
4
 
4
5
  SimpleCov.profiles.define "root_filter" do
5
6
  # Exclude all files outside of simplecov root
7
+ root_filter = /\A#{Regexp.escape(SimpleCov.root)}/io
6
8
  add_filter do |src|
7
- !(src.filename =~ /^#{Regexp.escape(SimpleCov.root)}/i)
9
+ !(src.filename =~ root_filter)
8
10
  end
9
11
  end
10
12
 
@@ -30,6 +32,8 @@ SimpleCov.profiles.define "rails" do
30
32
  add_group "Mailers", "app/mailers"
31
33
  add_group "Helpers", "app/helpers"
32
34
  add_group "Libraries", "lib"
35
+
36
+ track_files "{app,lib}/**/*.rb"
33
37
  end
34
38
 
35
39
  # Default configuration
@@ -47,11 +51,11 @@ at_exit do
47
51
  # If we are in a different process than called start, don't interfere.
48
52
  next if SimpleCov.pid != Process.pid
49
53
 
50
- if $ERROR_INFO # was an exception thrown?
54
+ if $! # was an exception thrown?
51
55
  # if it was a SystemExit, use the accompanying status
52
56
  # otherwise set a non-zero status representing termination by some other exception
53
57
  # (see github issue 41)
54
- @exit_status = $ERROR_INFO.is_a?(SystemExit) ? $ERROR_INFO.status : SimpleCov::ExitCodes::EXCEPTION
58
+ @exit_status = $!.is_a?(SystemExit) ? $!.status : SimpleCov::ExitCodes::EXCEPTION
55
59
  else
56
60
  # Store the exit status of the test run since it goes away after calling the at_exit proc...
57
61
  @exit_status = SimpleCov::ExitCodes::SUCCESS
@@ -61,11 +65,15 @@ at_exit do
61
65
 
62
66
  if SimpleCov.result? # Result has been computed
63
67
  covered_percent = SimpleCov.result.covered_percent.round(2)
68
+ covered_percentages = SimpleCov.result.covered_percentages.map { |p| p.round(2) }
64
69
 
65
70
  if @exit_status == SimpleCov::ExitCodes::SUCCESS # No other errors
66
71
  if covered_percent < SimpleCov.minimum_coverage # rubocop:disable Metrics/BlockNesting
67
72
  $stderr.printf("Coverage (%.2f%%) is below the expected minimum coverage (%.2f%%).\n", covered_percent, SimpleCov.minimum_coverage)
68
73
  @exit_status = SimpleCov::ExitCodes::MINIMUM_COVERAGE
74
+ elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file } # rubocop:disable Metrics/BlockNesting
75
+ $stderr.printf("File (%s) is only (%.2f%%) covered. This is below the expected minimum coverage per file of (%.2f%%).\n", SimpleCov.result.least_covered_file, covered_percentages.min, SimpleCov.minimum_coverage_by_file)
76
+ @exit_status = SimpleCov::ExitCodes::MINIMUM_COVERAGE
69
77
  elsif (last_run = SimpleCov::LastRun.read) # rubocop:disable Metrics/BlockNesting
70
78
  diff = last_run["result"]["covered_percent"] - covered_percent
71
79
  if diff > SimpleCov.maximum_coverage_drop # rubocop:disable Metrics/BlockNesting
@@ -92,5 +100,20 @@ if home_dir
92
100
  end
93
101
 
94
102
  # Autoload config from .simplecov if present
95
- config_path = File.join(SimpleCov.root, ".simplecov")
96
- load config_path if File.exist?(config_path)
103
+ # Recurse upwards until we find .simplecov or reach the root directory
104
+
105
+ config_path = Pathname.new(SimpleCov.root)
106
+ loop do
107
+ filename = config_path.join(".simplecov")
108
+ if filename.exist?
109
+ begin
110
+ load filename
111
+ rescue LoadError, StandardError
112
+ $stderr.puts "Warning: Error occurred while trying to load #{filename}. " \
113
+ "Error message: #{$!.message}"
114
+ end
115
+ break
116
+ end
117
+ config_path, = config_path.split
118
+ break if config_path.root?
119
+ end