simplecov 0.3.0 → 0.3.1
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.
- data/README.rdoc +238 -11
- data/Rakefile +0 -13
- data/VERSION +1 -1
- data/lib/simplecov.rb +23 -12
- data/lib/simplecov/adapters.rb +4 -4
- data/lib/simplecov/configuration.rb +19 -3
- data/lib/simplecov/filter.rb +4 -0
- data/lib/simplecov/formatter.rb +1 -1
- data/lib/simplecov/formatter/simple_formatter.rb +4 -0
- data/lib/simplecov/merge_helpers.rb +2 -0
- data/lib/simplecov/result.rb +24 -5
- data/lib/simplecov/result_merger.rb +17 -0
- data/lib/simplecov/source_file.rb +35 -3
- data/simplecov.gemspec +2 -2
- metadata +3 -3
data/README.rdoc
CHANGED
@@ -1,30 +1,257 @@
|
|
1
1
|
= simplecov
|
2
2
|
|
3
|
-
SimpleCov is a code coverage analysis tool for Ruby 1.9. It
|
4
|
-
|
5
|
-
|
3
|
+
SimpleCov is a code coverage analysis tool for Ruby 1.9. It uses 1.9's built-in Coverage library to gather code
|
4
|
+
coverage data, but makes processing it's results much easier by providing a clean API to filter, group, merge, format
|
5
|
+
and display those results, thus giving you a complete code coverage suite with just a couple lines of code.
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
In most cases, you'll want overall coverage results for your projects, including all types of tests, cucumber features
|
8
|
+
etc. Simplecov automatically takes care of this by caching and then merging results when generating reports, so your
|
9
|
+
coverage report gives you a more accurate report on the blank spots in your test coverage.
|
9
10
|
|
10
|
-
|
11
|
-
for
|
11
|
+
Though a very simple formatter for printing the coverage results comes bundled with the simplecov gem, this is more
|
12
|
+
for explaining the basic usage of formatters if you want to build your own. To get a pretty HTML-page with your results,
|
13
|
+
you will want to use the simplecov-html gem (http://github.com/colszowka/simplecov-html).
|
12
14
|
|
13
|
-
==
|
15
|
+
== Basic usage
|
14
16
|
|
15
17
|
Update your Gemfile with this and do a bundle install:
|
16
18
|
group :test do
|
17
|
-
gem 'simplecov', '>= 0.
|
18
|
-
gem 'simplecov-html', '>= 0.2.0'
|
19
|
+
gem 'simplecov-html', '>= 0.3.0' # Will install simplecov as a dependency
|
19
20
|
end
|
20
21
|
|
21
22
|
Then, add the following to your Rails test/test_helper.rb (right at the top, line 00):
|
22
23
|
|
23
|
-
require '
|
24
|
+
require 'simplecov-html'
|
24
25
|
SimpleCov.start 'rails'
|
25
26
|
|
26
27
|
Now, when running rake test you'll get a coverage/ folder inside your app's root where you can browse your code coverage.
|
27
28
|
|
29
|
+
== Configuration
|
30
|
+
|
31
|
+
Configuration settings can be applied in three formats.
|
32
|
+
|
33
|
+
The 'direct' way:
|
34
|
+
|
35
|
+
SimpleCov.some_config_option 'foo'
|
36
|
+
|
37
|
+
Using a block:
|
38
|
+
|
39
|
+
SimpleCov.configure do
|
40
|
+
some_config_option 'foo'
|
41
|
+
end
|
42
|
+
|
43
|
+
Using a block and automatically starting the coverage:
|
44
|
+
|
45
|
+
SimpleCov.start do
|
46
|
+
some_config_option 'foo'
|
47
|
+
end
|
48
|
+
|
49
|
+
Most times, you'll want to use the latter, so loading and setting up simplecov is in one place at the top of your test helper.
|
50
|
+
|
51
|
+
== Filters
|
52
|
+
|
53
|
+
Filters can be used to remove selected files from your coverage data. By default, a filter is applied that removes all files
|
54
|
+
OUTSIDE of your project's root directory - otherwise you'd end up with a billion of coverage reports for source files in the
|
55
|
+
gems you are using.
|
56
|
+
|
57
|
+
Of course you can define your own to remove things like configuration files, tests or whatever you don't need in your coverage
|
58
|
+
report.
|
59
|
+
|
60
|
+
=== Defining custom filters
|
61
|
+
|
62
|
+
You can currently define a filter using either a String (that will then be Regexp-matched against each source file's path),
|
63
|
+
a block or by passing in your own Filter class.
|
64
|
+
|
65
|
+
==== String filter
|
66
|
+
|
67
|
+
SimpleCov.start do
|
68
|
+
add_filter "/test/"
|
69
|
+
end
|
70
|
+
|
71
|
+
This simple string filter will remove all files that match "/test/" in their path.
|
72
|
+
|
73
|
+
==== Block filter
|
74
|
+
|
75
|
+
SimpleCov.start do
|
76
|
+
add_filter do |source_file|
|
77
|
+
source_file.lines.count < 5
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
Block filters receive a SimpleCov::SourceFile instance and expect your block to return either true (if the file is to be removed
|
82
|
+
from the result) or false (if the result should be kept). Please check out the RDoc for SimpleCov::SourceFile to learn about the
|
83
|
+
methods available to you. In the above example, the filter will remove all files that have less then 5 lines of code.
|
84
|
+
|
85
|
+
==== Custom filter class
|
86
|
+
|
87
|
+
class LineFilter < SimpleCov::Filter
|
88
|
+
def passes?(source_file)
|
89
|
+
source_file.lines.count < filter_argument
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
SimpleCov.add_filter LineFilter.new(5)
|
94
|
+
|
95
|
+
Defining your own filters is pretty easy: Just inherit from SimpleCov::Filter and define a method 'passes?(source_file)'. When running
|
96
|
+
the filter, a true return value from this method will result in the removal of the given source_file. The filter_argument method
|
97
|
+
is being set in the SimpleCov::Filter initialize method and thus is set to 5 in this example.
|
98
|
+
|
99
|
+
== Groups
|
100
|
+
|
101
|
+
You can separate your source files into groups. For example, in a rails app, you'll want to have separate listings for
|
102
|
+
Models, Controllers, Helpers, Libs and Plugins. Group definition works similar to Filters (and indeed also accepts custom
|
103
|
+
filter classes), but source files end up in a group when the filter passes (returns true), as opposed to filtering results,
|
104
|
+
which exclude files from results when the filter results in a true value.
|
105
|
+
|
106
|
+
Add your groups with:
|
107
|
+
|
108
|
+
SimpleCov.start do
|
109
|
+
add_group "Models", "app/models"
|
110
|
+
add_group "Controllers", "app/controllers"
|
111
|
+
add_group "Long files" do |src_file|
|
112
|
+
src_file.lines.count > 100
|
113
|
+
end
|
114
|
+
add_group "Short files", LineFilter.new(5) # Using the LineFilter class defined in Filters section above
|
115
|
+
end
|
116
|
+
|
117
|
+
== Merging results
|
118
|
+
|
119
|
+
Normally, you want to have your coverage analyzed across ALL of your test suites, right?
|
120
|
+
|
121
|
+
Simplecov automatically caches coverage results in your (coverage_path)/resultset.yml. Those results will then
|
122
|
+
be automatically merged when generating the result, so when coverage is set up properly for cucumber and your
|
123
|
+
unit / functional / integration tests, all of those test suites will be taken into account when building the
|
124
|
+
coverage report.
|
125
|
+
|
126
|
+
There are two things to note here though:
|
127
|
+
|
128
|
+
=== Test suite names
|
129
|
+
|
130
|
+
First, simplecov by itself does not really know about "test suites" and thus makes a guess based upon the command
|
131
|
+
line arguments it is currently running on. This works fine, though the test suites used for your coverage report
|
132
|
+
won't be easy to recognize.
|
133
|
+
|
134
|
+
Thus, if you want nicely labeled test suites, you have to give Simplecov a cue what the name of the currently running
|
135
|
+
test suite is. You can do so by specifying SimpleCov.command_name in one test file that is part of your specific suite.
|
136
|
+
|
137
|
+
So, in order to get proper suite names in a Rails app (yeah, sorry for being Rails biased, but everyone knows what
|
138
|
+
the structure of those projects is. You can apply this accordingly to the RSpecs for your Outlook-WebDAV-Calendar-Sync gem),
|
139
|
+
you could do something like this:
|
140
|
+
|
141
|
+
# test/unit/some_test.rb
|
142
|
+
SimpleCov.command_name 'Unit Tests'
|
143
|
+
|
144
|
+
# test/functionals/some_controller_test.rb
|
145
|
+
SimpleCov.command_name "Functional Tests"
|
146
|
+
|
147
|
+
# test/integration/some_integration_test.rb
|
148
|
+
SimpleCov.command_name "Integration Tests"
|
149
|
+
|
150
|
+
# features/steps/web_steps.rb
|
151
|
+
SimpleCov.command_name "Cucumber Features"
|
152
|
+
|
153
|
+
Note that this has only to be invoked ONCE PER TEST SUITE, so even if you have 200 unit test files, specifying it in
|
154
|
+
some_test.rb is fair enough.
|
155
|
+
|
156
|
+
simplecov-html prints the used test suites in the footer of the generated coverage report.
|
157
|
+
|
158
|
+
=== Timeout for merge
|
159
|
+
|
160
|
+
Of course, your cached coverage data is likely to become invalid at some point. Thus, result sets that are older than
|
161
|
+
SimpleCov.merge_timeout will not be used any more. By default, the timeout is 600 seconds (10 minutes), and you can
|
162
|
+
raise (or lower) it by specifying SimpleCov.merge_timeout 3600 (1 hour), or, inside a configure/start block, with
|
163
|
+
just "merge_timeout 3600".
|
164
|
+
|
165
|
+
You can deactivate merging altogether with "SimpleCov.use_merging false".
|
166
|
+
|
167
|
+
== Adapters
|
168
|
+
|
169
|
+
By default, Simplecov's only config assumption is that you only want coverage reports for files inside your project
|
170
|
+
root. To save you from repetitive configuration, you can use predefined blocks of configuration, called 'adapters',
|
171
|
+
or define your own.
|
172
|
+
|
173
|
+
You can then pass the name of the adapter to be used as the first argument to SimpleCov.start. For example, simplecov
|
174
|
+
comes bundled with a 'rails' adapter. It looks somewhat like this:
|
175
|
+
|
176
|
+
SimpleCov.adapters.define 'rails' do
|
177
|
+
add_filter '/test/'
|
178
|
+
add_filter '/config/'
|
179
|
+
|
180
|
+
add_group 'Controllers', 'app/controllers'
|
181
|
+
add_group 'Models', 'app/models'
|
182
|
+
add_group 'Helpers', 'app/helpers'
|
183
|
+
add_group 'Libraries', 'lib'
|
184
|
+
add_group 'Plugins', 'vendor/plugins'
|
185
|
+
end
|
186
|
+
|
187
|
+
As you can see, it's just a glorified SimpleCov.configure block. In your test_helper.rb, launch simplecov with:
|
188
|
+
|
189
|
+
SimpleCov.start 'rails'
|
190
|
+
|
191
|
+
OR
|
192
|
+
|
193
|
+
SimpleCov.start 'rails' do
|
194
|
+
# additional config here
|
195
|
+
end
|
196
|
+
|
197
|
+
=== Custom adapters
|
198
|
+
|
199
|
+
You can load additional adapters with the SimpleCov.load_adapter('xyz') method. This allows you to build upon an existing
|
200
|
+
adapter and customize it so you can reuse it in unit tests and cucumber features, for example.
|
201
|
+
|
202
|
+
# lib/simplecov_custom_adapter.rb
|
203
|
+
require 'simplecov'
|
204
|
+
SimpleCov.adapters.define 'myadapter' do
|
205
|
+
load_adapter 'rails'
|
206
|
+
add_filter 'vendor' # Don't include vendored stuff
|
207
|
+
end
|
208
|
+
|
209
|
+
# features/support/env.rb
|
210
|
+
require 'simplecov_custom_adapter'
|
211
|
+
SimpleCov.start 'myadapter'
|
212
|
+
|
213
|
+
# test/test_helper.rb
|
214
|
+
require 'simplecov_custom_adapter'
|
215
|
+
SimpleCov.start 'myadapter'
|
216
|
+
|
217
|
+
== Customizing exit behaviour
|
218
|
+
|
219
|
+
You can define what simplecov should do when your test suite finishes by customizing the at_exit hook:
|
220
|
+
|
221
|
+
SimpleCov.at_exit do
|
222
|
+
SimpleCov.result.format!
|
223
|
+
end
|
224
|
+
|
225
|
+
Above is the default behaviour. Do whatever you like instead!
|
226
|
+
|
227
|
+
== Using your own formatter
|
228
|
+
|
229
|
+
You can use your own formatter with:
|
230
|
+
|
231
|
+
SimpleCov.formatter = SimpleCov::Formatter::HTMLFormatter
|
232
|
+
|
233
|
+
When calling SimpleCov.result.format!, it will be invoked with SimpleCov::Formatter::YourFormatter.new.format(result), "result"
|
234
|
+
being an instance of SimpleCov::Result. Do whatever your wish with that!
|
235
|
+
|
236
|
+
== Configuration options
|
237
|
+
|
238
|
+
=== SimpleCov.root '/some/path/to/coverage'
|
239
|
+
|
240
|
+
The root directory for the project coverage is being generated for. This defaults to the current working directory
|
241
|
+
and should be just fine. Note that by default, all files outside of root will be filtered and thus not included in your
|
242
|
+
coverage report, so you'll probably rarely want to adjust this setting other than specifying an absolute path here.
|
243
|
+
|
244
|
+
=== SimpleCov.coverage_dir 'coverage'
|
245
|
+
|
246
|
+
The name of the subdirectory of root that coverage will be generated to. Defaults to 'coverage'.
|
247
|
+
|
248
|
+
=== ...TODO...
|
249
|
+
|
250
|
+
== Kudos
|
251
|
+
|
252
|
+
Thanks to Aaron Patterson (http://engineering.attinteractive.com/2010/08/code-coverage-in-ruby-1-9/) for the original idea
|
253
|
+
for this!
|
254
|
+
|
28
255
|
== TODO
|
29
256
|
* Improve on tests (integration tests)
|
30
257
|
|
data/Rakefile
CHANGED
@@ -25,19 +25,6 @@ Rake::TestTask.new(:test) do |test|
|
|
25
25
|
test.verbose = true
|
26
26
|
end
|
27
27
|
|
28
|
-
begin
|
29
|
-
require 'rcov/rcovtask'
|
30
|
-
Rcov::RcovTask.new do |test|
|
31
|
-
test.libs << 'test'
|
32
|
-
test.pattern = 'test/**/test_*.rb'
|
33
|
-
test.verbose = true
|
34
|
-
end
|
35
|
-
rescue LoadError
|
36
|
-
task :rcov do
|
37
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
28
|
task :test => :check_dependencies
|
42
29
|
|
43
30
|
task :default => :test
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
data/lib/simplecov.rb
CHANGED
@@ -1,14 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# Code coverage for ruby 1.9. Please check out README for a full introduction.
|
3
|
+
#
|
1
4
|
module SimpleCov
|
5
|
+
# Indicates invalid coverage data
|
2
6
|
class CoverageDataError < StandardError; end;
|
7
|
+
|
8
|
+
# The version of the simplecov gem
|
3
9
|
VERSION = File.read(File.join(File.dirname(__FILE__), '../VERSION'))
|
4
10
|
|
5
11
|
class << self
|
6
|
-
attr_accessor :running
|
12
|
+
attr_accessor :running#, :result # TODO: Remove result?
|
7
13
|
|
8
14
|
#
|
9
15
|
# Sets up SimpleCov to run against your project.
|
16
|
+
# You can optionally specify an adapter to use as well as configuration with a block:
|
17
|
+
# SimpleCov.start
|
18
|
+
# OR
|
19
|
+
# SimpleCov.start 'rails' # using rails adapter
|
20
|
+
# OR
|
21
|
+
# SimpleCov.start do
|
22
|
+
# add_filter 'test'
|
23
|
+
# end
|
24
|
+
# OR
|
25
|
+
# SimpleCov.start 'rails' do
|
26
|
+
# add_filter 'test'
|
27
|
+
# end
|
10
28
|
#
|
11
|
-
#
|
29
|
+
# Please check out the RDoc for SimpleCov::Configuration to find about available config options
|
12
30
|
#
|
13
31
|
def start(adapter=nil, &block)
|
14
32
|
unless "1.9".respond_to?(:encoding)
|
@@ -24,12 +42,13 @@ module SimpleCov
|
|
24
42
|
end
|
25
43
|
|
26
44
|
#
|
27
|
-
# Returns the result for the
|
45
|
+
# Returns the result for the current coverage run, merging it across test suites
|
46
|
+
# from cache using SimpleCov::ResultMerger if use_merging is activated (default)
|
28
47
|
#
|
29
48
|
def result
|
30
49
|
@result ||= SimpleCov::Result.new(Coverage.result) if running
|
31
50
|
# If we're using merging of results, store the current result
|
32
|
-
# first, then merge the results and return
|
51
|
+
# first, then merge the results and return those
|
33
52
|
if use_merging
|
34
53
|
SimpleCov::ResultMerger.store_result(@result) if @result
|
35
54
|
return SimpleCov::ResultMerger.merged_result
|
@@ -40,14 +59,6 @@ module SimpleCov
|
|
40
59
|
self.running = false
|
41
60
|
end
|
42
61
|
|
43
|
-
#
|
44
|
-
# Returns the project name - currently assuming the last dirname in
|
45
|
-
# the SimpleCov.root is this
|
46
|
-
#
|
47
|
-
def project_name
|
48
|
-
File.basename(root.split('/').last).capitalize.gsub('_', ' ')
|
49
|
-
end
|
50
|
-
|
51
62
|
#
|
52
63
|
# Applies the configured filters to the given array of SimpleCov::SourceFile items
|
53
64
|
#
|
data/lib/simplecov/adapters.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#
|
2
2
|
# Adaptars are glorified SimpleCov configuration procs that can be easily
|
3
3
|
# loaded using SimpleCov.start :rails and defined using
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
4
|
+
# SimpleCov.adapters.define :foo do
|
5
|
+
# # SimpleCov configuration here, same as in SimpleCov.configure
|
6
|
+
# end
|
7
7
|
#
|
8
8
|
class SimpleCov::Adapters < Hash
|
9
9
|
#
|
@@ -19,7 +19,7 @@ class SimpleCov::Adapters < Hash
|
|
19
19
|
end
|
20
20
|
|
21
21
|
#
|
22
|
-
# Applies the adapter of given name
|
22
|
+
# Applies the adapter of given name on SimpleCov.configure
|
23
23
|
#
|
24
24
|
def load(name)
|
25
25
|
name = name.to_sym
|
@@ -79,14 +79,15 @@ module SimpleCov::Configuration
|
|
79
79
|
end
|
80
80
|
|
81
81
|
#
|
82
|
-
#
|
82
|
+
# Allows you to configure simplecov in a block instead of prepending SimpleCov to all config methods
|
83
|
+
# you're calling.
|
83
84
|
#
|
84
85
|
# SimpleCov.configure do
|
85
86
|
# add_filter 'foobar'
|
86
87
|
# end
|
87
88
|
#
|
88
|
-
# This is equivalent to SimpleCov.add_filter 'foobar' and thus makes it easier to set a
|
89
|
-
# options.
|
89
|
+
# This is equivalent to SimpleCov.add_filter 'foobar' and thus makes it easier to set a buchn of configure
|
90
|
+
# options at once.
|
90
91
|
#
|
91
92
|
def configure(&block)
|
92
93
|
instance_exec(&block)
|
@@ -109,6 +110,16 @@ module SimpleCov::Configuration
|
|
109
110
|
@at_exit ||= Proc.new { SimpleCov.result.format! }
|
110
111
|
end
|
111
112
|
|
113
|
+
#
|
114
|
+
# Returns the project name - currently assuming the last dirname in
|
115
|
+
# the SimpleCov.root is this.
|
116
|
+
#
|
117
|
+
def project_name(new_name=nil)
|
118
|
+
return @project_name if @project_name and new_name.nil?
|
119
|
+
@project_name = new_name if new_name.kind_of?(String)
|
120
|
+
@project_name ||= File.basename(root.split('/').last).capitalize.gsub('_', ' ')
|
121
|
+
end
|
122
|
+
|
112
123
|
#
|
113
124
|
# Defines whether to use result merging so all your test suites (test:units, test:functionals, cucumber, ...)
|
114
125
|
# are joined and combined into a single coverage report
|
@@ -153,6 +164,11 @@ module SimpleCov::Configuration
|
|
153
164
|
filters << parse_filter(filter_argument, &filter_proc)
|
154
165
|
end
|
155
166
|
|
167
|
+
#
|
168
|
+
# Define a group for files. Works similar to add_filter, only that the first
|
169
|
+
# argument is the desired group name and files PASSING the filter end up in the group
|
170
|
+
# (while filters exclude when the filter is applicable).
|
171
|
+
#
|
156
172
|
def add_group(group_name, filter_argument=nil, &filter_proc)
|
157
173
|
groups[group_name] = parse_filter(filter_argument, &filter_proc)
|
158
174
|
end
|
data/lib/simplecov/filter.rb
CHANGED
@@ -22,12 +22,16 @@ module SimpleCov
|
|
22
22
|
end
|
23
23
|
|
24
24
|
class StringFilter < SimpleCov::Filter
|
25
|
+
# Returns true when the given source file's filename matches the
|
26
|
+
# string configured when initializing this Filter with StringFilter.new('somestring)
|
25
27
|
def passes?(source_file)
|
26
28
|
!(source_file.filename =~ /#{filter_argument}/)
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
32
|
class BlockFilter < SimpleCov::Filter
|
33
|
+
# Returns true if the block given when initializing this filter with BlockFilter.new {|src_file| ... }
|
34
|
+
# returns true for the given source file.
|
31
35
|
def passes?(source_file)
|
32
36
|
!filter_argument.call(source_file)
|
33
37
|
end
|
data/lib/simplecov/formatter.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
module SimpleCov::ArrayMergeHelper
|
2
|
+
# Merges an array of coverage results with self
|
2
3
|
def merge_resultset(array)
|
3
4
|
new_array = []
|
4
5
|
|
@@ -20,6 +21,7 @@ module SimpleCov::ArrayMergeHelper
|
|
20
21
|
end
|
21
22
|
|
22
23
|
module SimpleCov::HashMergeHelper
|
24
|
+
# Merges the given Coverage.result hash with self
|
23
25
|
def merge_resultset(hash)
|
24
26
|
new_resultset = {}
|
25
27
|
(self.keys + hash.keys).each do |filename|
|
data/lib/simplecov/result.rb
CHANGED
@@ -2,45 +2,63 @@ require 'digest/sha1'
|
|
2
2
|
require 'yaml'
|
3
3
|
|
4
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
|
+
#
|
5
9
|
class Result
|
6
|
-
|
7
|
-
|
10
|
+
# Returns the original Coverage.result used for this instance of SimpleCov::Result
|
11
|
+
attr_reader :original_result
|
12
|
+
# Returns all files that are applicable to this result (sans filters!) as instances of SimpleCov::SourceFile. Aliased as :source_files
|
13
|
+
attr_reader :files
|
8
14
|
alias_method :source_files, :files
|
15
|
+
# Explicitly set the Time this result has been created
|
16
|
+
attr_writer :created_at
|
17
|
+
# Explicitly set the command name that was used for this coverage result. Defaults to SimpleCov.command_name
|
18
|
+
attr_writer :command_name
|
9
19
|
|
20
|
+
# Initialize a new SimpleCov::Result from given Coverage.result (a Hash of filenames each containing an array of
|
21
|
+
# coverage data)
|
10
22
|
def initialize(original_result)
|
11
23
|
@original_result = original_result.freeze
|
12
24
|
@files = original_result.map {|filename, coverage| SimpleCov::SourceFile.new(filename, coverage)}.sort_by(&:filename)
|
13
25
|
filter!
|
14
26
|
end
|
15
27
|
|
28
|
+
# Returns all filenames for source files contained in this result
|
16
29
|
def filenames
|
17
30
|
files.map(&:filename)
|
18
31
|
end
|
19
32
|
|
33
|
+
# Returns a Hash of groups for this result. Define groups using SimpleCov.add_group 'Models', 'app/models'
|
20
34
|
def groups
|
21
35
|
@groups ||= SimpleCov.grouped(files)
|
22
36
|
end
|
23
37
|
|
38
|
+
# The overall percentual coverage for this result
|
39
|
+
#
|
40
|
+
# FIXME: Kind of inaccurate - should use LOC instead of Files count!
|
24
41
|
def covered_percent
|
25
42
|
files.map(&:covered_percent).inject(:+) / files.count.to_f
|
26
43
|
end
|
27
44
|
|
45
|
+
# Applies the configured SimpleCov.formatter on this result
|
28
46
|
def format!
|
29
47
|
SimpleCov.formatter.new.format(self)
|
30
48
|
end
|
31
49
|
|
32
|
-
# Defines when this result has been created
|
50
|
+
# Defines when this result has been created. Defaults to Time.now
|
33
51
|
def created_at
|
34
52
|
@created_at ||= Time.now
|
35
53
|
end
|
36
54
|
|
37
|
-
# The command name that launched this result.
|
55
|
+
# The command name that launched this result.
|
38
56
|
# Retrieved from SimpleCov.command_name
|
39
57
|
def command_name
|
40
58
|
@command_name ||= SimpleCov.command_name
|
41
59
|
end
|
42
60
|
|
43
|
-
# Returns a hash representation of this Result
|
61
|
+
# Returns a hash representation of this Result that can be used for marshalling it into YAML
|
44
62
|
def to_hash
|
45
63
|
{command_name => {:original_result => original_result.reject {|filename, result| !filenames.include?(filename) }, :created_at => created_at}}
|
46
64
|
end
|
@@ -66,6 +84,7 @@ module SimpleCov
|
|
66
84
|
|
67
85
|
private
|
68
86
|
|
87
|
+
# Applies all configured SimpleCov filters on this result's source files
|
69
88
|
def filter!
|
70
89
|
@files = SimpleCov.filtered(files)
|
71
90
|
end
|
@@ -1,15 +1,26 @@
|
|
1
1
|
require 'yaml'
|
2
|
+
#
|
3
|
+
# Singleton that is responsible for caching, loading and merging
|
4
|
+
# SimpleCov::Results into a single result for coverage analysis based
|
5
|
+
# upon multiple test suites.
|
6
|
+
#
|
2
7
|
module SimpleCov::ResultMerger
|
3
8
|
class << self
|
9
|
+
# The path to the resultset.yml cache file
|
4
10
|
def resultset_path
|
5
11
|
File.join(SimpleCov.coverage_path, 'resultset.yml')
|
6
12
|
end
|
7
13
|
|
14
|
+
# Loads the cached resultset from YAML and returns it as a Hash
|
8
15
|
def resultset
|
9
16
|
return {} unless File.exist?(resultset_path)
|
10
17
|
YAML.load(File.read(resultset_path))
|
11
18
|
end
|
12
19
|
|
20
|
+
# Gets the resultset hash and re-creates all included instances
|
21
|
+
# of SimpleCov::Result from that.
|
22
|
+
# All results that are above the SimpleCov.merge_timeout will be
|
23
|
+
# dropped. Returns an array of SimpleCov::Result items.
|
13
24
|
def results
|
14
25
|
results = []
|
15
26
|
resultset.each do |command_name, data|
|
@@ -22,6 +33,11 @@ module SimpleCov::ResultMerger
|
|
22
33
|
results
|
23
34
|
end
|
24
35
|
|
36
|
+
#
|
37
|
+
# Gets all SimpleCov::Results from cache, merges them and produces a new
|
38
|
+
# SimpleCov::Result with merged coverage data and the command_name
|
39
|
+
# for the result consisting of a join on all source result's names
|
40
|
+
#
|
25
41
|
def merged_result
|
26
42
|
merged = {}
|
27
43
|
results.each do |result|
|
@@ -33,6 +49,7 @@ module SimpleCov::ResultMerger
|
|
33
49
|
result
|
34
50
|
end
|
35
51
|
|
52
|
+
# Saves the given SimpleCov::Result in the resultset cache
|
36
53
|
def store_result(result)
|
37
54
|
new_set = resultset
|
38
55
|
command_name, data = result.to_hash.first
|
@@ -1,4 +1,8 @@
|
|
1
1
|
module SimpleCov
|
2
|
+
#
|
3
|
+
# Representation of a source file including it's coverage data, source code,
|
4
|
+
# source lines and featuring helpers to interpret that data.
|
5
|
+
#
|
2
6
|
class SourceFile
|
3
7
|
# Representation of a single line in a source file including
|
4
8
|
# this specific line's source code, line_number and code coverage,
|
@@ -6,7 +10,12 @@ module SimpleCov
|
|
6
10
|
# line), 0 (line not covered) or >1 (the amount of times the line was
|
7
11
|
# executed)
|
8
12
|
class Line
|
9
|
-
|
13
|
+
# The source code for this line. Aliased as :source
|
14
|
+
attr_reader :src
|
15
|
+
# The line number in the source file. Aliased as :line, :number
|
16
|
+
attr_reader :line_number
|
17
|
+
# The coverage data for this line: either nil (never), 0 (missed) or >=1 (times covered)
|
18
|
+
attr_reader :coverage
|
10
19
|
# Lets grab some fancy aliases, shall we?
|
11
20
|
alias_method :source, :src
|
12
21
|
alias_method :line, :line_number
|
@@ -19,48 +28,71 @@ module SimpleCov
|
|
19
28
|
@src, @line_number, @coverage = src, line_number, coverage
|
20
29
|
end
|
21
30
|
|
31
|
+
# Returns true if this is a line that should have been covered, but was not
|
22
32
|
def missed?
|
23
33
|
not never? and coverage == 0
|
24
34
|
end
|
25
35
|
|
36
|
+
# Returns true if this is a line that has been covered
|
26
37
|
def covered?
|
27
38
|
not never? and coverage > 0
|
28
39
|
end
|
29
40
|
|
41
|
+
# Returns true if this line is not relevant for coverage
|
30
42
|
def never?
|
31
43
|
coverage.nil?
|
32
44
|
end
|
33
45
|
end
|
34
46
|
|
35
|
-
|
47
|
+
# The full path to this source file (e.g. /User/colszowka/projects/simplecov/lib/simplecov/source_file.rb)
|
48
|
+
attr_reader :filename
|
49
|
+
# The array of coverage data received from the Coverage.result
|
50
|
+
attr_reader :coverage
|
51
|
+
# The source code for this file. Aliased as :source
|
52
|
+
attr_reader :src
|
36
53
|
alias_method :source, :src
|
37
|
-
alias_method :source_lines, :lines
|
38
54
|
|
39
55
|
def initialize(filename, coverage)
|
40
56
|
@filename, @coverage, @src = filename, coverage, File.readlines(filename)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns all source lines for this file as instances of SimpleCov::SourceFile::Line,
|
60
|
+
# and thus including coverage data. Aliased as :source_lines
|
61
|
+
def lines
|
62
|
+
return @lines unless @lines.nil?
|
63
|
+
# Initialize lines
|
41
64
|
@lines = []
|
42
65
|
coverage.each_with_index do |coverage, i|
|
43
66
|
@lines << SimpleCov::SourceFile::Line.new(src[i], i+1, coverage)
|
44
67
|
end
|
68
|
+
@lines
|
45
69
|
end
|
70
|
+
alias_method :source_lines, :lines
|
46
71
|
|
72
|
+
# Access SimpleCov::SourceFile::Line source lines by line number
|
47
73
|
def line(number)
|
48
74
|
lines[number-1]
|
49
75
|
end
|
50
76
|
|
77
|
+
# The coverage for this file in percent. 0 if the file has no relevant lines
|
51
78
|
def covered_percent
|
52
79
|
return 100.0 if lines.length == 0 or lines.length == never_lines.count
|
53
80
|
(covered_lines.count) * 100 / (lines.count-never_lines.count).to_f
|
54
81
|
end
|
55
82
|
|
83
|
+
# Returns all covered lines as SimpleCov::SourceFile::Line
|
56
84
|
def covered_lines
|
57
85
|
@covered_lines ||= lines.select {|c| c.covered? }
|
58
86
|
end
|
59
87
|
|
88
|
+
# Returns all lines that should have been, but were not covered
|
89
|
+
# as instances of SimpleCov::SourceFile::Line
|
60
90
|
def missed_lines
|
61
91
|
@missed_lines ||= lines.select {|c| c.missed? }
|
62
92
|
end
|
63
93
|
|
94
|
+
# Returns all lines that are not relevant for coverage as
|
95
|
+
# SimpleCov::SourceFile::Line instances
|
64
96
|
def never_lines
|
65
97
|
@never_lines ||= lines.select {|c| c.never? }
|
66
98
|
end
|
data/simplecov.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{simplecov}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Christoph Olszowka"]
|
12
|
-
s.date = %q{2010-08-
|
12
|
+
s.date = %q{2010-08-23}
|
13
13
|
s.description = %q{Code coverage for Ruby 1.9}
|
14
14
|
s.email = %q{christoph at olszowka.de}
|
15
15
|
s.extra_rdoc_files = [
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 1
|
9
|
+
version: 0.3.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Christoph Olszowka
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-08-
|
17
|
+
date: 2010-08-23 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|