gigpark-rcov 0.8.6
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/BLURB +111 -0
- data/LICENSE +53 -0
- data/Rakefile +78 -0
- data/THANKS +96 -0
- data/bin/rcov +508 -0
- data/doc/readme_for_api.markdown +22 -0
- data/doc/readme_for_emacs.markdown +52 -0
- data/doc/readme_for_rake.markdown +51 -0
- data/doc/readme_for_vim.markdown +34 -0
- data/editor-extensions/rcov.el +131 -0
- data/editor-extensions/rcov.vim +38 -0
- data/ext/rcovrt/1.8/callsite.c +216 -0
- data/ext/rcovrt/1.8/rcovrt.c +287 -0
- data/ext/rcovrt/1.9/callsite.c +234 -0
- data/ext/rcovrt/1.9/rcovrt.c +264 -0
- data/ext/rcovrt/extconf.rb +21 -0
- data/lib/rcov.rb +33 -0
- data/lib/rcov/call_site_analyzer.rb +225 -0
- data/lib/rcov/code_coverage_analyzer.rb +268 -0
- data/lib/rcov/coverage_info.rb +36 -0
- data/lib/rcov/differential_analyzer.rb +116 -0
- data/lib/rcov/file_statistics.rb +334 -0
- data/lib/rcov/formatters.rb +13 -0
- data/lib/rcov/formatters/base_formatter.rb +168 -0
- data/lib/rcov/formatters/failure_report.rb +15 -0
- data/lib/rcov/formatters/full_text_report.rb +48 -0
- data/lib/rcov/formatters/html_coverage.rb +244 -0
- data/lib/rcov/formatters/html_erb_template.rb +45 -0
- data/lib/rcov/formatters/text_coverage_diff.rb +193 -0
- data/lib/rcov/formatters/text_report.rb +32 -0
- data/lib/rcov/formatters/text_summary.rb +11 -0
- data/lib/rcov/lowlevel.rb +146 -0
- data/lib/rcov/rcovtask.rb +155 -0
- data/lib/rcov/templates/detail.html.erb +78 -0
- data/lib/rcov/templates/index.html.erb +76 -0
- data/lib/rcov/templates/screen.css +168 -0
- data/lib/rcov/version.rb +10 -0
- data/setup.rb +1588 -0
- data/test/assets/sample_01.rb +7 -0
- data/test/assets/sample_02.rb +5 -0
- data/test/assets/sample_03.rb +20 -0
- data/test/assets/sample_04.rb +10 -0
- data/test/assets/sample_05-new.rb +17 -0
- data/test/assets/sample_05-old.rb +13 -0
- data/test/assets/sample_05.rb +17 -0
- data/test/call_site_analyzer_test.rb +171 -0
- data/test/code_coverage_analyzer_test.rb +184 -0
- data/test/file_statistics_test.rb +471 -0
- data/test/functional_test.rb +89 -0
- data/test/turn_off_rcovrt.rb +4 -0
- metadata +109 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
module Rcov
|
2
|
+
module Formatters
|
3
|
+
class HtmlErbTemplate
|
4
|
+
attr_accessor :local_variables
|
5
|
+
|
6
|
+
def initialize(template_file, locals={})
|
7
|
+
require "erb"
|
8
|
+
|
9
|
+
template_path = File.expand_path("#{File.dirname(__FILE__)}/../templates/#{template_file}")
|
10
|
+
@template = ERB.new(File.read(template_path))
|
11
|
+
@local_variables = locals
|
12
|
+
@path_relativizer = Hash.new{|h,base|
|
13
|
+
h[base] = Pathname.new(base).cleanpath.to_s.gsub(%r{^\w:[/\\]}, "").gsub(/\./, "_").gsub(/[\\\/]/, "-") + ".html"
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
def render
|
18
|
+
@template.result(get_binding)
|
19
|
+
end
|
20
|
+
|
21
|
+
def relative_filename(path)
|
22
|
+
@path_relativizer[path]
|
23
|
+
end
|
24
|
+
|
25
|
+
def line_css(line_number)
|
26
|
+
case fileinfo.coverage[line_number]
|
27
|
+
when true
|
28
|
+
"marked"
|
29
|
+
when :inferred
|
30
|
+
"inferred"
|
31
|
+
else
|
32
|
+
"uncovered"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(key, *args)
|
37
|
+
local_variables.has_key?(key) ? local_variables[key] : super
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_binding
|
41
|
+
binding
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
module Rcov
|
2
|
+
class TextCoverageDiff < BaseFormatter # :nodoc:
|
3
|
+
FORMAT_VERSION = [0, 1, 0]
|
4
|
+
DEFAULT_OPTS = { :textmode => :coverage_diff, :coverage_diff_mode => :record,
|
5
|
+
:coverage_diff_file => "coverage.info", :diff_cmd => "diff",
|
6
|
+
:comments_run_by_default => true }
|
7
|
+
HUNK_HEADER = /@@ -\d+,\d+ \+(\d+),(\d+) @@/
|
8
|
+
|
9
|
+
def SERIALIZER
|
10
|
+
# mfp> this was going to be YAML but I caught it failing at basic
|
11
|
+
# round-tripping, turning "\n" into "" and corrupting the data, so
|
12
|
+
# it must be Marshal for now
|
13
|
+
Marshal
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(opts = {})
|
17
|
+
options = DEFAULT_OPTS.clone.update(opts)
|
18
|
+
@textmode = options[:textmode]
|
19
|
+
@color = options[:color]
|
20
|
+
@mode = options[:coverage_diff_mode]
|
21
|
+
@state_file = options[:coverage_diff_file]
|
22
|
+
@diff_cmd = options[:diff_cmd]
|
23
|
+
@gcc_output = options[:gcc_output]
|
24
|
+
super(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def execute
|
28
|
+
case @mode
|
29
|
+
when :record
|
30
|
+
record_state
|
31
|
+
when :compare
|
32
|
+
compare_state
|
33
|
+
else
|
34
|
+
raise "Unknown TextCoverageDiff mode: #{mode.inspect}."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def record_state
|
39
|
+
state = {}
|
40
|
+
each_file_pair_sorted do |filename, fileinfo|
|
41
|
+
state[filename] = {:lines => SCRIPT_LINES__[filename], :coverage => fileinfo.coverage.to_a,:counts => fileinfo.counts}
|
42
|
+
end
|
43
|
+
File.open(@state_file, "w") do |f|
|
44
|
+
self.SERIALIZER.dump([FORMAT_VERSION, state], f)
|
45
|
+
end
|
46
|
+
rescue
|
47
|
+
$stderr.puts <<-EOF
|
48
|
+
Couldn't save coverage data to #{@state_file}.
|
49
|
+
EOF
|
50
|
+
end # '
|
51
|
+
|
52
|
+
require 'tempfile'
|
53
|
+
def compare_state
|
54
|
+
return unless verify_diff_available
|
55
|
+
begin
|
56
|
+
format, prev_state = File.open(@state_file){|f| self.SERIALIZER.load(f) }
|
57
|
+
rescue
|
58
|
+
$stderr.puts <<-EOF
|
59
|
+
Couldn't load coverage data from #{@state_file}.
|
60
|
+
EOF
|
61
|
+
return # '
|
62
|
+
end
|
63
|
+
if !(Array === format) or
|
64
|
+
FORMAT_VERSION[0] != format[0] || FORMAT_VERSION[1] < format[1]
|
65
|
+
$stderr.puts <<-EOF
|
66
|
+
Couldn't load coverage data from #{@state_file}.
|
67
|
+
The file is saved in the format #{format.inspect[0..20]}.
|
68
|
+
This rcov executable understands #{FORMAT_VERSION.inspect}.
|
69
|
+
EOF
|
70
|
+
return # '
|
71
|
+
end
|
72
|
+
each_file_pair_sorted do |filename, fileinfo|
|
73
|
+
old_data = Tempfile.new("#{mangle_filename(filename)}-old")
|
74
|
+
new_data = Tempfile.new("#{mangle_filename(filename)}-new")
|
75
|
+
if prev_state.has_key? filename
|
76
|
+
old_code, old_cov = prev_state[filename].values_at(:lines, :coverage)
|
77
|
+
old_code.each_with_index do |line, i|
|
78
|
+
prefix = old_cov[i] ? " " : "!! "
|
79
|
+
old_data.write "#{prefix}#{line}"
|
80
|
+
end
|
81
|
+
else
|
82
|
+
old_data.write ""
|
83
|
+
end
|
84
|
+
old_data.close
|
85
|
+
SCRIPT_LINES__[filename].each_with_index do |line, i|
|
86
|
+
prefix = fileinfo.coverage[i] ? " " : "!! "
|
87
|
+
new_data.write "#{prefix}#{line}"
|
88
|
+
end
|
89
|
+
new_data.close
|
90
|
+
|
91
|
+
diff = `#{@diff_cmd} -u "#{old_data.path}" "#{new_data.path}"`
|
92
|
+
new_uncovered_hunks = process_unified_diff(filename, diff)
|
93
|
+
old_data.close!
|
94
|
+
new_data.close!
|
95
|
+
display_hunks(filename, new_uncovered_hunks)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def display_hunks(filename, hunks)
|
100
|
+
return if hunks.empty?
|
101
|
+
puts
|
102
|
+
puts "=" * 80
|
103
|
+
puts "!!!!! Uncovered code introduced in #{filename}"
|
104
|
+
|
105
|
+
hunks.each do |offset, lines|
|
106
|
+
if @gcc_output
|
107
|
+
lines.each_with_index do |line,i|
|
108
|
+
lineno = offset + i
|
109
|
+
flag = (/^!! / !~ line) ? "-" : ":"
|
110
|
+
prefix = "#{filename}#{flag}#{lineno}#{flag}"
|
111
|
+
puts "#{prefix}#{line[3..-1]}"
|
112
|
+
end
|
113
|
+
elsif @color
|
114
|
+
puts "### #{filename}:#{offset}"
|
115
|
+
lines.each do |line|
|
116
|
+
prefix = (/^!! / !~ line) ? "\e[32;40m" : "\e[31;40m"
|
117
|
+
puts "#{prefix}#{line[3..-1].chomp}\e[37;40m"
|
118
|
+
end
|
119
|
+
else
|
120
|
+
puts "### #{filename}:#{offset}"
|
121
|
+
puts lines
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def verify_diff_available
|
127
|
+
old_stderr = STDERR.dup
|
128
|
+
old_stdout = STDOUT.dup
|
129
|
+
new_stderr = Tempfile.new("rcov_check_diff")
|
130
|
+
STDERR.reopen new_stderr.path
|
131
|
+
STDOUT.reopen new_stderr.path
|
132
|
+
|
133
|
+
retval = system "#{@diff_cmd} --version"
|
134
|
+
unless retval
|
135
|
+
old_stderr.puts <<EOF
|
136
|
+
The '#{@diff_cmd}' executable seems not to be available.
|
137
|
+
You can specify which diff executable should be used with --diff-cmd.
|
138
|
+
If your system doesn't have one, you might want to use Diff::LCS's:
|
139
|
+
gem install diff-lcs
|
140
|
+
and use --diff-cmd=ldiff.
|
141
|
+
EOF
|
142
|
+
return false
|
143
|
+
end
|
144
|
+
true
|
145
|
+
ensure
|
146
|
+
STDOUT.reopen old_stdout
|
147
|
+
STDERR.reopen old_stderr
|
148
|
+
new_stderr.close!
|
149
|
+
end
|
150
|
+
|
151
|
+
def process_unified_diff(filename, diff)
|
152
|
+
current_hunk = []
|
153
|
+
current_hunk_start = 0
|
154
|
+
keep_current_hunk = false
|
155
|
+
state = :init
|
156
|
+
interesting_hunks = []
|
157
|
+
diff.each_with_index do |line, i|
|
158
|
+
#puts "#{state} %5d #{line}" % i
|
159
|
+
case state
|
160
|
+
when :init
|
161
|
+
if md = HUNK_HEADER.match(line)
|
162
|
+
current_hunk = []
|
163
|
+
current_hunk_start = md[1].to_i
|
164
|
+
state = :body
|
165
|
+
end
|
166
|
+
when :body
|
167
|
+
case line
|
168
|
+
when HUNK_HEADER
|
169
|
+
new_start = $1.to_i
|
170
|
+
if keep_current_hunk
|
171
|
+
interesting_hunks << [current_hunk_start, current_hunk]
|
172
|
+
end
|
173
|
+
current_hunk_start = new_start
|
174
|
+
current_hunk = []
|
175
|
+
keep_current_hunk = false
|
176
|
+
when /^-/
|
177
|
+
# ignore
|
178
|
+
when /^\+!! /
|
179
|
+
keep_current_hunk = true
|
180
|
+
current_hunk << line[1..-1]
|
181
|
+
else
|
182
|
+
current_hunk << line[1..-1]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
if keep_current_hunk
|
187
|
+
interesting_hunks << [current_hunk_start, current_hunk]
|
188
|
+
end
|
189
|
+
|
190
|
+
interesting_hunks
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Rcov
|
2
|
+
class TextReport < TextSummary # :nodoc:
|
3
|
+
def execute
|
4
|
+
print_lines
|
5
|
+
print_header
|
6
|
+
print_lines
|
7
|
+
|
8
|
+
each_file_pair_sorted do |fname, finfo|
|
9
|
+
name = fname.size < 52 ? fname : "..." + fname[-48..-1]
|
10
|
+
print_info(name, finfo.num_lines, finfo.num_code_lines,
|
11
|
+
finfo.code_coverage)
|
12
|
+
end
|
13
|
+
|
14
|
+
print_lines
|
15
|
+
print_info("Total", num_lines, num_code_lines, code_coverage)
|
16
|
+
print_lines
|
17
|
+
puts summary
|
18
|
+
end
|
19
|
+
|
20
|
+
def print_info(name, lines, loc, coverage)
|
21
|
+
puts "|%-51s | %5d | %5d | %5.1f%% |" % [name, lines, loc, 100 * coverage]
|
22
|
+
end
|
23
|
+
|
24
|
+
def print_lines
|
25
|
+
puts "+----------------------------------------------------+-------+-------+--------+"
|
26
|
+
end
|
27
|
+
|
28
|
+
def print_header
|
29
|
+
puts "| File | Lines | LOC | COV |"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
|
2
|
+
#
|
3
|
+
# See LEGAL and LICENSE for licensing information.
|
4
|
+
|
5
|
+
require 'rcov/version'
|
6
|
+
|
7
|
+
module Rcov
|
8
|
+
|
9
|
+
# RCOV__ performs the low-level tracing of the execution, gathering code
|
10
|
+
# coverage information in the process. The C core made available through the
|
11
|
+
# rcovrt extension will be used if possible. Otherwise the functionality
|
12
|
+
# will be emulated using set_trace_func, but this is very expensive and
|
13
|
+
# will fail if other libraries (e.g. breakpoint) change the trace_func.
|
14
|
+
#
|
15
|
+
# Do not use this module; it is very low-level and subject to frequent
|
16
|
+
# changes. Rcov::CodeCoverageAnalyzer offers a much more convenient and
|
17
|
+
# stable interface.
|
18
|
+
|
19
|
+
module RCOV__
|
20
|
+
COVER = {}
|
21
|
+
CALLSITES = {}
|
22
|
+
DEFSITES = {}
|
23
|
+
pure_ruby_impl_needed = true
|
24
|
+
unless defined? $rcov_do_not_use_rcovrt
|
25
|
+
begin
|
26
|
+
require 'rcovrt'
|
27
|
+
abi = [0,0,0]
|
28
|
+
begin
|
29
|
+
abi = RCOV__.ABI
|
30
|
+
raise if abi[0] != RCOVRT_ABI[0] || abi[1] < RCOVRT_ABI[1]
|
31
|
+
pure_ruby_impl_needed = false
|
32
|
+
rescue
|
33
|
+
$stderr.puts <<-EOF
|
34
|
+
The rcovrt extension I found was built for a different version of rcov.
|
35
|
+
The required ABI is: #{RCOVRT_ABI.join(".")}
|
36
|
+
Your current rcovrt extension is: #{abi.join(".")}
|
37
|
+
|
38
|
+
Please delete rcovrt.{so,bundle,dll,...} and install the required one.
|
39
|
+
EOF
|
40
|
+
raise LoadError
|
41
|
+
end
|
42
|
+
rescue LoadError
|
43
|
+
$stderr.puts <<-EOF
|
44
|
+
|
45
|
+
Since the rcovrt extension couldn't be loaded, rcov will run in pure-Ruby
|
46
|
+
mode, which is about two orders of magnitude slower.
|
47
|
+
|
48
|
+
If you're on win32, you can find a pre-built extension (usable with recent
|
49
|
+
One Click Installer and mswin32 builds) at http://eigenclass.org/hiki.rb?rcov .
|
50
|
+
|
51
|
+
EOF
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if pure_ruby_impl_needed
|
56
|
+
methods = %w[install_coverage_hook remove_coverage_hook reset_coverage
|
57
|
+
install_callsite_hook remove_callsite_hook reset_callsite
|
58
|
+
generate_coverage_info generate_callsite_info]
|
59
|
+
sklass = class << self; self end
|
60
|
+
(methods & sklass.instance_methods).each do |meth|
|
61
|
+
sklass.class_eval{ remove_method meth }
|
62
|
+
end
|
63
|
+
|
64
|
+
@coverage_hook_activated = @callsite_hook_activated = false
|
65
|
+
|
66
|
+
def self.install_coverage_hook # :nodoc:
|
67
|
+
install_common_hook
|
68
|
+
@coverage_hook_activated = true
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.install_callsite_hook # :nodoc:
|
72
|
+
install_common_hook
|
73
|
+
@callsite_hook_activated = true
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.install_common_hook # :nodoc:
|
77
|
+
set_trace_func lambda {|event, file, line, id, binding, klass|
|
78
|
+
next unless SCRIPT_LINES__.has_key? file
|
79
|
+
case event
|
80
|
+
when 'call'
|
81
|
+
if @callsite_hook_activated
|
82
|
+
receiver = eval("self", binding)
|
83
|
+
klass = class << klass; self end unless klass === receiver
|
84
|
+
begin
|
85
|
+
DEFSITES[[klass.to_s, id.to_s]] = [file, line]
|
86
|
+
rescue Exception
|
87
|
+
end
|
88
|
+
caller_arr = self.format_backtrace_array(caller[1,1])
|
89
|
+
begin
|
90
|
+
hash = CALLSITES[[klass.to_s, id.to_s]] ||= {}
|
91
|
+
hash[caller_arr] ||= 0
|
92
|
+
hash[caller_arr] += 1
|
93
|
+
#puts "#{event} #{file} #{line} #{klass.inspect} " +
|
94
|
+
# "#{klass.object_id} #{id} #{eval('self', binding)}"
|
95
|
+
rescue Exception
|
96
|
+
end
|
97
|
+
end
|
98
|
+
when 'c-call', 'c-return', 'class'
|
99
|
+
return
|
100
|
+
end
|
101
|
+
if @coverage_hook_activated
|
102
|
+
COVER[file] ||= Array.new(SCRIPT_LINES__[file].size, 0)
|
103
|
+
COVER[file][line - 1] ||= 0
|
104
|
+
COVER[file][line - 1] += 1
|
105
|
+
end
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.remove_coverage_hook # :nodoc:
|
110
|
+
@coverage_hook_activated = false
|
111
|
+
set_trace_func(nil) if !@callsite_hook_activated
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.remove_callsite_hook # :nodoc:
|
115
|
+
@callsite_hook_activated = false
|
116
|
+
set_trace_func(nil) if !@coverage_hook_activated
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.reset_coverage # :nodoc:
|
120
|
+
COVER.replace({})
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.reset_callsite # :nodoc:
|
124
|
+
CALLSITES.replace({})
|
125
|
+
DEFSITES.replace({})
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.generate_coverage_info # :nodoc:
|
129
|
+
Marshal.load(Marshal.dump(COVER))
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.generate_callsite_info # :nodoc:
|
133
|
+
[CALLSITES, DEFSITES]
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.format_backtrace_array(backtrace)
|
137
|
+
backtrace.map do |line|
|
138
|
+
md = /^([^:]*)(?::(\d+)(?::in `(.*)'))?/.match(line)
|
139
|
+
raise "Bad backtrace format" unless md
|
140
|
+
[nil, md[3] ? md[3].to_sym : nil, md[1], (md[2] || '').to_i]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Define a task library for performing code coverage analysis of unit tests
|
4
|
+
# using rcov.
|
5
|
+
|
6
|
+
require 'rake'
|
7
|
+
require 'rake/tasklib'
|
8
|
+
|
9
|
+
module Rcov
|
10
|
+
|
11
|
+
# Create a task that runs a set of tests through rcov, generating code
|
12
|
+
# coverage reports.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# require 'rcov/rcovtask'
|
17
|
+
#
|
18
|
+
# Rcov::RcovTask.new do |t|
|
19
|
+
# t.libs << "test"
|
20
|
+
# t.test_files = FileList['test/test*.rb']
|
21
|
+
# t.verbose = true
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# If rake is invoked with a "TEST=filename" command line option,
|
25
|
+
# then the list of test files will be overridden to include only the
|
26
|
+
# filename specified on the command line. This provides an easy way
|
27
|
+
# to run just one test.
|
28
|
+
#
|
29
|
+
# If rake is invoked with a "RCOVOPTS=options" command line option,
|
30
|
+
# then the given options are passed to rcov.
|
31
|
+
#
|
32
|
+
# If rake is invoked with a "RCOVPATH=path/to/rcov" command line option,
|
33
|
+
# then the given rcov executable will be used; otherwise the one in your
|
34
|
+
# PATH will be used.
|
35
|
+
#
|
36
|
+
# Examples:
|
37
|
+
#
|
38
|
+
# rake rcov # run tests normally
|
39
|
+
# rake rcov TEST=just_one_file.rb # run just one test file.
|
40
|
+
# rake rcov RCOVOPTS="-p" # run in profile mode
|
41
|
+
# rake rcov RCOVOPTS="-T" # generate text report
|
42
|
+
#
|
43
|
+
class RcovTask < Rake::TaskLib
|
44
|
+
|
45
|
+
# Name of test task. (default is :rcov)
|
46
|
+
attr_accessor :name
|
47
|
+
|
48
|
+
# List of directories to added to $LOAD_PATH before running the
|
49
|
+
# tests. (default is 'lib')
|
50
|
+
attr_accessor :libs
|
51
|
+
|
52
|
+
# True if verbose test output desired. (default is false)
|
53
|
+
attr_accessor :verbose
|
54
|
+
|
55
|
+
# Request that the tests be run with the warning flag set.
|
56
|
+
# E.g. warning=true implies "ruby -w" used to run the tests.
|
57
|
+
attr_accessor :warning
|
58
|
+
|
59
|
+
# Glob pattern to match test files. (default is 'test/test*.rb')
|
60
|
+
attr_accessor :pattern
|
61
|
+
|
62
|
+
# Array of commandline options to pass to ruby when running the rcov loader.
|
63
|
+
attr_accessor :ruby_opts
|
64
|
+
|
65
|
+
# Array of commandline options to pass to rcov. An explicit
|
66
|
+
# RCOVOPTS=opts on the command line will override this. (default
|
67
|
+
# is <tt>["--text-report"]</tt>)
|
68
|
+
attr_accessor :rcov_opts
|
69
|
+
|
70
|
+
# Output directory for the XHTML report.
|
71
|
+
attr_accessor :output_dir
|
72
|
+
|
73
|
+
# Explicitly define the list of test files to be included in a
|
74
|
+
# test. +list+ is expected to be an array of file names (a
|
75
|
+
# FileList is acceptable). If both +pattern+ and +test_files+ are
|
76
|
+
# used, then the list of test files is the union of the two.
|
77
|
+
def test_files=(list)
|
78
|
+
@test_files = list
|
79
|
+
end
|
80
|
+
|
81
|
+
# Create a testing task.
|
82
|
+
def initialize(name=:rcov)
|
83
|
+
@name = name
|
84
|
+
@libs = ["lib"]
|
85
|
+
@pattern = nil
|
86
|
+
@test_files = nil
|
87
|
+
@verbose = false
|
88
|
+
@warning = false
|
89
|
+
@rcov_opts = ["--text-report"]
|
90
|
+
@ruby_opts = []
|
91
|
+
@output_dir = "coverage"
|
92
|
+
yield self if block_given?
|
93
|
+
@pattern = 'test/test*.rb' if @pattern.nil? && @test_files.nil?
|
94
|
+
define
|
95
|
+
end
|
96
|
+
|
97
|
+
# Create the tasks defined by this task lib.
|
98
|
+
def define
|
99
|
+
lib_path = @libs.join(File::PATH_SEPARATOR)
|
100
|
+
actual_name = Hash === name ? name.keys.first : name
|
101
|
+
unless Rake.application.last_comment
|
102
|
+
desc "Analyze code coverage with tests" +
|
103
|
+
(@name==:rcov ? "" : " for #{actual_name}")
|
104
|
+
end
|
105
|
+
task @name do
|
106
|
+
run_code = ''
|
107
|
+
RakeFileUtils.verbose(@verbose) do
|
108
|
+
run_code =
|
109
|
+
case rcov_path
|
110
|
+
when nil, ''
|
111
|
+
"-S rcov"
|
112
|
+
else %!"#{rcov_path}"!
|
113
|
+
end
|
114
|
+
ruby_opts = @ruby_opts.clone
|
115
|
+
ruby_opts.push( "-I#{lib_path}" )
|
116
|
+
ruby_opts.push run_code
|
117
|
+
ruby_opts.push( "-w" ) if @warning
|
118
|
+
ruby ruby_opts.join(" ") + " " + option_list +
|
119
|
+
%[ -o "#{@output_dir}" ] +
|
120
|
+
file_list.collect { |fn| %["#{fn}"] }.join(' ')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
desc "Remove rcov products for #{actual_name}"
|
125
|
+
task paste("clobber_", actual_name) do
|
126
|
+
rm_r @output_dir rescue nil
|
127
|
+
end
|
128
|
+
|
129
|
+
clobber_task = paste("clobber_", actual_name)
|
130
|
+
task :clobber => [clobber_task]
|
131
|
+
|
132
|
+
task actual_name => clobber_task
|
133
|
+
self
|
134
|
+
end
|
135
|
+
|
136
|
+
def rcov_path # :nodoc:
|
137
|
+
ENV['RCOVPATH']
|
138
|
+
end
|
139
|
+
|
140
|
+
def option_list # :nodoc:
|
141
|
+
ENV['RCOVOPTS'] || @rcov_opts.join(" ") || ""
|
142
|
+
end
|
143
|
+
|
144
|
+
def file_list # :nodoc:
|
145
|
+
if ENV['TEST']
|
146
|
+
FileList[ ENV['TEST'] ]
|
147
|
+
else
|
148
|
+
result = []
|
149
|
+
result += @test_files.to_a if @test_files
|
150
|
+
result += FileList[ @pattern ].to_a if @pattern
|
151
|
+
FileList[result]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|