simplecov 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ .rvmrc
2
+ .bundle
3
+
4
+ ## MAC OS
5
+ .DS_Store
6
+
7
+ ## TEXTMATE
8
+ *.tmproj
9
+ tmtags
10
+
11
+ ## EMACS
12
+ *~
13
+ \#*
14
+ .\#*
15
+
16
+ ## VIM
17
+ *.swp
18
+
19
+ ## PROJECT::GENERAL
20
+ coverage
21
+ rdoc
22
+ pkg
23
+
24
+ ## PROJECT::SPECIFIC
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