simplecov 0.9.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +7 -7
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +69 -0
  4. data/CHANGELOG.md +39 -22
  5. data/Gemfile +16 -15
  6. data/MIT-LICENSE +1 -1
  7. data/README.md +183 -178
  8. data/Rakefile +16 -7
  9. data/doc/alternate-formatters.md +36 -0
  10. data/doc/commercial-services.md +20 -0
  11. data/doc/editor-integration.md +13 -0
  12. data/features/rspec_basic.feature +3 -2
  13. data/features/rspec_groups_and_filters_complex.feature +2 -0
  14. data/features/rspec_groups_using_filter_class.feature +3 -2
  15. data/features/step_definitions/html_steps.rb +6 -7
  16. data/features/step_definitions/simplecov_steps.rb +18 -16
  17. data/features/step_definitions/transformers.rb +2 -2
  18. data/features/step_definitions/web_steps.rb +4 -4
  19. data/features/support/env.rb +17 -15
  20. data/lib/simplecov.rb +35 -24
  21. data/lib/simplecov/command_guesser.rb +33 -34
  22. data/lib/simplecov/configuration.rb +238 -234
  23. data/lib/simplecov/defaults.rb +37 -36
  24. data/lib/simplecov/exit_codes.rb +7 -5
  25. data/lib/simplecov/file_list.rb +38 -36
  26. data/lib/simplecov/filter.rb +12 -2
  27. data/lib/simplecov/formatter.rb +2 -2
  28. data/lib/simplecov/formatter/simple_formatter.rb +1 -1
  29. data/lib/simplecov/jruby_fix.rb +4 -4
  30. data/lib/simplecov/last_run.rb +15 -13
  31. data/lib/simplecov/merge_helpers.rb +26 -27
  32. data/lib/simplecov/no_defaults.rb +2 -2
  33. data/lib/simplecov/profiles.rb +21 -19
  34. data/lib/simplecov/railtie.rb +1 -1
  35. data/lib/simplecov/railties/tasks.rake +7 -7
  36. data/lib/simplecov/result.rb +5 -5
  37. data/lib/simplecov/result_merger.rb +65 -62
  38. data/lib/simplecov/source_file.rb +23 -24
  39. data/lib/simplecov/version.rb +20 -1
  40. data/simplecov.gemspec +14 -12
  41. data/test/faked_project/Gemfile +5 -5
  42. data/test/faked_project/Rakefile +4 -4
  43. data/test/faked_project/features/step_definitions/my_steps.rb +3 -4
  44. data/test/faked_project/features/support/env.rb +5 -5
  45. data/test/faked_project/lib/faked_project.rb +1 -1
  46. data/test/faked_project/lib/faked_project/some_class.rb +3 -4
  47. data/test/faked_project/spec/faked_spec.rb +2 -2
  48. data/test/faked_project/spec/forking_spec.rb +7 -0
  49. data/test/faked_project/spec/meta_magic_spec.rb +1 -1
  50. data/test/faked_project/spec/some_class_spec.rb +3 -3
  51. data/test/faked_project/spec/spec_helper.rb +4 -8
  52. data/test/faked_project/test/faked_test.rb +2 -2
  53. data/test/faked_project/test/meta_magic_test.rb +1 -1
  54. data/test/faked_project/test/some_class_test.rb +3 -3
  55. data/test/faked_project/test/test_helper.rb +5 -9
  56. data/test/fixtures/app/controllers/sample_controller.rb +1 -1
  57. data/test/fixtures/app/models/user.rb +1 -1
  58. data/test/fixtures/deleted_source_sample.rb +3 -3
  59. data/test/fixtures/frameworks/rspec_bad.rb +4 -4
  60. data/test/fixtures/frameworks/rspec_good.rb +4 -4
  61. data/test/fixtures/frameworks/testunit_bad.rb +3 -3
  62. data/test/fixtures/frameworks/testunit_good.rb +3 -3
  63. data/test/fixtures/resultset2.rb +0 -1
  64. data/test/fixtures/sample.rb +1 -1
  65. data/test/fixtures/utf-8.rb +1 -1
  66. data/test/helper.rb +8 -8
  67. data/test/test_1_8_fallbacks.rb +6 -6
  68. data/test/test_command_guesser.rb +7 -7
  69. data/test/test_deleted_source.rb +2 -2
  70. data/test/test_file_list.rb +8 -6
  71. data/test/test_filters.rb +29 -13
  72. data/test/test_merge_helpers.rb +26 -23
  73. data/test/test_result.rb +32 -23
  74. data/test/test_return_codes.rb +3 -3
  75. data/test/test_source_file.rb +4 -4
  76. data/test/test_source_file_line.rb +13 -13
  77. metadata +145 -63
  78. data/lib/simplecov/json.rb +0 -27
@@ -1,51 +1,57 @@
1
1
  # Load default formatter gem
2
- require 'simplecov-html'
2
+ require "simplecov-html"
3
3
 
4
- SimpleCov.profiles.define 'root_filter' do
4
+ SimpleCov.profiles.define "root_filter" do
5
5
  # Exclude all files outside of simplecov root
6
6
  add_filter do |src|
7
7
  !(src.filename =~ /^#{Regexp.escape(SimpleCov.root)}/i)
8
8
  end
9
9
  end
10
10
 
11
- SimpleCov.profiles.define 'test_frameworks' do
12
- add_filter '/test/'
13
- add_filter '/features/'
14
- add_filter '/spec/'
15
- add_filter '/autotest/'
11
+ SimpleCov.profiles.define "test_frameworks" do
12
+ add_filter "/test/"
13
+ add_filter "/features/"
14
+ add_filter "/spec/"
15
+ add_filter "/autotest/"
16
16
  end
17
17
 
18
- SimpleCov.profiles.define 'rails' do
19
- load_profile 'test_frameworks'
18
+ SimpleCov.profiles.define "bundler_filter" do
19
+ add_filter "/vendor/bundle/"
20
+ end
21
+
22
+ SimpleCov.profiles.define "rails" do
23
+ load_profile "test_frameworks"
20
24
 
21
- add_filter '/config/'
22
- add_filter '/db/'
23
- add_filter '/vendor/bundle/'
25
+ add_filter "/config/"
26
+ add_filter "/db/"
24
27
 
25
- add_group 'Controllers', 'app/controllers'
26
- add_group 'Models', 'app/models'
27
- add_group 'Mailers', 'app/mailers'
28
- add_group 'Helpers', 'app/helpers'
29
- add_group 'Libraries', 'lib'
28
+ add_group "Controllers", "app/controllers"
29
+ add_group "Models", "app/models"
30
+ add_group "Mailers", "app/mailers"
31
+ add_group "Helpers", "app/helpers"
32
+ add_group "Libraries", "lib"
30
33
  end
31
34
 
32
35
  # Default configuration
33
36
  SimpleCov.configure do
34
37
  formatter SimpleCov::Formatter::HTMLFormatter
38
+ load_profile "bundler_filter"
35
39
  # Exclude files outside of SimpleCov.root
36
- load_profile 'root_filter'
40
+ load_profile "root_filter"
37
41
  end
38
42
 
39
43
  # Gotta stash this a-s-a-p, see the CommandGuesser class and i.e. #110 for further info
40
- SimpleCov::CommandGuesser.original_run_command = "#{$0} #{ARGV.join(" ")}"
44
+ SimpleCov::CommandGuesser.original_run_command = "#{$PROGRAM_NAME} #{ARGV.join(' ')}"
41
45
 
42
46
  at_exit do
47
+ # If we are in a different process than called start, don't interfere.
48
+ next if SimpleCov.pid != Process.pid
43
49
 
44
- if $! # was an exception thrown?
50
+ if $ERROR_INFO # was an exception thrown?
45
51
  # if it was a SystemExit, use the accompanying status
46
52
  # otherwise set a non-zero status representing termination by some other exception
47
53
  # (see github issue 41)
48
- @exit_status = $!.is_a?(SystemExit) ? $!.status : SimpleCov::ExitCodes::EXCEPTION
54
+ @exit_status = $ERROR_INFO.is_a?(SystemExit) ? $ERROR_INFO.status : SimpleCov::ExitCodes::EXCEPTION
49
55
  else
50
56
  # Store the exit status of the test run since it goes away after calling the at_exit proc...
51
57
  @exit_status = SimpleCov::ExitCodes::SUCCESS
@@ -57,18 +63,13 @@ at_exit do
57
63
  covered_percent = SimpleCov.result.covered_percent.round(2)
58
64
 
59
65
  if @exit_status == SimpleCov::ExitCodes::SUCCESS # No other errors
60
- if covered_percent < SimpleCov.minimum_coverage
61
- $stderr.puts "Coverage (%.2f%%) is below the expected minimum coverage (%.2f%%)." % \
62
- [covered_percent, SimpleCov.minimum_coverage]
63
-
66
+ if covered_percent < SimpleCov.minimum_coverage # rubocop:disable Metrics/BlockNesting
67
+ $stderr.printf("Coverage (%.2f%%) is below the expected minimum coverage (%.2f%%).\n", covered_percent, SimpleCov.minimum_coverage)
64
68
  @exit_status = SimpleCov::ExitCodes::MINIMUM_COVERAGE
65
-
66
- elsif (last_run = SimpleCov::LastRun.read)
67
- diff = last_run['result']['covered_percent'] - covered_percent
68
- if diff > SimpleCov.maximum_coverage_drop
69
- $stderr.puts "Coverage has dropped by %.2f%% since the last time (maximum allowed: %.2f%%)." % \
70
- [diff, SimpleCov.maximum_coverage_drop]
71
-
69
+ elsif (last_run = SimpleCov::LastRun.read) # rubocop:disable Metrics/BlockNesting
70
+ diff = last_run["result"]["covered_percent"] - covered_percent
71
+ if diff > SimpleCov.maximum_coverage_drop # rubocop:disable Metrics/BlockNesting
72
+ $stderr.printf("Coverage has dropped by %.2f%% since the last time (maximum allowed: %.2f%%).\n", diff, SimpleCov.maximum_coverage_drop)
72
73
  @exit_status = SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
73
74
  end
74
75
  end
@@ -83,13 +84,13 @@ at_exit do
83
84
  end
84
85
 
85
86
  # Autoload config from ~/.simplecov if present
86
- require 'etc'
87
- home_dir = File.expand_path('~') || Etc.getpwuid.dir || (user = ENV["USER"] && File.expand_path("~#{user}"))
87
+ require "etc"
88
+ home_dir = File.expand_path("~") || Etc.getpwuid.dir || (ENV["USER"] && File.expand_path("~#{ENV['USER']}"))
88
89
  if home_dir
89
- global_config_path = File.join(home_dir, '.simplecov')
90
+ global_config_path = File.join(home_dir, ".simplecov")
90
91
  load global_config_path if File.exist?(global_config_path)
91
92
  end
92
93
 
93
94
  # Autoload config from .simplecov if present
94
- config_path = File.join(SimpleCov.root, '.simplecov')
95
+ config_path = File.join(SimpleCov.root, ".simplecov")
95
96
  load config_path if File.exist?(config_path)
@@ -1,6 +1,8 @@
1
- module SimpleCov::ExitCodes
2
- SUCCESS = 0
3
- EXCEPTION = 1
4
- MINIMUM_COVERAGE = 2
5
- MAXIMUM_COVERAGE_DROP = 3
1
+ module SimpleCov
2
+ module ExitCodes
3
+ SUCCESS = 0
4
+ EXCEPTION = 1
5
+ MINIMUM_COVERAGE = 2
6
+ MAXIMUM_COVERAGE_DROP = 3
7
+ end
6
8
  end
@@ -1,46 +1,48 @@
1
1
  # An array of SimpleCov SourceFile instances with additional collection helper
2
2
  # methods for calculating coverage across them etc.
3
- class SimpleCov::FileList < Array
4
- # Returns the count of lines that have coverage
5
- def covered_lines
6
- return 0.0 if empty?
7
- map {|f| f.covered_lines.count }.inject(&:+)
8
- end
3
+ module SimpleCov
4
+ class FileList < Array
5
+ # Returns the count of lines that have coverage
6
+ def covered_lines
7
+ return 0.0 if empty?
8
+ map { |f| f.covered_lines.count }.inject(&:+)
9
+ end
9
10
 
10
- # Returns the count of lines that have been missed
11
- def missed_lines
12
- return 0.0 if empty?
13
- map {|f| f.missed_lines.count }.inject(&:+)
14
- end
11
+ # Returns the count of lines that have been missed
12
+ def missed_lines
13
+ return 0.0 if empty?
14
+ map { |f| f.missed_lines.count }.inject(&:+)
15
+ end
15
16
 
16
- # Returns the count of lines that are not relevant for coverage
17
- def never_lines
18
- return 0.0 if empty?
19
- map {|f| f.never_lines.count }.inject(&:+)
20
- end
17
+ # Returns the count of lines that are not relevant for coverage
18
+ def never_lines
19
+ return 0.0 if empty?
20
+ map { |f| f.never_lines.count }.inject(&:+)
21
+ end
21
22
 
22
- # Returns the count of skipped lines
23
- def skipped_lines
24
- return 0.0 if empty?
25
- map {|f| f.skipped_lines.count }.inject(&:+)
26
- end
23
+ # Returns the count of skipped lines
24
+ def skipped_lines
25
+ return 0.0 if empty?
26
+ map { |f| f.skipped_lines.count }.inject(&:+)
27
+ end
27
28
 
28
- # Returns the overall amount of relevant lines of code across all files in this list
29
- def lines_of_code
30
- covered_lines + missed_lines
31
- end
29
+ # Returns the overall amount of relevant lines of code across all files in this list
30
+ def lines_of_code
31
+ covered_lines + missed_lines
32
+ end
32
33
 
33
- # Computes the coverage based upon lines covered and lines missed
34
- # @return [Float]
35
- def covered_percent
36
- return 100.0 if empty? or lines_of_code == 0
37
- Float(covered_lines * 100.0 / lines_of_code)
38
- end
34
+ # Computes the coverage based upon lines covered and lines missed
35
+ # @return [Float]
36
+ def covered_percent
37
+ return 100.0 if empty? || lines_of_code.zero?
38
+ Float(covered_lines * 100.0 / lines_of_code)
39
+ end
39
40
 
40
- # Computes the strength (hits / line) based upon lines covered and lines missed
41
- # @return [Float]
42
- def covered_strength
43
- return 0.0 if empty? or lines_of_code == 0
44
- Float(map {|f| f.covered_strength * f.lines_of_code }.inject(&:+) / lines_of_code)
41
+ # Computes the strength (hits / line) based upon lines covered and lines missed
42
+ # @return [Float]
43
+ def covered_strength
44
+ return 0.0 if empty? || lines_of_code.zero?
45
+ Float(map { |f| f.covered_strength * f.lines_of_code }.inject(&:+) / lines_of_code)
46
+ end
45
47
  end
46
48
  end
@@ -16,8 +16,8 @@ module SimpleCov
16
16
  @filter_argument = filter_argument
17
17
  end
18
18
 
19
- def matches?(source_file)
20
- raise "The base filter class is not intended for direct use"
19
+ def matches?(_)
20
+ fail "The base filter class is not intended for direct use"
21
21
  end
22
22
 
23
23
  def passes?(source_file)
@@ -41,4 +41,14 @@ module SimpleCov
41
41
  filter_argument.call(source_file)
42
42
  end
43
43
  end
44
+
45
+ class ArrayFilter < SimpleCov::Filter
46
+ # Returns true if any of the file paths passed in the given array matches the string
47
+ # configured when initializing this Filter with StringFilter.new(['some/path', 'other/path'])
48
+ def matches?(source_files_list)
49
+ filter_argument.any? do |arg|
50
+ source_files_list.filename =~ /#{arg}/
51
+ end
52
+ end
53
+ end
44
54
  end
@@ -4,5 +4,5 @@ module SimpleCov
4
4
  end
5
5
  end
6
6
 
7
- require 'simplecov/formatter/simple_formatter'
8
- require 'simplecov/formatter/multi_formatter'
7
+ require "simplecov/formatter/simple_formatter"
8
+ require "simplecov/formatter/multi_formatter"
@@ -9,7 +9,7 @@ module SimpleCov
9
9
  output = ""
10
10
  result.groups.each do |name, files|
11
11
  output << "Group: #{name}\n"
12
- output << "="*40
12
+ output << "=" * 40
13
13
  output << "\n"
14
14
  files.each do |file|
15
15
  output << "#{file.filename} (coverage: #{file.covered_percent.round(2)}%)\n"
@@ -1,6 +1,6 @@
1
1
  if defined?(JRUBY_VERSION) && JRUBY_VERSION.to_f < 1.7
2
- require 'jruby'
3
- java_import 'org.jruby.ast.NodeType'
2
+ require "jruby"
3
+ java_import "org.jruby.ast.NodeType"
4
4
 
5
5
  # Coverage for JRuby < 1.7.0 does not work correctly
6
6
  #
@@ -11,9 +11,9 @@ if defined?(JRUBY_VERSION) && JRUBY_VERSION.to_f < 1.7
11
11
  # This monkey patches Coverage to address those issues
12
12
  module Coverage
13
13
  class << self
14
- alias __broken_result__ result
14
+ alias_method :__broken_result__, :result
15
15
 
16
- def result
16
+ def result # rubocop:disable Metrics/MethodLength
17
17
  fixed = {}
18
18
  __broken_result__.each do |path, executed_lines|
19
19
  next unless File.file? path
@@ -1,20 +1,22 @@
1
- module SimpleCov::LastRun
2
- class << self
3
- def last_run_path
4
- File.join(SimpleCov.coverage_path, '.last_run.json')
5
- end
1
+ require "json"
6
2
 
7
- def read
8
- return nil unless File.exist?(last_run_path)
3
+ module SimpleCov
4
+ module LastRun
5
+ class << self
6
+ def last_run_path
7
+ File.join(SimpleCov.coverage_path, ".last_run.json")
8
+ end
9
9
 
10
- SimpleCov::JSON.parse(File.read(last_run_path))
11
- end
10
+ def read
11
+ return nil unless File.exist?(last_run_path)
12
+ JSON.parse(File.read(last_run_path))
13
+ end
12
14
 
13
- def write(json)
14
- File.open(last_run_path, "w+") do |f|
15
- f.puts SimpleCov::JSON.dump(json)
15
+ def write(json)
16
+ File.open(last_run_path, "w+") do |f|
17
+ f.puts JSON.pretty_generate(json)
18
+ end
16
19
  end
17
20
  end
18
21
  end
19
22
  end
20
-
@@ -1,37 +1,36 @@
1
- module SimpleCov::ArrayMergeHelper
2
- # Merges an array of coverage results with self
3
- def merge_resultset(array)
4
- new_array = []
5
-
6
- self.each_with_index do |element, i|
7
- new_array[i] = element
8
- end
9
-
10
- array.each_with_index do |element, i|
11
- if element.nil? and new_array[i].nil?
12
- new_array[i] = nil
13
- else
14
- local_value = element || 0
15
- other_value = new_array[i] || 0
16
- new_array[i] = local_value + other_value
1
+ module SimpleCov
2
+ module ArrayMergeHelper
3
+ # Merges an array of coverage results with self
4
+ def merge_resultset(array)
5
+ new_array = dup
6
+ array.each_with_index do |element, i|
7
+ if element.nil? && new_array[i].nil?
8
+ new_array[i] = nil
9
+ else
10
+ local_value = element || 0
11
+ other_value = new_array[i] || 0
12
+ new_array[i] = local_value + other_value
13
+ end
17
14
  end
15
+ new_array
18
16
  end
19
- new_array
20
17
  end
21
18
  end
22
19
 
23
- module SimpleCov::HashMergeHelper
24
- # Merges the given Coverage.result hash with self
25
- def merge_resultset(hash)
26
- new_resultset = {}
27
- (self.keys + hash.keys).each do |filename|
28
- new_resultset[filename] = []
29
- end
20
+ module SimpleCov
21
+ module HashMergeHelper
22
+ # Merges the given Coverage.result hash with self
23
+ def merge_resultset(hash)
24
+ new_resultset = {}
25
+ (keys + hash.keys).each do |filename|
26
+ new_resultset[filename] = []
27
+ end
30
28
 
31
- new_resultset.each do |filename, data|
32
- new_resultset[filename] = (self[filename] || []).merge_resultset(hash[filename] || [])
29
+ new_resultset.each_key do |filename|
30
+ new_resultset[filename] = (self[filename] || []).merge_resultset(hash[filename] || [])
31
+ end
32
+ new_resultset
33
33
  end
34
- new_resultset
35
34
  end
36
35
  end
37
36
 
@@ -1,2 +1,2 @@
1
- ENV['SIMPLECOV_NO_DEFAULTS'] = 'yes, no defaults'
2
- require 'simplecov'
1
+ ENV["SIMPLECOV_NO_DEFAULTS"] = "yes, no defaults"
2
+ require "simplecov"
@@ -5,25 +5,27 @@
5
5
  # # SimpleCov configuration here, same as in SimpleCov.configure
6
6
  # end
7
7
  #
8
- class SimpleCov::Profiles < Hash
9
- #
10
- # Define a SimpleCov profile:
11
- # SimpleCov.profiles.define 'rails' do
12
- # # Same as SimpleCov.configure do .. here
13
- # end
14
- #
15
- def define(name, &blk)
16
- name = name.to_sym
17
- raise "SimpleCov Profile '#{name}' is already defined" unless self[name].nil?
18
- self[name] = blk
19
- end
8
+ module SimpleCov
9
+ class Profiles < Hash
10
+ #
11
+ # Define a SimpleCov profile:
12
+ # SimpleCov.profiles.define 'rails' do
13
+ # # Same as SimpleCov.configure do .. here
14
+ # end
15
+ #
16
+ def define(name, &blk)
17
+ name = name.to_sym
18
+ fail "SimpleCov Profile '#{name}' is already defined" unless self[name].nil?
19
+ self[name] = blk
20
+ end
20
21
 
21
- #
22
- # Applies the profile of given name on SimpleCov.configure
23
- #
24
- def load(name)
25
- name = name.to_sym
26
- raise "Could not find SimpleCov Profile called '#{name}'" unless has_key?(name)
27
- SimpleCov.configure(&self[name])
22
+ #
23
+ # Applies the profile of given name on SimpleCov.configure
24
+ #
25
+ def load(name)
26
+ name = name.to_sym
27
+ fail "Could not find SimpleCov Profile called '#{name}'" unless key?(name)
28
+ SimpleCov.configure(&self[name])
29
+ end
28
30
  end
29
31
  end
@@ -1,7 +1,7 @@
1
1
  module SimpleCov
2
2
  class Railtie < ::Rails::Railtie
3
3
  rake_tasks do
4
- load 'simplecov/railties/tasks.rake'
4
+ load "simplecov/railties/tasks.rake"
5
5
  end
6
6
  end
7
7
  end