simplecov 0.3.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.
- data/.document +5 -0
- data/.gitignore +24 -0
- data/LICENSE +20 -0
- data/README.rdoc +43 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/simplecov.rb +107 -0
- data/lib/simplecov/adapters.rb +47 -0
- data/lib/simplecov/configuration.rb +174 -0
- data/lib/simplecov/filter.rb +35 -0
- data/lib/simplecov/formatter.rb +7 -0
- data/lib/simplecov/formatter/simple_formatter.rb +15 -0
- data/lib/simplecov/merge_helpers.rb +37 -0
- data/lib/simplecov/result.rb +73 -0
- data/lib/simplecov/result_merger.rb +46 -0
- data/lib/simplecov/source_file.rb +68 -0
- data/simple_cov.gemspec +81 -0
- data/simplecov.gemspec +82 -0
- data/test/fixtures/app/controllers/sample_controller.rb +10 -0
- data/test/fixtures/app/models/user.rb +10 -0
- data/test/fixtures/resultset1.rb +4 -0
- data/test/fixtures/resultset2.rb +5 -0
- data/test/fixtures/sample.rb +10 -0
- data/test/helper.rb +14 -0
- data/test/test_filters.rb +73 -0
- data/test/test_merge_helpers.rb +92 -0
- data/test/test_result.rb +133 -0
- data/test/test_source_file.rb +49 -0
- data/test/test_source_file_line.rb +110 -0
- metadata +117 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Christoph Olszowka
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
= simplecov
|
2
|
+
|
3
|
+
SimpleCov is a code coverage analysis tool for Ruby 1.9. It makes use of Ruby's built-in Coverage library, wrapping
|
4
|
+
it's results in a object-oriented manner. It also adds some sugar like filtering (so the coverage of used gems is not
|
5
|
+
taken into account) and grouping (to check coverage on your Rails models for instance).
|
6
|
+
|
7
|
+
Though it ships with a basic formatter, it isn't particularily useful by itself, so you're going to need a dedicated
|
8
|
+
formatter library - check out simple_cov-html for that!
|
9
|
+
|
10
|
+
Thanks to Aaron Patterson (http://engineering.attinteractive.com/2010/08/code-coverage-in-ruby-1-9/) for the original idea
|
11
|
+
for this!
|
12
|
+
|
13
|
+
== Example config for Rails 3 (using HTML formatter)
|
14
|
+
|
15
|
+
Update your Gemfile with this and do a bundle install:
|
16
|
+
group :test do
|
17
|
+
gem 'simplecov', '>= 0.2.0'
|
18
|
+
gem 'simplecov-html', '>= 0.2.0'
|
19
|
+
end
|
20
|
+
|
21
|
+
Then, add the following to your Rails test/test_helper.rb (right at the top, line 00):
|
22
|
+
|
23
|
+
require 'simple_cov'
|
24
|
+
SimpleCov.start 'rails'
|
25
|
+
|
26
|
+
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
|
+
== TODO
|
29
|
+
* Improve on tests (integration tests)
|
30
|
+
|
31
|
+
== Note on Patches/Pull Requests
|
32
|
+
|
33
|
+
* Fork the project.
|
34
|
+
* Make your feature addition or bug fix.
|
35
|
+
* Add tests for it. This is important so I don't break it in a
|
36
|
+
future version unintentionally.
|
37
|
+
* Commit, do not mess with rakefile, version, or history.
|
38
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
39
|
+
* Send me a pull request. Bonus points for topic branches.
|
40
|
+
|
41
|
+
== Copyright
|
42
|
+
|
43
|
+
Copyright (c) 2010 Christoph Olszowka. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "simplecov"
|
8
|
+
gem.summary = %Q{Code coverage for Ruby 1.9}
|
9
|
+
gem.description = %Q{Code coverage for Ruby 1.9}
|
10
|
+
gem.email = "christoph at olszowka.de"
|
11
|
+
gem.homepage = "http://github.com/colszowka/simplecov"
|
12
|
+
gem.authors = ["Christoph Olszowka"]
|
13
|
+
gem.add_development_dependency "shoulda", "= 2.10.3"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
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
|
+
task :test => :check_dependencies
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "simplecov #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.0
|
data/lib/simplecov.rb
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
module SimpleCov
|
2
|
+
class CoverageDataError < StandardError; end;
|
3
|
+
VERSION = File.read(File.join(File.dirname(__FILE__), '../VERSION'))
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :running, :result # TODO: Remove result?
|
7
|
+
|
8
|
+
#
|
9
|
+
# Sets up SimpleCov to run against your project.
|
10
|
+
#
|
11
|
+
# TODO: Explain config! Add default adapters!
|
12
|
+
#
|
13
|
+
def start(adapter=nil, &block)
|
14
|
+
unless "1.9".respond_to?(:encoding)
|
15
|
+
warn "WARNING: SimpleCov is activated, but you're not running Ruby 1.9 - no coverage analysis will happen"
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
require 'coverage'
|
19
|
+
load_adapter(adapter) unless adapter.nil?
|
20
|
+
Coverage.start
|
21
|
+
configure(&block) if block_given?
|
22
|
+
@result = nil
|
23
|
+
self.running = true
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Returns the result for the currntly runnig coverage run
|
28
|
+
#
|
29
|
+
def result
|
30
|
+
@result ||= SimpleCov::Result.new(Coverage.result) if running
|
31
|
+
# If we're using merging of results, store the current result
|
32
|
+
# first, then merge the results and return them
|
33
|
+
if use_merging
|
34
|
+
SimpleCov::ResultMerger.store_result(@result) if @result
|
35
|
+
return SimpleCov::ResultMerger.merged_result
|
36
|
+
else
|
37
|
+
return @result
|
38
|
+
end
|
39
|
+
ensure
|
40
|
+
self.running = false
|
41
|
+
end
|
42
|
+
|
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
|
+
#
|
52
|
+
# Applies the configured filters to the given array of SimpleCov::SourceFile items
|
53
|
+
#
|
54
|
+
def filtered(files)
|
55
|
+
result = files.clone
|
56
|
+
filters.each do |filter|
|
57
|
+
result = result.select {|source_file| filter.passes?(source_file) }
|
58
|
+
end
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Applies the configured groups to the given array of SimpleCov::SourceFile items
|
64
|
+
#
|
65
|
+
def grouped(files)
|
66
|
+
grouped = {}
|
67
|
+
grouped_files = []
|
68
|
+
groups.each do |name, filter|
|
69
|
+
grouped[name] = files.select {|source_file| !filter.passes?(source_file)}
|
70
|
+
grouped_files += grouped[name]
|
71
|
+
end
|
72
|
+
if groups.length > 0 and (other_files = files.reject {|source_file| grouped_files.include?(source_file)}).length > 0
|
73
|
+
grouped["Ungrouped"] = other_files
|
74
|
+
end
|
75
|
+
grouped
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Applies the adapter of given name on SimpleCov configuration
|
80
|
+
#
|
81
|
+
def load_adapter(name)
|
82
|
+
adapters.load(name)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
|
88
|
+
require 'simplecov/configuration'
|
89
|
+
SimpleCov.send :extend, SimpleCov::Configuration
|
90
|
+
require 'simplecov/adapters'
|
91
|
+
require 'simplecov/source_file'
|
92
|
+
require 'simplecov/result'
|
93
|
+
require 'simplecov/filter'
|
94
|
+
require 'simplecov/formatter'
|
95
|
+
require 'simplecov/merge_helpers'
|
96
|
+
require 'simplecov/result_merger'
|
97
|
+
|
98
|
+
# Default configuration
|
99
|
+
SimpleCov.configure do
|
100
|
+
formatter SimpleCov::Formatter::SimpleFormatter
|
101
|
+
# Exclude files outside of SimpleCov.root
|
102
|
+
load_adapter 'root_filter'
|
103
|
+
end
|
104
|
+
|
105
|
+
at_exit do
|
106
|
+
SimpleCov.at_exit.call
|
107
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#
|
2
|
+
# Adaptars are glorified SimpleCov configuration procs that can be easily
|
3
|
+
# loaded using SimpleCov.start :rails and defined using
|
4
|
+
# SimpleCov.adapters.define :foo do
|
5
|
+
# # SimpleCov configuration here, same as in
|
6
|
+
# end
|
7
|
+
#
|
8
|
+
class SimpleCov::Adapters < Hash
|
9
|
+
#
|
10
|
+
# Define a SimpleCov adapter:
|
11
|
+
# SimpleCov.adapters.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 Adapter '#{name}' is already defined" unless self[name].nil?
|
18
|
+
self[name] = blk
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Applies the adapter of given name
|
23
|
+
#
|
24
|
+
def load(name)
|
25
|
+
name = name.to_sym
|
26
|
+
raise "Could not find SimpleCov Adapter called '#{name}'" unless has_key?(name)
|
27
|
+
SimpleCov.configure(&self[name])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
SimpleCov.adapters.define 'root_filter' do
|
32
|
+
# Exclude all files outside of simplecov root
|
33
|
+
add_filter do |src|
|
34
|
+
!(src.filename =~ /^#{SimpleCov.root}/)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
SimpleCov.adapters.define 'rails' do
|
39
|
+
add_filter '/test/'
|
40
|
+
add_filter '/config/'
|
41
|
+
|
42
|
+
add_group 'Controllers', 'app/controllers'
|
43
|
+
add_group 'Models', 'app/models'
|
44
|
+
add_group 'Helpers', 'app/helpers'
|
45
|
+
add_group 'Libraries', 'lib'
|
46
|
+
add_group 'Plugins', 'vendor/plugins'
|
47
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
#
|
2
|
+
# Bundles the configuration options used for SimpleCov. All methods
|
3
|
+
# defined here are usable from SimpleCov directly. Please check out
|
4
|
+
# SimpleCov documentation for further info.
|
5
|
+
#
|
6
|
+
module SimpleCov::Configuration
|
7
|
+
attr_writer :filters, :groups, :formatter
|
8
|
+
|
9
|
+
#
|
10
|
+
# The root for the project. This defaults to the
|
11
|
+
# current working directory.
|
12
|
+
#
|
13
|
+
# Configure with SimpleCov.root('/my/project/path')
|
14
|
+
#
|
15
|
+
def root(root=nil)
|
16
|
+
return @root if @root and root.nil?
|
17
|
+
@root = File.expand_path(root || Dir.getwd)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# The name of the output and cache directory. Defaults to 'coverage'
|
22
|
+
#
|
23
|
+
# Configure with SimpleCov.coverage_dir('cov')
|
24
|
+
#
|
25
|
+
def coverage_dir(dir=nil)
|
26
|
+
return @coverage_dir if @coverage_dir and dir.nil?
|
27
|
+
@coverage_dir = (dir || 'coverage')
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Returns the full path to the output directory using SimpleCov.root
|
32
|
+
# and SimpleCov.coverage_dir, so you can adjust this by configuring those
|
33
|
+
# values. Will create the directory if it's missing
|
34
|
+
#
|
35
|
+
def coverage_path
|
36
|
+
coverage_path = File.join(root, coverage_dir)
|
37
|
+
system "mkdir -p '#{coverage_path}'"
|
38
|
+
coverage_path
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Returns the list of configured filters. Add filters using SimpleCov.add_filter.
|
43
|
+
#
|
44
|
+
def filters
|
45
|
+
@filters ||= []
|
46
|
+
end
|
47
|
+
|
48
|
+
# The name of the command currently running. It is used for result merging and defaults
|
49
|
+
# to the command line arguments the current test suite is running on.
|
50
|
+
# You can specify it manually with SimpleCov.command_name("test:units")
|
51
|
+
def command_name(name=nil)
|
52
|
+
@name ||= (name.nil? ? ARGV.join(" ") : name)
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Gets or sets the configured formatter.
|
57
|
+
#
|
58
|
+
# Configure with: SimpleCov.formatter(SimpleCov::Formatter::SimpleFormatter)
|
59
|
+
#
|
60
|
+
def formatter(formatter=nil)
|
61
|
+
return @formatter if @formatter and formatter.nil?
|
62
|
+
@formatter = formatter
|
63
|
+
raise "No formatter configured. Please specify a formatter using SimpleCov.formatter = SimpleCov::Formatter::SimpleFormatter" unless @formatter
|
64
|
+
@formatter
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Returns the configured groups. Add groups using SimpleCov.add_group
|
69
|
+
#
|
70
|
+
def groups
|
71
|
+
@groups ||= {}
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Returns the hash of available adapters
|
76
|
+
#
|
77
|
+
def adapters
|
78
|
+
@adapters ||= SimpleCov::Adapters.new
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Configure SimpleCov using a block:
|
83
|
+
#
|
84
|
+
# SimpleCov.configure do
|
85
|
+
# add_filter 'foobar'
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# This is equivalent to SimpleCov.add_filter 'foobar' and thus makes it easier to set a lot of configure
|
89
|
+
# options.
|
90
|
+
#
|
91
|
+
def configure(&block)
|
92
|
+
instance_exec(&block)
|
93
|
+
end
|
94
|
+
|
95
|
+
#
|
96
|
+
# Gets or sets the behavior to process coverage results.
|
97
|
+
#
|
98
|
+
# By default, it will call SimpleCov.result.format!
|
99
|
+
#
|
100
|
+
# Configure with:
|
101
|
+
# SimpleCov.at_exit do
|
102
|
+
# puts "Coverage done"
|
103
|
+
# SimpleCov.result.format!
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
def at_exit(&block)
|
107
|
+
return Proc.new {} unless running or block_given?
|
108
|
+
@at_exit = block if block_given?
|
109
|
+
@at_exit ||= Proc.new { SimpleCov.result.format! }
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Defines whether to use result merging so all your test suites (test:units, test:functionals, cucumber, ...)
|
114
|
+
# are joined and combined into a single coverage report
|
115
|
+
#
|
116
|
+
def use_merging(use=nil)
|
117
|
+
@use_merging = use unless use.nil? # Set if param given
|
118
|
+
@use_merging = true if @use_merging != false
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# Defines them maximum age (in seconds) of a resultset to still be included in merged results.
|
123
|
+
# i.e. If you run cucumber features, then later rake test, if the stored cucumber resultset is
|
124
|
+
# more seconds ago than specified here, it won't be taken into account when merging (and is also
|
125
|
+
# purged from the resultset cache)
|
126
|
+
#
|
127
|
+
# Of course, this only applies when merging is active (e.g. SimpleCov.use_merging is not false!)
|
128
|
+
#
|
129
|
+
# Default is 600 seconds (10 minutes)
|
130
|
+
#
|
131
|
+
# Configure with SimpleCov.merge_timeout(3600) # 1hr
|
132
|
+
#
|
133
|
+
def merge_timeout(seconds=nil)
|
134
|
+
@merge_timeout = seconds if !seconds.nil? and seconds.kind_of?(Fixnum)
|
135
|
+
@merge_timeout ||= 600
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Add a filter to the processing chain.
|
140
|
+
# There are three ways to define a filter:
|
141
|
+
#
|
142
|
+
# * as a String that will then be matched against all source files' file paths,
|
143
|
+
# SimpleCov.add_filter 'app/models' # will reject all your models
|
144
|
+
# * as a block which will be passed the source file in question and should either
|
145
|
+
# return a true or false value, depending on whether the file should be removed
|
146
|
+
# SimpleCov.add_filter do |src_file|
|
147
|
+
# File.basename(src_file.filename) == 'environment.rb'
|
148
|
+
# end # Will exclude environment.rb files from the results
|
149
|
+
# * as an instance of a subclass of SimpleCov::Filter. See the documentation there
|
150
|
+
# on how to define your own filter classes
|
151
|
+
#
|
152
|
+
def add_filter(filter_argument=nil, &filter_proc)
|
153
|
+
filters << parse_filter(filter_argument, &filter_proc)
|
154
|
+
end
|
155
|
+
|
156
|
+
def add_group(group_name, filter_argument=nil, &filter_proc)
|
157
|
+
groups[group_name] = parse_filter(filter_argument, &filter_proc)
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# The actal filter processor. Not meant for direct use
|
162
|
+
#
|
163
|
+
def parse_filter(filter_argument=nil, &filter_proc)
|
164
|
+
if filter_argument.kind_of?(SimpleCov::Filter)
|
165
|
+
filter_argument
|
166
|
+
elsif filter_argument.kind_of?(String)
|
167
|
+
SimpleCov::StringFilter.new(filter_argument)
|
168
|
+
elsif filter_proc
|
169
|
+
SimpleCov::BlockFilter.new(filter_proc)
|
170
|
+
else
|
171
|
+
raise ArgumentError, "Please specify either a string or a block to filter with"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|