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
data/BLURB
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
Overview
|
2
|
+
========
|
3
|
+
rcov is a code coverage tool for Ruby. It is commonly used for viewing overall
|
4
|
+
test coverage of target code. It features:
|
5
|
+
* fast execution: 20-300 times faster than previous tools
|
6
|
+
* multiple analysis modes: standard, bogo-profile, "intentional testing",
|
7
|
+
dependency analysis...
|
8
|
+
* detection of uncovered code introduced since the last run ("differential
|
9
|
+
code coverage")
|
10
|
+
* fairly accurate coverage information through code linkage inference using
|
11
|
+
simple heuristics
|
12
|
+
* cross-referenced XHTML and several kinds of text reports
|
13
|
+
* support for easy automation with Rake
|
14
|
+
* colorblind-friendliness
|
15
|
+
|
16
|
+
How do I use it?
|
17
|
+
================
|
18
|
+
|
19
|
+
In the common scenario, your tests are under test/ and the target code
|
20
|
+
(whose coverage you want) is in lib/. In that case, all you have to do is
|
21
|
+
use rcov to run the tests (instead of testrb), and a number of XHTML files
|
22
|
+
with the code coverage information will be generated, e.g.
|
23
|
+
|
24
|
+
rcov -Ilib test/*.rb
|
25
|
+
|
26
|
+
will execute all the .rb files under test/ and generate the code coverage
|
27
|
+
report for the target code (i.e. for the files in lib/) under coverage/. The
|
28
|
+
target code needs not be under lib/; rcov will detect is as long as it is
|
29
|
+
require()d by the tests. rcov is smart enough to ignore "uninteresting"
|
30
|
+
files: the tests themselves, files installed in Ruby's standard locations,
|
31
|
+
etc. See rcov --help for the list of regexps rcov matches filenames
|
32
|
+
against.
|
33
|
+
|
34
|
+
rcov can also be used from Rake; see readme_for_rake or the RDoc documentation
|
35
|
+
for more information.
|
36
|
+
|
37
|
+
rcov can output information in several formats, and perform different kinds
|
38
|
+
of analyses in addition to plain code coverage. See rcov --help for a
|
39
|
+
description of the available options.
|
40
|
+
|
41
|
+
Sample output
|
42
|
+
=============
|
43
|
+
|
44
|
+
The text report (also used by default in RcovTasks) resembles
|
45
|
+
|
46
|
+
|
47
|
+
+-----------------------------------------------------+-------+-------+--------+
|
48
|
+
| File | Lines | LOC | COV |
|
49
|
+
+-----------------------------------------------------+-------+-------+--------+
|
50
|
+
|lib/rcov.rb | 572 | 358 | 91.3% |
|
51
|
+
+-----------------------------------------------------+-------+-------+--------+
|
52
|
+
|Total | 572 | 358 | 91.3% |
|
53
|
+
+-----------------------------------------------------+-------+-------+--------+
|
54
|
+
91.3% 1 file(s) 572 Lines 358 LOC
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
The (undecorated) textual output with execution count information looks like this:
|
59
|
+
|
60
|
+
$ rcov --no-html --text-counts b.rb
|
61
|
+
================================================================================
|
62
|
+
./b.rb
|
63
|
+
================================================================================
|
64
|
+
| 2
|
65
|
+
a, b, c = (1..3).to_a | 2
|
66
|
+
10.times do | 1
|
67
|
+
a += 1 | 10
|
68
|
+
20.times do |i| | 10
|
69
|
+
b += i | 200
|
70
|
+
b.times do | 200
|
71
|
+
c += (j = (b-a).abs) > 0 ? j : 0 | 738800
|
72
|
+
end | 0
|
73
|
+
end | 0
|
74
|
+
end | 0
|
75
|
+
|
76
|
+
|
77
|
+
rcov can detect when you've added code that was not covered by your unit
|
78
|
+
tests:
|
79
|
+
|
80
|
+
$ rcov --text-coverage-diff --no-color test/*.rb
|
81
|
+
Started
|
82
|
+
.......................................
|
83
|
+
Finished in 1.163085 seconds.
|
84
|
+
|
85
|
+
39 tests, 415 assertions, 0 failures, 0 errors
|
86
|
+
|
87
|
+
================================================================================
|
88
|
+
!!!!! Uncovered code introduced in lib/rcov.rb
|
89
|
+
|
90
|
+
### lib/rcov.rb:207
|
91
|
+
|
92
|
+
def precompute_coverage(comments_run_by_default = true)
|
93
|
+
changed = false
|
94
|
+
lastidx = lines.size - 1
|
95
|
+
if (!is_code?(lastidx) || /^__END__$/ =~ @lines[-1]) && !@coverage[lastidx]
|
96
|
+
!! # mark the last block of comments
|
97
|
+
!! @coverage[lastidx] ||= :inferred
|
98
|
+
!! (lastidx-1).downto(0) do |i|
|
99
|
+
!! break if is_code?(i)
|
100
|
+
!! @coverage[i] ||= :inferred
|
101
|
+
!! end
|
102
|
+
!! end
|
103
|
+
(0...lines.size).each do |i|
|
104
|
+
next if @coverage[i]
|
105
|
+
line = @lines[i]
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
License
|
110
|
+
-------
|
111
|
+
rcov is released under the terms of Ruby's license.
|
data/LICENSE
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
rcov is copyrighted free software by Mauricio Fernandez <mfp@acm.org>.
|
2
|
+
You can redistribute it and/or modify it under either the terms of the GPL,
|
3
|
+
or the conditions below:
|
4
|
+
|
5
|
+
1. You may make and give away verbatim copies of the source form of the
|
6
|
+
software without restriction, provided that you duplicate all of the
|
7
|
+
original copyright notices and associated disclaimers.
|
8
|
+
|
9
|
+
2. You may modify your copy of the software in any way, provided that
|
10
|
+
you do at least ONE of the following:
|
11
|
+
|
12
|
+
a) place your modifications in the Public Domain or otherwise
|
13
|
+
make them Freely Available, such as by posting said
|
14
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
15
|
+
the author to include your modifications in the software.
|
16
|
+
|
17
|
+
b) use the modified software only within your corporation or
|
18
|
+
organization.
|
19
|
+
|
20
|
+
c) give non-standard binaries non-standard names, with
|
21
|
+
instructions on where to get the original software distribution.
|
22
|
+
|
23
|
+
d) make other distribution arrangements with the author.
|
24
|
+
|
25
|
+
3. You may distribute the software in object code or binary form,
|
26
|
+
provided that you do at least ONE of the following:
|
27
|
+
|
28
|
+
a) distribute the binaries and library files of the software,
|
29
|
+
together with instructions (in the manual page or equivalent)
|
30
|
+
on where to get the original distribution.
|
31
|
+
|
32
|
+
b) accompany the distribution with the machine-readable source of
|
33
|
+
the software.
|
34
|
+
|
35
|
+
c) give non-standard binaries non-standard names, with
|
36
|
+
instructions on where to get the original software distribution.
|
37
|
+
|
38
|
+
d) make other distribution arrangements with the author.
|
39
|
+
|
40
|
+
4. You may modify and include the part of the software into any other
|
41
|
+
software (possibly commercial). But some files in the distribution
|
42
|
+
are not written by the author, so that they are not under these terms.
|
43
|
+
|
44
|
+
5. The scripts and library files supplied as input to or produced as
|
45
|
+
output from the software do not automatically fall under the
|
46
|
+
copyright of the software, but belong to whomever generated them,
|
47
|
+
and may be sold commercially, and may be aggregated with this
|
48
|
+
software.
|
49
|
+
|
50
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
51
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
52
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
53
|
+
PURPOSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
$:.unshift "lib" if File.directory? "lib"
|
2
|
+
require 'rcov/rcovtask'
|
3
|
+
require 'rcov/version'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/clean'
|
8
|
+
|
9
|
+
# Use the specified rcov executable instead of the one in $PATH
|
10
|
+
# (this way we get a sort of informal functional test).
|
11
|
+
# This could also be specified from the command like, e.g.
|
12
|
+
# rake rcov RCOVPATH=/path/to/myrcov
|
13
|
+
ENV["RCOVPATH"] = "bin/rcov"
|
14
|
+
|
15
|
+
# The following task is largely equivalent to:
|
16
|
+
# Rcov::RcovTask.new
|
17
|
+
desc "Create a cross-referenced code coverage report."
|
18
|
+
Rcov::RcovTask.new do |t|
|
19
|
+
t.test_files = FileList['test/*_test.rb']
|
20
|
+
t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
|
21
|
+
t.rcov_opts << "--xrefs" # comment to disable cross-references
|
22
|
+
t.verbose = true
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Analyze code coverage for the FileStatistics class."
|
26
|
+
Rcov::RcovTask.new(:rcov_sourcefile) do |t|
|
27
|
+
t.test_files = FileList['test/file_statistics_test.rb']
|
28
|
+
t.verbose = true
|
29
|
+
t.rcov_opts << "--test-unit-only"
|
30
|
+
t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
|
31
|
+
t.output_dir = "coverage.sourcefile"
|
32
|
+
end
|
33
|
+
|
34
|
+
Rcov::RcovTask.new(:rcov_ccanalyzer) do |t|
|
35
|
+
t.test_files = FileList['test/code_coverage_analyzer_test.rb']
|
36
|
+
t.verbose = true
|
37
|
+
t.rcov_opts << "--test-unit-only"
|
38
|
+
t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
|
39
|
+
t.output_dir = "coverage.ccanalyzer"
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Run the unit tests with rcovrt."
|
43
|
+
Rake::TestTask.new(:test_rcovrt => ["ext/rcovrt/rcovrt.so"]) do |t|
|
44
|
+
system("cd ext/rcovrt && make clean && rm Makefile")
|
45
|
+
t.libs << "ext/rcovrt"
|
46
|
+
t.test_files = FileList['test/*_test.rb']
|
47
|
+
t.verbose = true
|
48
|
+
end
|
49
|
+
|
50
|
+
file "ext/rcovrt/rcovrt.so" => FileList["ext/rcovrt/*.c"] do
|
51
|
+
ruby "setup.rb config"
|
52
|
+
ruby "setup.rb setup"
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Run the unit tests in pure-Ruby mode ."
|
56
|
+
Rake::TestTask.new(:test_pure_ruby) do |t|
|
57
|
+
t.libs << "ext/rcovrt"
|
58
|
+
t.test_files = FileList['test/turn_off_rcovrt.rb', 'test/*_test.rb']
|
59
|
+
t.verbose = true
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "Run the unit tests"
|
63
|
+
task :test => [:test_rcovrt]
|
64
|
+
|
65
|
+
desc "install by setup.rb"
|
66
|
+
task :install do
|
67
|
+
sh "sudo ruby setup.rb install"
|
68
|
+
end
|
69
|
+
|
70
|
+
task :default => :test
|
71
|
+
|
72
|
+
desc "Generate rdoc documentation for the rcov library"
|
73
|
+
Rake::RDocTask.new("rdoc") { |rdoc|
|
74
|
+
rdoc.rdoc_dir = 'doc'
|
75
|
+
rdoc.title = "rcov"
|
76
|
+
rdoc.options << "--line-numbers" << "--inline-source"
|
77
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
78
|
+
}
|
data/THANKS
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
Tom Dolbilin:
|
3
|
+
* identified and fixed backslash problem on win32 for generated filenames
|
4
|
+
|
5
|
+
Andrew Kreiling:
|
6
|
+
* made the index XHTML compliant
|
7
|
+
* consolidate multiple references to the same underlying .rb file
|
8
|
+
|
9
|
+
Robert Feldt:
|
10
|
+
* pointed me to dynamic uses of the tracing hooks, provided the inspiration
|
11
|
+
for RCOV__.run_hooked
|
12
|
+
* helped to refine the color scheme
|
13
|
+
|
14
|
+
Andre Nathan:
|
15
|
+
* identified a bug in the heuristics: missing propagation for lines
|
16
|
+
with only }, ), ]
|
17
|
+
|
18
|
+
David Roberts:
|
19
|
+
* reported confusing behavior when all files are ignored because they match
|
20
|
+
a regexp in the reject list
|
21
|
+
* tested the RubyGems package for win32
|
22
|
+
|
23
|
+
John-Mason Shackelford:
|
24
|
+
* reported an important bug in the pure-Ruby tracer module, which broke it
|
25
|
+
altogether in 0.4.0
|
26
|
+
* suggested a change in the CSS to make XHTML reports more readable under IE
|
27
|
+
|
28
|
+
Dave Burt:
|
29
|
+
* reported an issue with text reports under cmd.exe (should use < 80 cols)
|
30
|
+
|
31
|
+
Alex Wayne:
|
32
|
+
* reported problem with heredocs: they were not being marked as a whole if
|
33
|
+
the "header" wasn't reported by Ruby.
|
34
|
+
* reported problem with the last line of literal data structs not being
|
35
|
+
covered if there was stuff after the end delimiter
|
36
|
+
|
37
|
+
Coda Hale:
|
38
|
+
* reported problem with blocks were the first line is not being marked
|
39
|
+
and ditto for the last line when end/} is followed by more stuff
|
40
|
+
|
41
|
+
Tim Shadel:
|
42
|
+
* reported that the last comment block was not being marked even when
|
43
|
+
it was the last thing in the file
|
44
|
+
|
45
|
+
Thomas Leitner:
|
46
|
+
* reported that the SCRIPT_LINES__ workaround did not always work
|
47
|
+
* fixed the bug which broke differential reports for filenames with
|
48
|
+
special characters
|
49
|
+
|
50
|
+
Assaph Mehr:
|
51
|
+
* beta-tested 0.7.0 and found a bug in --aggregate (missing files)
|
52
|
+
|
53
|
+
Ryan Kinderman:
|
54
|
+
* suggested that -Ipath be passed to ruby instead of rcov in RcovTasks
|
55
|
+
|
56
|
+
Jan Svitok:
|
57
|
+
* reported typo in rcovtask.rb's RDoc
|
58
|
+
|
59
|
+
rubikitch:
|
60
|
+
* implemented --annotate mode
|
61
|
+
* implemented --gcc option
|
62
|
+
* superior emacs support
|
63
|
+
* testing, refactoring...
|
64
|
+
* many other things, see darcs changes
|
65
|
+
|
66
|
+
Zed A. Shaw:
|
67
|
+
* reported and fixed segfault triggered by rspec
|
68
|
+
|
69
|
+
Lee Marlow:
|
70
|
+
* patch allowing to run rcov against a data file with no input code
|
71
|
+
|
72
|
+
Kurt Stephens:
|
73
|
+
* patch to rethrow any exceptions generated by the traced scripts after
|
74
|
+
report generation; notably SystemExit, allowing to use the exit code from
|
75
|
+
test runners under rake.
|
76
|
+
|
77
|
+
Brian Candler:
|
78
|
+
* found compatibility issues with the REXML lib included in ruby-1.8.6-p110
|
79
|
+
and provided a workaround
|
80
|
+
|
81
|
+
Mat Schaffer:
|
82
|
+
* reported missing line colorization on Safari and probably other browsers,
|
83
|
+
owing to self-closing <a> not being handled properly despite being valid
|
84
|
+
XHTML 1.0.
|
85
|
+
|
86
|
+
Sam Granieri:
|
87
|
+
* tested workaround for REXML bug
|
88
|
+
|
89
|
+
Kosmas Schütz, Daniel Berger, François Beausoleil, Bil Kleb:
|
90
|
+
* provided information about the ruby-1.8.6-p11[01] REXML problems
|
91
|
+
|
92
|
+
Chad Humphries:
|
93
|
+
* indicated that Spec::DSL::Example has changed in RSpec trunk
|
94
|
+
|
95
|
+
Jeremy Hinegardner:
|
96
|
+
* more info about REXML's bugs in 1.8.6-p11[01]
|
data/bin/rcov
ADDED
@@ -0,0 +1,508 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: iso-8859-1 -*-
|
3
|
+
# rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
|
4
|
+
#
|
5
|
+
# rcov originally based on
|
6
|
+
# module COVERAGE__ originally (c) NAKAMURA Hiroshi
|
7
|
+
# module PrettyCoverage originally (c) Simon Strandgaard
|
8
|
+
#
|
9
|
+
# rewritten & extended by Mauricio Fern�ndez <mfp@acm.org>
|
10
|
+
#
|
11
|
+
# See LEGAL and LICENSE for additional licensing information.
|
12
|
+
#
|
13
|
+
require 'cgi'
|
14
|
+
require 'rbconfig'
|
15
|
+
require 'optparse'
|
16
|
+
require 'ostruct'
|
17
|
+
|
18
|
+
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
|
19
|
+
require 'rcov/version'
|
20
|
+
require 'rcov/formatters'
|
21
|
+
|
22
|
+
#{{{ "main" code
|
23
|
+
options = OpenStruct.new
|
24
|
+
options.color = true
|
25
|
+
options.range = 30.0
|
26
|
+
options.profiling = false
|
27
|
+
options.destdir = nil
|
28
|
+
options.loadpaths = []
|
29
|
+
options.textmode = false
|
30
|
+
options.skip = Rcov::BaseFormatter::DEFAULT_OPTS[:ignore]
|
31
|
+
options.include = []
|
32
|
+
options.html = true
|
33
|
+
options.comments_run_by_default = false
|
34
|
+
options.test_unit_only = false
|
35
|
+
options.spec_only = false
|
36
|
+
options.sort = :name
|
37
|
+
options.sort_reverse = false
|
38
|
+
options.output_threshold = 101
|
39
|
+
options.failure_threshold = nil
|
40
|
+
options.replace_prog_name = false
|
41
|
+
options.callsites = false
|
42
|
+
options.crossrefs = false
|
43
|
+
options.coverage_diff_file = "coverage.info"
|
44
|
+
options.coverage_diff_mode = :compare
|
45
|
+
options.coverage_diff_save = false
|
46
|
+
options.diff_cmd = "diff"
|
47
|
+
options.report_cov_bug_for = nil
|
48
|
+
options.aggregate_file = nil
|
49
|
+
options.gcc_output = false
|
50
|
+
options.charset = nil
|
51
|
+
|
52
|
+
EXTRA_HELP = <<-EOF
|
53
|
+
|
54
|
+
You can run several programs at once:
|
55
|
+
rcov something.rb somethingelse.rb
|
56
|
+
|
57
|
+
The parameters to be passed to the program under inspection can be specified
|
58
|
+
after --:
|
59
|
+
|
60
|
+
rcov -Ilib -t something.rb -- --theseopts --are --given --to --something.rb
|
61
|
+
|
62
|
+
ARGV will be set to the specified parameters after --.
|
63
|
+
Keep in mind that all the programs are run under the same process
|
64
|
+
(i.e. they just get Kernel#load()'ed in sequence).
|
65
|
+
|
66
|
+
$PROGRAM_NAME (aka. $0) will be set before each file is load()ed if
|
67
|
+
--replace-progname is used.
|
68
|
+
EOF
|
69
|
+
|
70
|
+
def deprecated(opt)
|
71
|
+
puts "#{opt} is now depricated. Please remove it from you Rakefile or scripts. It will be removed in the next release."
|
72
|
+
end
|
73
|
+
|
74
|
+
#{{{ OptionParser
|
75
|
+
opts = OptionParser.new do |opts|
|
76
|
+
opts.banner = <<-EOF
|
77
|
+
rcov #{Rcov::VERSION} #{Rcov::RELEASE_DATE}
|
78
|
+
Usage: rcov [options] <script1.rb> [script2.rb] [-- --extra-options]
|
79
|
+
EOF
|
80
|
+
opts.separator ""
|
81
|
+
opts.separator "Options:"
|
82
|
+
|
83
|
+
opts.on("-o", "--output PATH", "Destination directory.") do |dir|
|
84
|
+
options.destdir = dir
|
85
|
+
end
|
86
|
+
|
87
|
+
opts.on("-I", "--include PATHS", "Prepend PATHS to $: (colon separated list)") do |paths|
|
88
|
+
options.loadpaths = paths.split(/:/)
|
89
|
+
end
|
90
|
+
|
91
|
+
opts.on("--[no-]comments", "Mark all comments by default.", "(default: --no-comments)") do |comments_run_p|
|
92
|
+
options.comments_run_by_default = comments_run_p
|
93
|
+
end
|
94
|
+
|
95
|
+
opts.on("--test-unit-only", "Only trace code executed inside TestCases.") do
|
96
|
+
deprecated("--test-unit-only")
|
97
|
+
end
|
98
|
+
|
99
|
+
opts.on("--spec-only", "Only trace code executed inside RSpec specs.") do
|
100
|
+
deprecated("--spec-only")
|
101
|
+
end
|
102
|
+
|
103
|
+
opts.on("-n", "--no-color", "Create colorblind-safe output.") do
|
104
|
+
options.color = false
|
105
|
+
end
|
106
|
+
|
107
|
+
opts.on("-i", "--include-file PATTERNS",
|
108
|
+
"Generate info for files matching a",
|
109
|
+
"pattern (comma-separated regexp list)") do |list|
|
110
|
+
begin
|
111
|
+
regexps = list.split(/,/).map{|x| Regexp.new(x) }
|
112
|
+
options.include += regexps
|
113
|
+
rescue RegexpError => e
|
114
|
+
raise OptionParser::InvalidArgument, e.message
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
opts.on("-x", "--exclude PATTERNS", "Don't generate info for files matching a","pattern (comma-separated regexp list)") do |list|
|
119
|
+
begin
|
120
|
+
regexps = list.split(/,/).map{|x| Regexp.new x}
|
121
|
+
options.skip += regexps
|
122
|
+
rescue RegexpError => e
|
123
|
+
raise OptionParser::InvalidArgument, e.message
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
opts.on("--exclude-only PATTERNS", "Skip info only for files matching the", "given patterns.") do |list|
|
128
|
+
begin
|
129
|
+
options.skip = list.split(/,/).map{|x| Regexp.new(x) }
|
130
|
+
rescue RegexpError => e
|
131
|
+
raise OptionParser::InvalidArgument, e.message
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
opts.on("--rails", "Skip config/, environment/ and vendor/.") do
|
136
|
+
options.skip.concat [%r{\bvendor/},%r{\bconfig/},%r{\benvironment/}]
|
137
|
+
end
|
138
|
+
|
139
|
+
opts.on("--[no-]callsites", "Show callsites in generated XHTML report.", "(somewhat slower; disabled by default)") do |val|
|
140
|
+
options.callsites = val
|
141
|
+
end
|
142
|
+
|
143
|
+
opts.on("--[no-]xrefs", "Generate fully cross-referenced report.", "(includes --callsites)") do |val|
|
144
|
+
options.crossrefs = val
|
145
|
+
options.callsites ||= val
|
146
|
+
end
|
147
|
+
|
148
|
+
opts.on("-p", "--profile", "Generate bogo-profiling info.") do
|
149
|
+
options.profiling = true
|
150
|
+
options.destdir ||= "profiling"
|
151
|
+
end
|
152
|
+
|
153
|
+
opts.on("-r", "--range RANGE", Float, "Color scale range for profiling info (dB).") do |val|
|
154
|
+
options.range = val
|
155
|
+
end
|
156
|
+
|
157
|
+
opts.on("-a", "--annotate", "Generate annotated source code.") do
|
158
|
+
options.html = false
|
159
|
+
options.textmode = :annotate
|
160
|
+
options.crossrefs = true
|
161
|
+
options.callsites = true
|
162
|
+
options.skip = [ %r!/test/unit/! ]
|
163
|
+
end
|
164
|
+
|
165
|
+
opts.on("-T", "--text-report", "Dump detailed plain-text report to stdout.", "(filename, LoC, total lines, coverage)") do
|
166
|
+
options.textmode = :report
|
167
|
+
end
|
168
|
+
|
169
|
+
opts.on("-t", "--text-summary", "Dump plain-text summary to stdout.") do
|
170
|
+
options.textmode = :summary
|
171
|
+
end
|
172
|
+
|
173
|
+
opts.on("--text-counts", "Dump execution counts in plaintext.") do
|
174
|
+
options.textmode = :counts
|
175
|
+
end
|
176
|
+
|
177
|
+
opts.on("--text-coverage", "Dump coverage info to stdout, using", "ANSI color sequences unless -n.") do
|
178
|
+
options.textmode = :coverage
|
179
|
+
end
|
180
|
+
|
181
|
+
opts.on("--gcc", "Dump uncovered line in GCC error format.") do
|
182
|
+
options.gcc_output = true
|
183
|
+
end
|
184
|
+
|
185
|
+
opts.on("--aggregate FILE", "Aggregate data from previous runs",
|
186
|
+
"in FILE. Overwrites FILE with the",
|
187
|
+
"merged data. FILE is created if",
|
188
|
+
"necessary.") do |file|
|
189
|
+
options.aggregate_file = file
|
190
|
+
end
|
191
|
+
|
192
|
+
opts.on("-D [FILE]", "--text-coverage-diff [FILE]",
|
193
|
+
"Compare code coverage with saved state",
|
194
|
+
"in FILE, defaults to coverage.info.",
|
195
|
+
"Implies --comments.") do |file|
|
196
|
+
options.textmode = :coverage_diff
|
197
|
+
options.comments_run_by_default = true
|
198
|
+
if options.coverage_diff_save
|
199
|
+
raise "You shouldn't use --save and --text-coverage-diff at a time."
|
200
|
+
end
|
201
|
+
options.coverage_diff_mode = :compare
|
202
|
+
options.coverage_diff_file = file if file && !file.empty?
|
203
|
+
end
|
204
|
+
|
205
|
+
opts.on("--save [FILE]", "Save coverage data to FILE,", "for later use with rcov -D.", "(default: coverage.info)") do |file|
|
206
|
+
options.coverage_diff_save = true
|
207
|
+
options.coverage_diff_mode = :record
|
208
|
+
if options.textmode == :coverage_diff
|
209
|
+
raise "You shouldn't use --save and --text-coverage-diff at a time."
|
210
|
+
end
|
211
|
+
options.coverage_diff_file = file if file && !file.empty?
|
212
|
+
end
|
213
|
+
|
214
|
+
opts.on("--[no-]html", "Generate HTML output.", "(default: --html)") do |val|
|
215
|
+
options.html = val
|
216
|
+
end
|
217
|
+
|
218
|
+
opts.on("--sort CRITERION", [:name, :loc, :coverage], "Sort files in the output by the specified", "field (name, loc, coverage)") do |criterion|
|
219
|
+
options.sort = criterion
|
220
|
+
end
|
221
|
+
|
222
|
+
opts.on("--sort-reverse", "Reverse files in the output.") do
|
223
|
+
options.sort_reverse = true
|
224
|
+
end
|
225
|
+
|
226
|
+
opts.on("--threshold INT", "Only list files with coverage < INT %.", "(default: 101)") do |threshold|
|
227
|
+
begin
|
228
|
+
threshold = Integer(threshold)
|
229
|
+
raise if threshold <= 0 || threshold > 101
|
230
|
+
rescue Exception
|
231
|
+
raise OptionParser::InvalidArgument, threshold
|
232
|
+
end
|
233
|
+
options.output_threshold = threshold
|
234
|
+
end
|
235
|
+
|
236
|
+
opts.on("--failure-threshold [INT]", "Fail if the coverage is below the threshold", "(default: 100)") do |threshold|
|
237
|
+
options.failure_threshold = (threshold || 100).to_i
|
238
|
+
options.textmode = :failure_report
|
239
|
+
end
|
240
|
+
|
241
|
+
opts.on("--charset CHARSET", "Charset used in Content-Type declaration of HTML reports.") do |c|
|
242
|
+
options.charset = c
|
243
|
+
end
|
244
|
+
|
245
|
+
opts.on("--only-uncovered", "Same as --threshold 100") do
|
246
|
+
options.output_threshold = 100
|
247
|
+
end
|
248
|
+
|
249
|
+
opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
|
250
|
+
options.replace_prog_name = true
|
251
|
+
end
|
252
|
+
|
253
|
+
opts.on("-w", "Turn warnings on (like ruby).") do
|
254
|
+
$VERBOSE = true
|
255
|
+
end
|
256
|
+
|
257
|
+
opts.on("--no-rcovrt", "Do not use the optimized C runtime.", "(will run 30-300 times slower)") do
|
258
|
+
$rcov_do_not_use_rcovrt = true
|
259
|
+
end
|
260
|
+
|
261
|
+
opts.on("--diff-cmd PROGNAME", "Use PROGNAME for --text-coverage-diff.",
|
262
|
+
"(default: diff)") do |cmd|
|
263
|
+
options.diff_cmd = cmd
|
264
|
+
end
|
265
|
+
|
266
|
+
opts.separator ""
|
267
|
+
|
268
|
+
opts.on_tail("-h", "--help", "Show extended help message") do
|
269
|
+
require 'pp'
|
270
|
+
puts opts
|
271
|
+
puts <<EOF
|
272
|
+
|
273
|
+
Files matching any of the following regexps will be omitted in the report(s):
|
274
|
+
#{PP.pp(options.skip, "").chomp}
|
275
|
+
EOF
|
276
|
+
puts EXTRA_HELP
|
277
|
+
exit
|
278
|
+
end
|
279
|
+
|
280
|
+
opts.on_tail("--report-cov-bug SELECTOR", "Report coverage analysis bug for the",
|
281
|
+
"method specified by SELECTOR", "(format: Foo::Bar#method, A::B.method)") do |selector|
|
282
|
+
case selector
|
283
|
+
when /([^.]+)(#|\.)(.*)/ then options.report_cov_bug_for = selector
|
284
|
+
else
|
285
|
+
raise OptionParser::InvalidArgument, selector
|
286
|
+
end
|
287
|
+
options.textmode = nil
|
288
|
+
options.html = false
|
289
|
+
options.callsites = true
|
290
|
+
end
|
291
|
+
opts.on_tail("--version", "Show version") do
|
292
|
+
puts "rcov " + Rcov::VERSION + " " + Rcov::RELEASE_DATE
|
293
|
+
exit
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
$ORIGINAL_ARGV = ARGV.clone
|
298
|
+
if (idx = ARGV.index("--"))
|
299
|
+
extra_args = ARGV[idx+1..-1]
|
300
|
+
ARGV.replace(ARGV[0,idx])
|
301
|
+
else
|
302
|
+
extra_args = []
|
303
|
+
end
|
304
|
+
|
305
|
+
begin
|
306
|
+
opts.parse! ARGV
|
307
|
+
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument => e
|
308
|
+
puts opts
|
309
|
+
puts
|
310
|
+
puts e.message
|
311
|
+
exit(-1)
|
312
|
+
end
|
313
|
+
|
314
|
+
options.destdir ||= "coverage"
|
315
|
+
unless ARGV[0] or options.aggregate_file && File.file?(options.aggregate_file)
|
316
|
+
puts opts
|
317
|
+
exit
|
318
|
+
end
|
319
|
+
|
320
|
+
# {{{ set loadpath
|
321
|
+
options.loadpaths.reverse_each{|x| $:.unshift x}
|
322
|
+
|
323
|
+
#{{{ require 'rcov': do it only now in order to be able to run rcov on itself
|
324
|
+
# since we need to set $: before.
|
325
|
+
|
326
|
+
require 'rcov'
|
327
|
+
|
328
|
+
options.callsites = true if options.report_cov_bug_for
|
329
|
+
options.textmode = :gcc if !options.textmode and options.gcc_output
|
330
|
+
|
331
|
+
def rcov_load_aggregate_data(file)
|
332
|
+
require 'zlib'
|
333
|
+
begin
|
334
|
+
old_data = nil
|
335
|
+
Zlib::GzipReader.open(file){|gz| old_data = Marshal.load(gz) }
|
336
|
+
rescue
|
337
|
+
old_data = {}
|
338
|
+
end
|
339
|
+
old_data || {}
|
340
|
+
end
|
341
|
+
|
342
|
+
def rcov_save_aggregate_data(file)
|
343
|
+
require 'zlib'
|
344
|
+
Zlib::GzipWriter.open(file) do |f|
|
345
|
+
Marshal.dump({:callsites => $rcov_callsite_analyzer, :coverage => $rcov_code_coverage_analyzer}, f)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
if options.callsites
|
350
|
+
if options.aggregate_file
|
351
|
+
saved_aggregate_data = rcov_load_aggregate_data(options.aggregate_file)
|
352
|
+
if saved_aggregate_data[:callsites]
|
353
|
+
$rcov_callsite_analyzer = saved_aggregate_data[:callsites]
|
354
|
+
end
|
355
|
+
end
|
356
|
+
$rcov_callsite_analyzer ||= Rcov::CallSiteAnalyzer.new
|
357
|
+
$rcov_callsite_analyzer.install_hook
|
358
|
+
else
|
359
|
+
$rcov_callsite_analyzer = nil
|
360
|
+
end
|
361
|
+
|
362
|
+
# {{{ create formatters
|
363
|
+
formatters = []
|
364
|
+
make_formatter = lambda do |klass|
|
365
|
+
klass.new(:destdir => options.destdir, :color => options.color,
|
366
|
+
:fsr => options.range, :textmode => options.textmode,
|
367
|
+
:ignore => options.skip, :dont_ignore => options.include,
|
368
|
+
:sort => options.sort,
|
369
|
+
:sort_reverse => options.sort_reverse,
|
370
|
+
:output_threshold => options.output_threshold,
|
371
|
+
:callsite_analyzer => $rcov_callsite_analyzer,
|
372
|
+
:coverage_diff_mode => options.coverage_diff_mode,
|
373
|
+
:coverage_diff_file => options.coverage_diff_file,
|
374
|
+
:callsites => options.callsites,
|
375
|
+
:cross_references => options.crossrefs,
|
376
|
+
:diff_cmd => options.diff_cmd,
|
377
|
+
:comments_run_by_default => options.comments_run_by_default,
|
378
|
+
:gcc_output => options.gcc_output,
|
379
|
+
:charset => options.charset,
|
380
|
+
:failure_threshold => options.failure_threshold
|
381
|
+
)
|
382
|
+
end
|
383
|
+
|
384
|
+
if options.html
|
385
|
+
if options.profiling
|
386
|
+
formatters << make_formatter[Rcov::HTMLProfiling]
|
387
|
+
else
|
388
|
+
formatters << make_formatter[Rcov::HTMLCoverage]
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
textual_formatters = { :counts => Rcov::FullTextReport, :coverage => Rcov::FullTextReport,
|
393
|
+
:gcc => Rcov::FullTextReport, :annotate => Rcov::RubyAnnotation,
|
394
|
+
:summary => Rcov::TextSummary, :report => Rcov::TextReport,
|
395
|
+
:coverage_diff => Rcov::TextCoverageDiff, :failure_report => Rcov::FailureReport }
|
396
|
+
|
397
|
+
if textual_formatters[options.textmode]
|
398
|
+
formatters << make_formatter[textual_formatters[options.textmode]]
|
399
|
+
end
|
400
|
+
|
401
|
+
formatters << make_formatter[Rcov::TextCoverageDiff] if options.coverage_diff_save
|
402
|
+
|
403
|
+
if options.aggregate_file
|
404
|
+
saved_aggregate_data ||= rcov_load_aggregate_data(options.aggregate_file)
|
405
|
+
if saved_aggregate_data[:coverage]
|
406
|
+
$rcov_code_coverage_analyzer = saved_aggregate_data[:coverage]
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
$rcov_code_coverage_analyzer ||= Rcov::CodeCoverageAnalyzer.new
|
411
|
+
|
412
|
+
# must be registered before test/unit puts its own
|
413
|
+
|
414
|
+
|
415
|
+
# The exception to rethrow after reporting has been handled.
|
416
|
+
$__rcov_exit_exception = nil
|
417
|
+
|
418
|
+
END {
|
419
|
+
$rcov_code_coverage_analyzer.remove_hook
|
420
|
+
$rcov_callsite_analyzer.remove_hook if $rcov_callsite_analyzer
|
421
|
+
rcov_save_aggregate_data(options.aggregate_file) if options.aggregate_file
|
422
|
+
$rcov_code_coverage_analyzer.dump_coverage_info(formatters)
|
423
|
+
if options.report_cov_bug_for
|
424
|
+
defsite = $rcov_callsite_analyzer.defsite(options.report_cov_bug_for)
|
425
|
+
if !defsite
|
426
|
+
$stderr.puts <<-EOF
|
427
|
+
Couldn't find definition site of #{options.report_cov_bug_for}.
|
428
|
+
Was it executed at all?
|
429
|
+
EOF
|
430
|
+
exit(-1)
|
431
|
+
end
|
432
|
+
lines, mark_info, count_info = $rcov_code_coverage_analyzer.data(defsite.file)
|
433
|
+
puts <<EOF
|
434
|
+
|
435
|
+
Please fill in the blanks in the following report.
|
436
|
+
|
437
|
+
|
438
|
+
You can post bugs to
|
439
|
+
http://github.com/relevance/rcov/issues
|
440
|
+
|
441
|
+
Thank you!
|
442
|
+
|
443
|
+
=============================================================================
|
444
|
+
Bug report generated on #{Time.new}
|
445
|
+
|
446
|
+
Ruby version: #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})
|
447
|
+
Platform: #{RUBY_PLATFORM}
|
448
|
+
rcov version: #{Rcov::VERSION}
|
449
|
+
rcovrt loaded? #{$".any?{|x| /\brcovrt\b/ =~ x} }
|
450
|
+
using RubyGems? #{$".any?{|x| /\brubygems\b/ =~ x} }
|
451
|
+
Command-line arguments: #{$ORIGINAL_ARGV.inspect}
|
452
|
+
Coverage analysis bug in: #{options.report_cov_bug_for}
|
453
|
+
|
454
|
+
Line(s) ____________ should be ______ (red/green).
|
455
|
+
|
456
|
+
Raw coverage information (feel free to remove useless data, but please leave
|
457
|
+
some context around the faulty lines):
|
458
|
+
|
459
|
+
EOF
|
460
|
+
defsite.line.upto(SCRIPT_LINES__[defsite.file].size) do |i|
|
461
|
+
puts "%7d:%5d:%s" % [count_info[i-1], i, lines[i-1]]
|
462
|
+
end
|
463
|
+
exit
|
464
|
+
end
|
465
|
+
if !formatters.empty? and formatters.all?{|formatter| formatter.sorted_file_pairs.empty? }
|
466
|
+
require 'pp'
|
467
|
+
$stderr.puts <<-EOF
|
468
|
+
|
469
|
+
No file to analyze was found. All the files loaded by rcov matched one of the
|
470
|
+
following expressions, and were thus ignored:
|
471
|
+
#{PP.pp(options.skip, "").chomp}
|
472
|
+
|
473
|
+
You can solve this by doing one or more of the following:
|
474
|
+
* rename the files not to be ignored so they don't match the above regexps
|
475
|
+
* use --include-file to give a list of patterns for files not to be ignored
|
476
|
+
* use --exclude-only to give the new list of regexps to match against
|
477
|
+
* structure your code as follows:
|
478
|
+
test/test_*.rb for the test cases
|
479
|
+
lib/**/*.rb for the target source code whose coverage you want
|
480
|
+
making sure that the test/test_*.rb files are loading from lib/, e.g. by
|
481
|
+
using the -Ilib command-line argument, adding
|
482
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
483
|
+
to test/test_*.rb, or running rcov via a Rakefile (read the RDoc
|
484
|
+
documentation or README.rake in the source distribution).
|
485
|
+
EOF
|
486
|
+
end
|
487
|
+
|
488
|
+
raise $__rcov_exit_exception if $__rcov_exit_exception
|
489
|
+
}
|
490
|
+
|
491
|
+
$rcov_code_coverage_analyzer.install_hook
|
492
|
+
|
493
|
+
#{{{ Load scripts
|
494
|
+
begin
|
495
|
+
pending_scripts = ARGV.clone
|
496
|
+
ARGV.replace extra_args
|
497
|
+
until pending_scripts.empty?
|
498
|
+
prog = pending_scripts.shift
|
499
|
+
if options.replace_prog_name
|
500
|
+
$0 = File.basename(File.expand_path(prog))
|
501
|
+
end
|
502
|
+
load prog
|
503
|
+
end
|
504
|
+
rescue Object => err
|
505
|
+
$__rcov_exit_exception = err
|
506
|
+
end
|
507
|
+
|
508
|
+
__END__
|