simplecov 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|