simplecov-patched 0.14.2

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 (126) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +31 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +88 -0
  5. data/.travis.yml +29 -0
  6. data/.yardopts +1 -0
  7. data/CHANGELOG.md +435 -0
  8. data/CONTRIBUTING.md +48 -0
  9. data/Gemfile +38 -0
  10. data/MIT-LICENSE +20 -0
  11. data/README.md +646 -0
  12. data/Rakefile +41 -0
  13. data/cucumber.yml +13 -0
  14. data/doc/alternate-formatters.md +36 -0
  15. data/doc/commercial-services.md +20 -0
  16. data/doc/editor-integration.md +13 -0
  17. data/features/config_autoload.feature +46 -0
  18. data/features/config_command_name.feature +45 -0
  19. data/features/config_coverage_dir.feature +33 -0
  20. data/features/config_deactivate_merging.feature +42 -0
  21. data/features/config_formatters.feature +77 -0
  22. data/features/config_merge_timeout.feature +39 -0
  23. data/features/config_nocov_token.feature +79 -0
  24. data/features/config_profiles.feature +44 -0
  25. data/features/config_project_name.feature +27 -0
  26. data/features/config_styles.feature +121 -0
  27. data/features/config_tracked_files.feature +29 -0
  28. data/features/cucumber_basic.feature +29 -0
  29. data/features/maximum_coverage_drop.feature +89 -0
  30. data/features/merging_test_unit_and_rspec.feature +44 -0
  31. data/features/minimum_coverage.feature +59 -0
  32. data/features/refuse_coverage_drop.feature +95 -0
  33. data/features/rspec_basic.feature +32 -0
  34. data/features/rspec_fails_on_initialization.feature +14 -0
  35. data/features/rspec_groups_and_filters_basic.feature +29 -0
  36. data/features/rspec_groups_and_filters_complex.feature +37 -0
  37. data/features/rspec_groups_using_filter_class.feature +41 -0
  38. data/features/rspec_without_simplecov.feature +20 -0
  39. data/features/skipping_code_blocks_manually.feature +70 -0
  40. data/features/step_definitions/html_steps.rb +44 -0
  41. data/features/step_definitions/simplecov_steps.rb +68 -0
  42. data/features/step_definitions/transformers.rb +13 -0
  43. data/features/step_definitions/web_steps.rb +64 -0
  44. data/features/support/env.rb +50 -0
  45. data/features/test_unit_basic.feature +34 -0
  46. data/features/test_unit_groups_and_filters_basic.feature +29 -0
  47. data/features/test_unit_groups_and_filters_complex.feature +35 -0
  48. data/features/test_unit_groups_using_filter_class.feature +40 -0
  49. data/features/test_unit_without_simplecov.feature +20 -0
  50. data/features/unicode_compatiblity.feature +67 -0
  51. data/lib/simplecov.rb +189 -0
  52. data/lib/simplecov/command_guesser.rb +59 -0
  53. data/lib/simplecov/configuration.rb +307 -0
  54. data/lib/simplecov/defaults.rb +121 -0
  55. data/lib/simplecov/exit_codes.rb +8 -0
  56. data/lib/simplecov/file_list.rb +59 -0
  57. data/lib/simplecov/filter.rb +54 -0
  58. data/lib/simplecov/formatter.rb +8 -0
  59. data/lib/simplecov/formatter/multi_formatter.rb +32 -0
  60. data/lib/simplecov/formatter/simple_formatter.rb +23 -0
  61. data/lib/simplecov/jruby_fix.rb +42 -0
  62. data/lib/simplecov/last_run.rb +24 -0
  63. data/lib/simplecov/load_global_config.rb +6 -0
  64. data/lib/simplecov/no_defaults.rb +2 -0
  65. data/lib/simplecov/profiles.rb +31 -0
  66. data/lib/simplecov/railtie.rb +7 -0
  67. data/lib/simplecov/railties/tasks.rake +11 -0
  68. data/lib/simplecov/raw_coverage.rb +39 -0
  69. data/lib/simplecov/result.rb +86 -0
  70. data/lib/simplecov/result_merger.rb +95 -0
  71. data/lib/simplecov/source_file.rb +196 -0
  72. data/lib/simplecov/version.rb +25 -0
  73. data/spec/1_8_fallbacks_spec.rb +31 -0
  74. data/spec/command_guesser_spec.rb +48 -0
  75. data/spec/config_loader_spec.rb +14 -0
  76. data/spec/configuration_spec.rb +35 -0
  77. data/spec/deleted_source_spec.rb +12 -0
  78. data/spec/faked_project/Gemfile +6 -0
  79. data/spec/faked_project/Rakefile +8 -0
  80. data/spec/faked_project/cucumber.yml +13 -0
  81. data/spec/faked_project/features/step_definitions/my_steps.rb +22 -0
  82. data/spec/faked_project/features/support/env.rb +12 -0
  83. data/spec/faked_project/features/test_stuff.feature +6 -0
  84. data/spec/faked_project/lib/faked_project.rb +11 -0
  85. data/spec/faked_project/lib/faked_project/framework_specific.rb +18 -0
  86. data/spec/faked_project/lib/faked_project/meta_magic.rb +24 -0
  87. data/spec/faked_project/lib/faked_project/some_class.rb +28 -0
  88. data/spec/faked_project/lib/faked_project/untested_class.rb +11 -0
  89. data/spec/faked_project/spec/faked_spec.rb +11 -0
  90. data/spec/faked_project/spec/forking_spec.rb +8 -0
  91. data/spec/faked_project/spec/meta_magic_spec.rb +15 -0
  92. data/spec/faked_project/spec/some_class_spec.rb +13 -0
  93. data/spec/faked_project/spec/spec_helper.rb +11 -0
  94. data/spec/faked_project/test/faked_test.rb +11 -0
  95. data/spec/faked_project/test/meta_magic_test.rb +13 -0
  96. data/spec/faked_project/test/some_class_test.rb +15 -0
  97. data/spec/faked_project/test/test_helper.rb +12 -0
  98. data/spec/file_list_spec.rb +50 -0
  99. data/spec/filters_spec.rb +98 -0
  100. data/spec/fixtures/app/controllers/sample_controller.rb +10 -0
  101. data/spec/fixtures/app/models/user.rb +10 -0
  102. data/spec/fixtures/deleted_source_sample.rb +15 -0
  103. data/spec/fixtures/frameworks/rspec_bad.rb +9 -0
  104. data/spec/fixtures/frameworks/rspec_good.rb +9 -0
  105. data/spec/fixtures/frameworks/testunit_bad.rb +9 -0
  106. data/spec/fixtures/frameworks/testunit_good.rb +9 -0
  107. data/spec/fixtures/iso-8859.rb +3 -0
  108. data/spec/fixtures/never.rb +2 -0
  109. data/spec/fixtures/resultset1.rb +4 -0
  110. data/spec/fixtures/resultset2.rb +4 -0
  111. data/spec/fixtures/sample.rb +16 -0
  112. data/spec/fixtures/skipped.rb +4 -0
  113. data/spec/fixtures/skipped_and_executed.rb +8 -0
  114. data/spec/fixtures/utf-8.rb +3 -0
  115. data/spec/helper.rb +26 -0
  116. data/spec/last_run_spec.rb +48 -0
  117. data/spec/multi_formatter_spec.rb +20 -0
  118. data/spec/raw_coverage_spec.rb +92 -0
  119. data/spec/result_merger_spec.rb +96 -0
  120. data/spec/result_spec.rb +209 -0
  121. data/spec/return_codes_spec.rb +34 -0
  122. data/spec/simplecov_spec.rb +110 -0
  123. data/spec/source_file_line_spec.rb +155 -0
  124. data/spec/source_file_spec.rb +141 -0
  125. data/spec/support/fail_rspec_on_ruby_warning.rb +75 -0
  126. metadata +320 -0
@@ -0,0 +1,8 @@
1
+ module SimpleCov
2
+ module ExitCodes
3
+ SUCCESS = 0
4
+ EXCEPTION = 1
5
+ MINIMUM_COVERAGE = 2
6
+ MAXIMUM_COVERAGE_DROP = 3
7
+ end
8
+ end
@@ -0,0 +1,59 @@
1
+ # An array of SimpleCov SourceFile instances with additional collection helper
2
+ # methods for calculating coverage across them etc.
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
10
+
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
16
+
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
22
+
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
28
+
29
+ # Computes the coverage based upon lines covered and lines missed for each file
30
+ # Returns an array with all coverage percentages
31
+ def covered_percentages
32
+ map(&:covered_percent)
33
+ end
34
+
35
+ # Finds the least covered file and returns that file's name
36
+ def least_covered_file
37
+ sort_by(&:covered_percent).first.filename
38
+ end
39
+
40
+ # Returns the overall amount of relevant lines of code across all files in this list
41
+ def lines_of_code
42
+ covered_lines + missed_lines
43
+ end
44
+
45
+ # Computes the coverage based upon lines covered and lines missed
46
+ # @return [Float]
47
+ def covered_percent
48
+ return 100.0 if empty? || lines_of_code.zero?
49
+ Float(covered_lines * 100.0 / lines_of_code)
50
+ end
51
+
52
+ # Computes the strength (hits / line) based upon lines covered and lines missed
53
+ # @return [Float]
54
+ def covered_strength
55
+ return 0.0 if empty? || lines_of_code.zero?
56
+ Float(map { |f| f.covered_strength * f.lines_of_code }.inject(&:+) / lines_of_code)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,54 @@
1
+ module SimpleCov
2
+ #
3
+ # Base filter class. Inherit from this to create custom filters,
4
+ # and overwrite the passes?(source_file) instance method
5
+ #
6
+ # # A sample class that rejects all source files.
7
+ # class StupidFilter < SimpleCov::Filter
8
+ # def passes?(source_file)
9
+ # false
10
+ # end
11
+ # end
12
+ #
13
+ class Filter
14
+ attr_reader :filter_argument
15
+ def initialize(filter_argument)
16
+ @filter_argument = filter_argument
17
+ end
18
+
19
+ def matches?(_)
20
+ raise "The base filter class is not intended for direct use"
21
+ end
22
+
23
+ def passes?(source_file)
24
+ warn "#{Kernel.caller.first}: [DEPRECATION] #passes? is deprecated. Use #matches? instead."
25
+ matches?(source_file)
26
+ end
27
+ end
28
+
29
+ class StringFilter < SimpleCov::Filter
30
+ # Returns true when the given source file's filename matches the
31
+ # string configured when initializing this Filter with StringFilter.new('somestring)
32
+ def matches?(source_file)
33
+ (source_file.filename =~ /#{filter_argument}/)
34
+ end
35
+ end
36
+
37
+ class BlockFilter < SimpleCov::Filter
38
+ # Returns true if the block given when initializing this filter with BlockFilter.new {|src_file| ... }
39
+ # returns true for the given source file.
40
+ def matches?(source_file)
41
+ filter_argument.call(source_file)
42
+ end
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
54
+ end
@@ -0,0 +1,8 @@
1
+ module SimpleCov
2
+ # TODO: Documentation on how to build your own formatters
3
+ module Formatter
4
+ end
5
+ end
6
+
7
+ require "simplecov/formatter/simple_formatter"
8
+ require "simplecov/formatter/multi_formatter"
@@ -0,0 +1,32 @@
1
+ module SimpleCov
2
+ module Formatter
3
+ class MultiFormatter
4
+ module InstanceMethods
5
+ def format(result)
6
+ formatters.map do |formatter|
7
+ begin
8
+ formatter.new.format(result)
9
+ rescue => e
10
+ STDERR.puts("Formatter #{formatter} failed with #{e.class}: #{e.message} (#{e.backtrace.first})")
11
+ nil
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.new(formatters = nil)
18
+ Class.new do
19
+ define_method :formatters do
20
+ @formatters ||= Array(formatters)
21
+ end
22
+ include InstanceMethods
23
+ end
24
+ end
25
+
26
+ def self.[](*args)
27
+ warn "#{Kernel.caller.first}: [DEPRECATION] ::[] is deprecated. Use ::new instead."
28
+ new(Array([*args]))
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ #
2
+ # A ridiculously simple formatter for SimpleCov results.
3
+ #
4
+ module SimpleCov
5
+ module Formatter
6
+ class SimpleFormatter
7
+ # Takes a SimpleCov::Result and generates a string out of it
8
+ def format(result)
9
+ output = ""
10
+ result.groups.each do |name, files|
11
+ output << "Group: #{name}\n"
12
+ output << "=" * 40
13
+ output << "\n"
14
+ files.each do |file|
15
+ output << "#{file.filename} (coverage: #{file.covered_percent.round(2)}%)\n"
16
+ end
17
+ output << "\n"
18
+ end
19
+ output
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,42 @@
1
+ if defined?(JRUBY_VERSION) && JRUBY_VERSION.to_f < 1.7
2
+ require "jruby"
3
+ java_import "org.jruby.ast.NodeType"
4
+
5
+ # Coverage for JRuby < 1.7.0 does not work correctly
6
+ #
7
+ # - does not distinguish lines that cannot be executed
8
+ # - does (partial) coverage for files loaded before `Coverage.start`.
9
+ # - does not expand a path like `lib/../spec` to `spec`.
10
+ #
11
+ # This monkey patches Coverage to address those issues
12
+ module Coverage
13
+ class << self
14
+ alias __broken_result__ result
15
+
16
+ def result # rubocop:disable Metrics/MethodLength
17
+ fixed = {}
18
+ __broken_result__.each do |path, executed_lines|
19
+ next unless File.file? path
20
+
21
+ covered_lines = executed_lines.dup
22
+
23
+ process = lambda do |node|
24
+ if node.node_type == NodeType::NEWLINENODE
25
+ pos = node.position
26
+ covered_lines[pos.line] ||= 0
27
+ end
28
+ node.child_nodes.each(&process)
29
+ end
30
+
31
+ process[JRuby.parse(File.read(path), path)]
32
+
33
+ if (first = covered_lines.detect { |x| x }) && first > 0
34
+ fixed[File.expand_path(path)] = covered_lines
35
+ end
36
+ end
37
+
38
+ fixed
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ require "json"
2
+
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
+
10
+ def read
11
+ return nil unless File.exist?(last_run_path)
12
+ json = File.read(last_run_path)
13
+ return nil if json.strip.empty?
14
+ JSON.parse(json)
15
+ end
16
+
17
+ def write(json)
18
+ File.open(last_run_path, "w+") do |f|
19
+ f.puts JSON.pretty_generate(json)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ require "etc"
2
+ home_dir = (ENV["HOME"] && File.expand_path("~")) || Etc.getpwuid.dir || (ENV["USER"] && File.expand_path("~#{ENV['USER']}"))
3
+ if home_dir
4
+ global_config_path = File.join(home_dir, ".simplecov")
5
+ load global_config_path if File.exist?(global_config_path)
6
+ end
@@ -0,0 +1,2 @@
1
+ ENV["SIMPLECOV_NO_DEFAULTS"] = "yes, no defaults"
2
+ require "simplecov"
@@ -0,0 +1,31 @@
1
+ #
2
+ # Profiles are SimpleCov configuration procs that can be easily
3
+ # loaded using SimpleCov.start :rails and defined using
4
+ # SimpleCov.profiles.define :foo do
5
+ # # SimpleCov configuration here, same as in SimpleCov.configure
6
+ # end
7
+ #
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
+ raise "SimpleCov Profile '#{name}' is already defined" unless self[name].nil?
19
+ self[name] = blk
20
+ end
21
+
22
+ #
23
+ # Applies the profile of given name on SimpleCov.configure
24
+ #
25
+ def load(name)
26
+ name = name.to_sym
27
+ raise "Could not find SimpleCov Profile called '#{name}'" unless key?(name)
28
+ SimpleCov.configure(&self[name])
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ module SimpleCov
2
+ class Railtie < ::Rails::Railtie
3
+ rake_tasks do
4
+ load "simplecov/railties/tasks.rake"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require "rake/testtask"
2
+ Rake::TestTask.new do |t|
3
+ t.name = "simplecov"
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
8
+ end
9
+
10
+ require "rake/clean"
11
+ CLOBBER.include "coverage"
@@ -0,0 +1,39 @@
1
+ module SimpleCov
2
+ module RawCoverage
3
+ module_function
4
+
5
+ # Merges multiple Coverage.result hashes
6
+ def merge_results(*results)
7
+ results.reduce({}) do |result, merged|
8
+ merge_resultsets(result, merged)
9
+ end
10
+ end
11
+
12
+ # Merges two Coverage.result hashes
13
+ def merge_resultsets(result1, result2)
14
+ (result1.keys | result2.keys).each_with_object({}) do |filename, merged|
15
+ file1 = result1[filename]
16
+ file2 = result2[filename]
17
+ merged[filename] = merge_file_coverage(file1, file2)
18
+ end
19
+ end
20
+
21
+ def merge_file_coverage(file1, file2)
22
+ return (file1 || file2).dup unless file1 && file2
23
+
24
+ file1.map.with_index do |count1, index|
25
+ count2 = file2[index]
26
+ merge_line_coverage(count1, count2)
27
+ end
28
+ end
29
+
30
+ def merge_line_coverage(count1, count2)
31
+ sum = count1.to_i + count2.to_i
32
+ if sum.zero? && (count1.nil? || count2.nil?)
33
+ nil
34
+ else
35
+ sum
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,86 @@
1
+ require "digest/sha1"
2
+ require "forwardable"
3
+
4
+ module SimpleCov
5
+ #
6
+ # A simplecov code coverage result, initialized from the Hash Ruby 1.9's built-in coverage
7
+ # library generates (Coverage.result).
8
+ #
9
+ class Result
10
+ extend Forwardable
11
+ # Returns the original Coverage.result used for this instance of SimpleCov::Result
12
+ attr_reader :original_result
13
+ # Returns all files that are applicable to this result (sans filters!) as instances of SimpleCov::SourceFile. Aliased as :source_files
14
+ attr_reader :files
15
+ alias source_files files
16
+ # Explicitly set the Time this result has been created
17
+ attr_writer :created_at
18
+ # Explicitly set the command name that was used for this coverage result. Defaults to SimpleCov.command_name
19
+ attr_writer :command_name
20
+
21
+ def_delegators :files, :covered_percent, :covered_percentages, :least_covered_file, :covered_strength, :covered_lines, :missed_lines
22
+ def_delegator :files, :lines_of_code, :total_lines
23
+
24
+ # Initialize a new SimpleCov::Result from given Coverage.result (a Hash of filenames each containing an array of
25
+ # coverage data)
26
+ def initialize(original_result)
27
+ @original_result = original_result.freeze
28
+ @files = SimpleCov::FileList.new(original_result.map do |filename, coverage|
29
+ SimpleCov::SourceFile.new(filename, coverage) if File.file?(filename)
30
+ end.compact.sort_by(&:filename))
31
+ filter!
32
+ end
33
+
34
+ # Returns all filenames for source files contained in this result
35
+ def filenames
36
+ files.map(&:filename)
37
+ end
38
+
39
+ # Returns a Hash of groups for this result. Define groups using SimpleCov.add_group 'Models', 'app/models'
40
+ def groups
41
+ @groups ||= SimpleCov.grouped(files)
42
+ end
43
+
44
+ # Applies the configured SimpleCov.formatter on this result
45
+ def format!
46
+ SimpleCov.formatter.new.format(self)
47
+ end
48
+
49
+ # Defines when this result has been created. Defaults to Time.now
50
+ def created_at
51
+ @created_at ||= Time.now
52
+ end
53
+
54
+ # The command name that launched this result.
55
+ # Delegated to SimpleCov.command_name if not set manually
56
+ def command_name
57
+ @command_name ||= SimpleCov.command_name
58
+ end
59
+
60
+ # Returns a hash representation of this Result that can be used for marshalling it into JSON
61
+ def to_hash
62
+ {command_name => {"coverage" => coverage, "timestamp" => created_at.to_i}}
63
+ end
64
+
65
+ # Loads a SimpleCov::Result#to_hash dump
66
+ def self.from_hash(hash)
67
+ command_name, data = hash.first
68
+ result = SimpleCov::Result.new(data["coverage"])
69
+ result.command_name = command_name
70
+ result.created_at = Time.at(data["timestamp"])
71
+ result
72
+ end
73
+
74
+ private
75
+
76
+ def coverage
77
+ keys = original_result.keys & filenames
78
+ Hash[keys.zip(original_result.values_at(*keys))]
79
+ end
80
+
81
+ # Applies all configured SimpleCov filters on this result's source files
82
+ def filter!
83
+ @files = SimpleCov.filtered(files)
84
+ end
85
+ end
86
+ end