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.
- checksums.yaml +7 -7
- data/.gitignore +0 -1
- data/.rubocop.yml +69 -0
- data/CHANGELOG.md +39 -22
- data/Gemfile +16 -15
- data/MIT-LICENSE +1 -1
- data/README.md +183 -178
- data/Rakefile +16 -7
- data/doc/alternate-formatters.md +36 -0
- data/doc/commercial-services.md +20 -0
- data/doc/editor-integration.md +13 -0
- data/features/rspec_basic.feature +3 -2
- data/features/rspec_groups_and_filters_complex.feature +2 -0
- data/features/rspec_groups_using_filter_class.feature +3 -2
- data/features/step_definitions/html_steps.rb +6 -7
- data/features/step_definitions/simplecov_steps.rb +18 -16
- data/features/step_definitions/transformers.rb +2 -2
- data/features/step_definitions/web_steps.rb +4 -4
- data/features/support/env.rb +17 -15
- data/lib/simplecov.rb +35 -24
- data/lib/simplecov/command_guesser.rb +33 -34
- data/lib/simplecov/configuration.rb +238 -234
- data/lib/simplecov/defaults.rb +37 -36
- data/lib/simplecov/exit_codes.rb +7 -5
- data/lib/simplecov/file_list.rb +38 -36
- data/lib/simplecov/filter.rb +12 -2
- data/lib/simplecov/formatter.rb +2 -2
- data/lib/simplecov/formatter/simple_formatter.rb +1 -1
- data/lib/simplecov/jruby_fix.rb +4 -4
- data/lib/simplecov/last_run.rb +15 -13
- data/lib/simplecov/merge_helpers.rb +26 -27
- data/lib/simplecov/no_defaults.rb +2 -2
- data/lib/simplecov/profiles.rb +21 -19
- data/lib/simplecov/railtie.rb +1 -1
- data/lib/simplecov/railties/tasks.rake +7 -7
- data/lib/simplecov/result.rb +5 -5
- data/lib/simplecov/result_merger.rb +65 -62
- data/lib/simplecov/source_file.rb +23 -24
- data/lib/simplecov/version.rb +20 -1
- data/simplecov.gemspec +14 -12
- data/test/faked_project/Gemfile +5 -5
- data/test/faked_project/Rakefile +4 -4
- data/test/faked_project/features/step_definitions/my_steps.rb +3 -4
- data/test/faked_project/features/support/env.rb +5 -5
- data/test/faked_project/lib/faked_project.rb +1 -1
- data/test/faked_project/lib/faked_project/some_class.rb +3 -4
- data/test/faked_project/spec/faked_spec.rb +2 -2
- data/test/faked_project/spec/forking_spec.rb +7 -0
- data/test/faked_project/spec/meta_magic_spec.rb +1 -1
- data/test/faked_project/spec/some_class_spec.rb +3 -3
- data/test/faked_project/spec/spec_helper.rb +4 -8
- data/test/faked_project/test/faked_test.rb +2 -2
- data/test/faked_project/test/meta_magic_test.rb +1 -1
- data/test/faked_project/test/some_class_test.rb +3 -3
- data/test/faked_project/test/test_helper.rb +5 -9
- data/test/fixtures/app/controllers/sample_controller.rb +1 -1
- data/test/fixtures/app/models/user.rb +1 -1
- data/test/fixtures/deleted_source_sample.rb +3 -3
- data/test/fixtures/frameworks/rspec_bad.rb +4 -4
- data/test/fixtures/frameworks/rspec_good.rb +4 -4
- data/test/fixtures/frameworks/testunit_bad.rb +3 -3
- data/test/fixtures/frameworks/testunit_good.rb +3 -3
- data/test/fixtures/resultset2.rb +0 -1
- data/test/fixtures/sample.rb +1 -1
- data/test/fixtures/utf-8.rb +1 -1
- data/test/helper.rb +8 -8
- data/test/test_1_8_fallbacks.rb +6 -6
- data/test/test_command_guesser.rb +7 -7
- data/test/test_deleted_source.rb +2 -2
- data/test/test_file_list.rb +8 -6
- data/test/test_filters.rb +29 -13
- data/test/test_merge_helpers.rb +26 -23
- data/test/test_result.rb +32 -23
- data/test/test_return_codes.rb +3 -3
- data/test/test_source_file.rb +4 -4
- data/test/test_source_file_line.rb +13 -13
- metadata +145 -63
- data/lib/simplecov/json.rb +0 -27
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require "rake/testtask"
|
2
2
|
Rake::TestTask.new do |t|
|
3
|
-
t.name =
|
3
|
+
t.name = "simplecov"
|
4
4
|
t.loader = :direct # uses require() which skips PWD in Ruby 1.9
|
5
|
-
t.libs.push
|
6
|
-
t.test_files = FileList[
|
7
|
-
t.ruby_opts.push
|
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
|
11
|
-
CLOBBER.include
|
10
|
+
require "rake/clean"
|
11
|
+
CLOBBER.include "coverage"
|
data/lib/simplecov/result.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
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
|
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,
|
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
|
-
|
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
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
+
def resultset_writelock
|
17
|
+
File.join(SimpleCov.coverage_path, ".resultset.json.lock")
|
18
|
+
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
@@ -25,26 +25,26 @@ module SimpleCov
|
|
25
25
|
alias_method :number, :line_number
|
26
26
|
|
27
27
|
def initialize(src, line_number, coverage)
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
fail ArgumentError, "Only String accepted for source" unless src.is_a?(String)
|
29
|
+
fail ArgumentError, "Only Fixnum accepted for line_number" unless line_number.is_a?(Fixnum)
|
30
|
+
fail ArgumentError, "Only Fixnum and nil accepted for coverage" unless coverage.is_a?(Fixnum) || coverage.nil?
|
31
31
|
@src, @line_number, @coverage = src, line_number, coverage
|
32
32
|
@skipped = false
|
33
33
|
end
|
34
34
|
|
35
35
|
# Returns true if this is a line that should have been covered, but was not
|
36
36
|
def missed?
|
37
|
-
|
37
|
+
!never? && !skipped? && coverage.zero?
|
38
38
|
end
|
39
39
|
|
40
40
|
# Returns true if this is a line that has been covered
|
41
41
|
def covered?
|
42
|
-
|
42
|
+
!never? && !skipped? && coverage > 0
|
43
43
|
end
|
44
44
|
|
45
45
|
# Returns true if this line is not relevant for coverage
|
46
46
|
def never?
|
47
|
-
|
47
|
+
!skipped? && coverage.nil?
|
48
48
|
end
|
49
49
|
|
50
50
|
# Flags this line as skipped
|
@@ -55,16 +55,16 @@ module SimpleCov
|
|
55
55
|
# Returns true if this line was skipped, false otherwise. Lines are skipped if they are wrapped with
|
56
56
|
# # :nocov: comment lines.
|
57
57
|
def skipped?
|
58
|
-
|
58
|
+
!!skipped
|
59
59
|
end
|
60
60
|
|
61
61
|
# The status of this line - either covered, missed, skipped or never. Useful i.e. for direct use
|
62
62
|
# as a css class in report generation
|
63
63
|
def status
|
64
|
-
return
|
65
|
-
return
|
66
|
-
return
|
67
|
-
return
|
64
|
+
return "skipped" if skipped?
|
65
|
+
return "never" if never?
|
66
|
+
return "missed" if missed?
|
67
|
+
return "covered" if covered?
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -78,7 +78,7 @@ module SimpleCov
|
|
78
78
|
|
79
79
|
def initialize(filename, coverage)
|
80
80
|
@filename, @coverage = filename, coverage
|
81
|
-
File.open(filename, "rb") {|f| @src = f.readlines }
|
81
|
+
File.open(filename, "rb") { |f| @src = f.readlines }
|
82
82
|
end
|
83
83
|
|
84
84
|
# Returns all source lines for this file as instances of SimpleCov::SourceFile::Line,
|
@@ -94,7 +94,7 @@ module SimpleCov
|
|
94
94
|
# Initialize lines
|
95
95
|
@lines = []
|
96
96
|
src.each_with_index do |src, i|
|
97
|
-
@lines << SimpleCov::SourceFile::Line.new(src, i+1, coverage[i])
|
97
|
+
@lines << SimpleCov::SourceFile::Line.new(src, i + 1, coverage[i])
|
98
98
|
end
|
99
99
|
process_skipped_lines!
|
100
100
|
@lines
|
@@ -103,14 +103,14 @@ module SimpleCov
|
|
103
103
|
|
104
104
|
# Access SimpleCov::SourceFile::Line source lines by line number
|
105
105
|
def line(number)
|
106
|
-
lines[number-1]
|
106
|
+
lines[number - 1]
|
107
107
|
end
|
108
108
|
|
109
109
|
# The coverage for this file in percent. 0 if the file has no relevant lines
|
110
110
|
def covered_percent
|
111
|
-
return 100.0 if lines.length
|
111
|
+
return 100.0 if lines.length.zero? || lines.length == never_lines.count
|
112
112
|
relevant_lines = lines.count - never_lines.count - skipped_lines.count
|
113
|
-
if relevant_lines
|
113
|
+
if relevant_lines.zero?
|
114
114
|
0.0
|
115
115
|
else
|
116
116
|
Float((covered_lines.count) * 100.0 / relevant_lines.to_f)
|
@@ -118,7 +118,7 @@ module SimpleCov
|
|
118
118
|
end
|
119
119
|
|
120
120
|
def covered_strength
|
121
|
-
return 0.0 if lines.length
|
121
|
+
return 0.0 if lines.length.zero? || lines.length == never_lines.count
|
122
122
|
|
123
123
|
lines_strength = 0
|
124
124
|
lines.each do |c|
|
@@ -127,7 +127,7 @@ module SimpleCov
|
|
127
127
|
|
128
128
|
effective_lines_count = Float(lines.count - never_lines.count - skipped_lines.count)
|
129
129
|
|
130
|
-
if effective_lines_count
|
130
|
+
if effective_lines_count.zero?
|
131
131
|
0.0
|
132
132
|
else
|
133
133
|
strength = lines_strength / effective_lines_count
|
@@ -137,24 +137,24 @@ module SimpleCov
|
|
137
137
|
|
138
138
|
# Returns all covered lines as SimpleCov::SourceFile::Line
|
139
139
|
def covered_lines
|
140
|
-
@covered_lines ||= lines.select
|
140
|
+
@covered_lines ||= lines.select(&:covered?)
|
141
141
|
end
|
142
142
|
|
143
143
|
# Returns all lines that should have been, but were not covered
|
144
144
|
# as instances of SimpleCov::SourceFile::Line
|
145
145
|
def missed_lines
|
146
|
-
@missed_lines ||= lines.select
|
146
|
+
@missed_lines ||= lines.select(&:missed?)
|
147
147
|
end
|
148
148
|
|
149
149
|
# Returns all lines that are not relevant for coverage as
|
150
150
|
# SimpleCov::SourceFile::Line instances
|
151
151
|
def never_lines
|
152
|
-
@never_lines ||= lines.select
|
152
|
+
@never_lines ||= lines.select(&:never?)
|
153
153
|
end
|
154
154
|
|
155
155
|
# Returns all lines that were skipped as SimpleCov::SourceFile::Line instances
|
156
156
|
def skipped_lines
|
157
|
-
@skipped_lines ||= lines.select
|
157
|
+
@skipped_lines ||= lines.select(&:skipped?)
|
158
158
|
end
|
159
159
|
|
160
160
|
# Returns the number of relevant lines (covered + missed)
|
@@ -175,7 +175,7 @@ module SimpleCov
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
-
|
178
|
+
private
|
179
179
|
|
180
180
|
# ruby 1.9 could use Float#round(places) instead
|
181
181
|
# @return [Float]
|
@@ -185,4 +185,3 @@ module SimpleCov
|
|
185
185
|
end
|
186
186
|
end
|
187
187
|
end
|
188
|
-
|
data/lib/simplecov/version.rb
CHANGED
@@ -1,3 +1,22 @@
|
|
1
1
|
module SimpleCov
|
2
|
-
VERSION = "0.
|
2
|
+
VERSION = "0.10.0"
|
3
|
+
def VERSION.to_a
|
4
|
+
split(".").map(&:to_i)
|
5
|
+
end
|
6
|
+
|
7
|
+
def VERSION.major
|
8
|
+
to_a[0]
|
9
|
+
end
|
10
|
+
|
11
|
+
def VERSION.minor
|
12
|
+
to_a[1]
|
13
|
+
end
|
14
|
+
|
15
|
+
def VERSION.patch
|
16
|
+
to_a[2]
|
17
|
+
end
|
18
|
+
|
19
|
+
def VERSION.pre
|
20
|
+
to_a[3]
|
21
|
+
end
|
3
22
|
end
|
data/simplecov.gemspec
CHANGED
@@ -1,25 +1,27 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'simplecov/version'
|
1
|
+
$LOAD_PATH.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "simplecov/version"
|
4
3
|
|
5
4
|
Gem::Specification.new do |gem|
|
6
|
-
gem.name =
|
5
|
+
gem.name = "simplecov"
|
7
6
|
gem.version = SimpleCov::VERSION
|
8
7
|
gem.platform = Gem::Platform::RUBY
|
9
8
|
gem.authors = ["Christoph Olszowka"]
|
10
|
-
gem.email = [
|
11
|
-
gem.homepage =
|
12
|
-
gem.description = %
|
9
|
+
gem.email = ["christoph at olszowka de"]
|
10
|
+
gem.homepage = "http://github.com/colszowka/simplecov"
|
11
|
+
gem.description = %(Code coverage for Ruby 1.9+ with a powerful configuration library and automatic merging of coverage across test suites)
|
13
12
|
gem.summary = gem.description
|
14
13
|
gem.license = "MIT"
|
15
14
|
|
16
15
|
gem.required_ruby_version = ">= 1.8.7"
|
17
|
-
|
18
|
-
gem.add_dependency
|
19
|
-
gem.add_dependency
|
16
|
+
|
17
|
+
gem.add_dependency "json", "~> 1.8"
|
18
|
+
gem.add_dependency "simplecov-html", "~> 0.10.0"
|
19
|
+
gem.add_dependency "docile", "~> 1.1.0"
|
20
|
+
|
21
|
+
gem.add_development_dependency "bundler", "~> 1.9"
|
20
22
|
|
21
23
|
gem.files = `git ls-files`.split("\n")
|
22
24
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
-
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
-
gem.require_paths = [
|
25
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
26
|
+
gem.require_paths = ["lib"]
|
25
27
|
end
|
data/test/faked_project/Gemfile
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
|
-
gem
|
4
|
-
gem
|
5
|
-
gem
|
6
|
-
gem
|
3
|
+
gem "simplecov", :path => "../../../"
|
4
|
+
gem "rake"
|
5
|
+
gem "rspec", ">= 2.6.0"
|
6
|
+
gem "cucumber"
|
data/test/faked_project/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require "bundler"
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rake/testtask"
|
4
4
|
Rake::TestTask.new(:test) do |test|
|
5
|
-
test.libs <<
|
6
|
-
test.test_files = FileList[
|
5
|
+
test.libs << "lib" << "test"
|
6
|
+
test.test_files = FileList["test/**/*_test.rb"].sort
|
7
7
|
test.verbose = true
|
8
8
|
end
|
@@ -7,7 +7,7 @@ When /^I write my cukes for the fake project$/ do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
Then /^I make all neccessary tests in a single step$/ do
|
10
|
-
expect(FakedProject.foo).to eq(
|
10
|
+
expect(FakedProject.foo).to eq("bar")
|
11
11
|
|
12
12
|
expect(FrameworkSpecific.cucumber).to eq("Only tested in Cucumber")
|
13
13
|
|
@@ -17,7 +17,6 @@ Then /^I make all neccessary tests in a single step$/ do
|
|
17
17
|
expect(FakedProject.new.dynamic).to eq("A dynamically defined instance method")
|
18
18
|
|
19
19
|
something = SomeClass.new("foo")
|
20
|
-
expect(something.reverse).to eq(
|
21
|
-
expect(something.compare_with(
|
20
|
+
expect(something.reverse).to eq("oof")
|
21
|
+
expect(something.compare_with("foo")).to be true
|
22
22
|
end
|
23
|
-
|