simplecov 0.9.1 → 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 (79) hide show
  1. checksums.yaml +7 -7
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +69 -0
  4. data/.travis.yml +12 -0
  5. data/CHANGELOG.md +59 -21
  6. data/Gemfile +22 -15
  7. data/MIT-LICENSE +1 -1
  8. data/README.md +198 -176
  9. data/Rakefile +17 -8
  10. data/doc/alternate-formatters.md +36 -0
  11. data/doc/commercial-services.md +20 -0
  12. data/doc/editor-integration.md +13 -0
  13. data/features/rspec_basic.feature +3 -2
  14. data/features/rspec_groups_and_filters_complex.feature +2 -0
  15. data/features/rspec_groups_using_filter_class.feature +3 -2
  16. data/features/step_definitions/html_steps.rb +6 -7
  17. data/features/step_definitions/simplecov_steps.rb +18 -16
  18. data/features/step_definitions/transformers.rb +2 -2
  19. data/features/step_definitions/web_steps.rb +4 -4
  20. data/features/support/env.rb +18 -15
  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/simple_formatter.rb +1 -1
  28. data/lib/simplecov/formatter.rb +2 -2
  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/lib/simplecov.rb +35 -24
  41. data/simplecov.gemspec +15 -12
  42. data/test/faked_project/Gemfile +5 -5
  43. data/test/faked_project/Rakefile +4 -4
  44. data/test/faked_project/features/step_definitions/my_steps.rb +3 -4
  45. data/test/faked_project/features/support/env.rb +5 -5
  46. data/test/faked_project/lib/faked_project/some_class.rb +3 -4
  47. data/test/faked_project/lib/faked_project.rb +1 -1
  48. data/test/faked_project/spec/faked_spec.rb +2 -2
  49. data/test/faked_project/spec/forking_spec.rb +7 -0
  50. data/test/faked_project/spec/meta_magic_spec.rb +1 -1
  51. data/test/faked_project/spec/some_class_spec.rb +3 -3
  52. data/test/faked_project/spec/spec_helper.rb +4 -8
  53. data/test/faked_project/test/faked_test.rb +2 -2
  54. data/test/faked_project/test/meta_magic_test.rb +1 -1
  55. data/test/faked_project/test/some_class_test.rb +3 -3
  56. data/test/faked_project/test/test_helper.rb +5 -9
  57. data/test/fixtures/app/controllers/sample_controller.rb +1 -1
  58. data/test/fixtures/app/models/user.rb +1 -1
  59. data/test/fixtures/deleted_source_sample.rb +3 -3
  60. data/test/fixtures/frameworks/rspec_bad.rb +4 -4
  61. data/test/fixtures/frameworks/rspec_good.rb +4 -4
  62. data/test/fixtures/frameworks/testunit_bad.rb +3 -3
  63. data/test/fixtures/frameworks/testunit_good.rb +3 -3
  64. data/test/fixtures/resultset2.rb +0 -1
  65. data/test/fixtures/sample.rb +1 -1
  66. data/test/fixtures/utf-8.rb +1 -1
  67. data/test/helper.rb +9 -11
  68. data/test/test_1_8_fallbacks.rb +7 -7
  69. data/test/test_command_guesser.rb +8 -8
  70. data/test/test_deleted_source.rb +3 -3
  71. data/test/test_file_list.rb +9 -7
  72. data/test/test_filters.rb +30 -14
  73. data/test/test_merge_helpers.rb +31 -24
  74. data/test/test_result.rb +32 -23
  75. data/test/test_return_codes.rb +10 -6
  76. data/test/test_source_file.rb +5 -38
  77. data/test/test_source_file_line.rb +17 -17
  78. metadata +146 -64
  79. data/lib/simplecov/json.rb +0 -27
@@ -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
@@ -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"
@@ -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"
@@ -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
@@ -1,11 +1,11 @@
1
- require 'rake/testtask'
1
+ require "rake/testtask"
2
2
  Rake::TestTask.new do |t|
3
- t.name = 'simplecov'
3
+ t.name = "simplecov"
4
4
  t.loader = :direct # uses require() which skips PWD in Ruby 1.9
5
- t.libs.push 'test', 'spec', Dir.pwd
6
- t.test_files = FileList['{test,spec}/**/*_{test,spec}.rb']
7
- t.ruby_opts.push '-r', 'simplecov', '-e', 'SimpleCov.start(:rails)'.inspect
5
+ t.libs.push "test", "spec", Dir.pwd
6
+ t.test_files = FileList["{test,spec}/**/*_{test,spec}.rb"]
7
+ t.ruby_opts.push "-r", "simplecov", "-e", "SimpleCov.start(:rails)".inspect
8
8
  end
9
9
 
10
- require 'rake/clean'
11
- CLOBBER.include 'coverage'
10
+ require "rake/clean"
11
+ CLOBBER.include "coverage"
@@ -1,5 +1,5 @@
1
- require 'digest/sha1'
2
- require 'forwardable'
1
+ require "digest/sha1"
2
+ require "forwardable"
3
3
 
4
4
  module SimpleCov
5
5
  #
@@ -57,9 +57,9 @@ module SimpleCov
57
57
  @command_name ||= SimpleCov.command_name
58
58
  end
59
59
 
60
- # Returns a hash representation of this Result that can be used for marshalling it into YAML
60
+ # Returns a hash representation of this Result that can be used for marshalling it into JSON
61
61
  def to_hash
62
- {command_name => {"coverage" => original_result.reject {|filename, result| !filenames.include?(filename) }, "timestamp" => created_at.to_i}}
62
+ {command_name => {"coverage" => original_result.reject { |filename, _| !filenames.include?(filename) }, "timestamp" => created_at.to_i}}
63
63
  end
64
64
 
65
65
  # Loads a SimpleCov::Result#to_hash dump
@@ -71,7 +71,7 @@ module SimpleCov
71
71
  result
72
72
  end
73
73
 
74
- private
74
+ private
75
75
 
76
76
  # Applies all configured SimpleCov filters on this result's source files
77
77
  def filter!
@@ -1,85 +1,88 @@
1
+ require "json"
2
+
1
3
  #
2
4
  # Singleton that is responsible for caching, loading and merging
3
5
  # SimpleCov::Results into a single result for coverage analysis based
4
6
  # upon multiple test suites.
5
7
  #
6
- module SimpleCov::ResultMerger
7
- class << self
8
- # The path to the .resultset.json cache file
9
- def resultset_path
10
- File.join(SimpleCov.coverage_path, '.resultset.json')
11
- end
8
+ module SimpleCov
9
+ module ResultMerger
10
+ class << self
11
+ # The path to the .resultset.json cache file
12
+ def resultset_path
13
+ File.join(SimpleCov.coverage_path, ".resultset.json")
14
+ end
12
15
 
13
- def resultset_writelock
14
- File.join(SimpleCov.coverage_path, '.resultset.json.lock')
15
- end
16
+ def resultset_writelock
17
+ File.join(SimpleCov.coverage_path, ".resultset.json.lock")
18
+ end
16
19
 
17
- # Loads the cached resultset from YAML and returns it as a Hash
18
- def resultset
19
- if stored_data
20
- begin
21
- SimpleCov::JSON.parse(stored_data)
22
- rescue
20
+ # Loads the cached resultset from JSON and returns it as a Hash
21
+ def resultset
22
+ if stored_data
23
+ begin
24
+ JSON.parse(stored_data)
25
+ rescue
26
+ {}
27
+ end
28
+ else
23
29
  {}
24
30
  end
25
- else
26
- {}
27
31
  end
28
- end
29
32
 
30
- # Returns the contents of the resultset cache as a string or if the file is missing or empty nil
31
- def stored_data
32
- if File.exist?(resultset_path) and stored_data = File.read(resultset_path) and stored_data.length >= 2
33
- stored_data
34
- else
35
- nil
33
+ # Returns the contents of the resultset cache as a string or if the file is missing or empty nil
34
+ def stored_data
35
+ return unless File.exist?(resultset_path)
36
+ data = File.read(resultset_path)
37
+ return if data.nil? || data.length < 2
38
+ data
36
39
  end
37
- end
38
40
 
39
- # Gets the resultset hash and re-creates all included instances
40
- # of SimpleCov::Result from that.
41
- # All results that are above the SimpleCov.merge_timeout will be
42
- # dropped. Returns an array of SimpleCov::Result items.
43
- def results
44
- results = []
45
- resultset.each do |command_name, data|
46
- result = SimpleCov::Result.from_hash(command_name => data)
47
- # Only add result if the timeout is above the configured threshold
48
- if (Time.now - result.created_at) < SimpleCov.merge_timeout
49
- results << result
41
+ # Gets the resultset hash and re-creates all included instances
42
+ # of SimpleCov::Result from that.
43
+ # All results that are above the SimpleCov.merge_timeout will be
44
+ # dropped. Returns an array of SimpleCov::Result items.
45
+ def results
46
+ results = []
47
+ resultset.each do |command_name, data|
48
+ result = SimpleCov::Result.from_hash(command_name => data)
49
+ # Only add result if the timeout is above the configured threshold
50
+ if (Time.now - result.created_at) < SimpleCov.merge_timeout
51
+ results << result
52
+ end
50
53
  end
54
+ results
51
55
  end
52
- results
53
- end
54
56
 
55
- #
56
- # Gets all SimpleCov::Results from cache, merges them and produces a new
57
- # SimpleCov::Result with merged coverage data and the command_name
58
- # for the result consisting of a join on all source result's names
59
- #
60
- def merged_result
61
- merged = {}
62
- results.each do |result|
63
- merged = result.original_result.merge_resultset(merged)
57
+ #
58
+ # Gets all SimpleCov::Results from cache, merges them and produces a new
59
+ # SimpleCov::Result with merged coverage data and the command_name
60
+ # for the result consisting of a join on all source result's names
61
+ #
62
+ def merged_result
63
+ merged = {}
64
+ results.each do |result|
65
+ merged = result.original_result.merge_resultset(merged)
66
+ end
67
+ result = SimpleCov::Result.new(merged)
68
+ # Specify the command name
69
+ result.command_name = results.map(&:command_name).sort.join(", ")
70
+ result
64
71
  end
65
- result = SimpleCov::Result.new(merged)
66
- # Specify the command name
67
- result.command_name = results.map(&:command_name).sort.join(", ")
68
- result
69
- end
70
72
 
71
- # Saves the given SimpleCov::Result in the resultset cache
72
- def store_result(result)
73
- File.open(resultset_writelock, "w+") do |f|
74
- f.flock(File::LOCK_EX)
75
- new_set = resultset
76
- command_name, data = result.to_hash.first
77
- new_set[command_name] = data
78
- File.open(resultset_path, "w+") do |f_|
79
- f_.puts SimpleCov::JSON.dump(new_set)
73
+ # Saves the given SimpleCov::Result in the resultset cache
74
+ def store_result(result)
75
+ File.open(resultset_writelock, "w+") do |f|
76
+ f.flock(File::LOCK_EX)
77
+ new_set = resultset
78
+ command_name, data = result.to_hash.first
79
+ new_set[command_name] = data
80
+ File.open(resultset_path, "w+") do |f_|
81
+ f_.puts JSON.pretty_generate(new_set)
82
+ end
80
83
  end
84
+ true
81
85
  end
82
- true
83
86
  end
84
87
  end
85
88
  end