Class: Rcov::FileStatistics
- Inherits:
-
Object
- Object
- Rcov::FileStatistics
- Defined in:
- lib/rcov/file_statistics.rb
Overview
A FileStatistics object associates a filename to:
-
its source code
-
the per-line coverage information after correction using rcov’s heuristics
-
the per-line execution counts
A FileStatistics object can be therefore be built given the filename, the associated source code, and an array holding execution counts (i.e. how many times each line has been executed).
FileStatistics is relatively intelligent: it handles normal comments, =begin/=end
, heredocs, many multiline-expressions… It uses a number of heuristics to determine what is code and what is a comment, and to refine the initial (incomplete) coverage information.
Basic usage is as follows:
sf = FileStatistics.new("foo.rb", ["puts 1", "if true &&", " false",
"puts 2", "end"], [1, 1, 0, 0, 0])
sf.num_lines # => 5
sf.num_code_lines # => 5
sf.coverage[2] # => true
sf.coverage[3] # => :inferred
sf.code_coverage # => 0.6
The array of strings representing the source code and the array of execution counts would normally be obtained from a Rcov::CodeCoverageAnalyzer.
Instance Attribute Summary collapse
-
#counts ⇒ Object
readonly
Returns the value of attribute counts.
-
#coverage ⇒ Object
readonly
Returns the value of attribute coverage.
-
#lines ⇒ Object
readonly
Returns the value of attribute lines.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Instance Method Summary collapse
-
#code_coverage ⇒ Object
Code coverage rate: fraction of lines of code executed, relative to the total amount of lines of code (loc).
- #code_coverage_for_report ⇒ Object
-
#initialize(name, lines, counts, comments_run_by_default = false) ⇒ FileStatistics
constructor
A new instance of FileStatistics.
-
#is_code?(lineno) ⇒ Boolean
Returns true if the given line number corresponds to code, as opposed to a comment (either # or =begin/=end blocks).
-
#merge(lines, coverage, counts) ⇒ Object
Merge code coverage and execution count information.
-
#num_code_lines ⇒ Object
Number of lines of code (loc).
-
#num_lines ⇒ Object
Total number of lines.
-
#total_coverage ⇒ Object
Total coverage rate if comments are also considered “executable”, given as a fraction, i.e.
- #total_coverage_for_report ⇒ Object
Constructor Details
#initialize(name, lines, counts, comments_run_by_default = false) ⇒ FileStatistics
Returns a new instance of FileStatistics.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/rcov/file_statistics.rb', line 29 def initialize(name, lines, counts, comments_run_by_default = false) @name = name @lines = lines initial_coverage = counts.map{|x| (x || 0) > 0 ? true : false } @coverage = CoverageInfo.new initial_coverage @counts = counts @is_begin_comment = nil # points to the line defining the heredoc identifier # but only if it was marked (we don't care otherwise) @heredoc_start = Array.new(lines.size, false) @multiline_string_start = Array.new(lines.size, false) extend_heredocs find_multiline_strings precompute_coverage comments_run_by_default end |
Instance Attribute Details
#counts ⇒ Object (readonly)
Returns the value of attribute counts.
28 29 30 |
# File 'lib/rcov/file_statistics.rb', line 28 def counts @counts end |
#coverage ⇒ Object (readonly)
Returns the value of attribute coverage.
28 29 30 |
# File 'lib/rcov/file_statistics.rb', line 28 def coverage @coverage end |
#lines ⇒ Object (readonly)
Returns the value of attribute lines.
28 29 30 |
# File 'lib/rcov/file_statistics.rb', line 28 def lines @lines end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
28 29 30 |
# File 'lib/rcov/file_statistics.rb', line 28 def name @name end |
Instance Method Details
#code_coverage ⇒ Object
Code coverage rate: fraction of lines of code executed, relative to the total amount of lines of code (loc). Returns a float from 0 to 1.0.
79 80 81 82 83 84 85 |
# File 'lib/rcov/file_statistics.rb', line 79 def code_coverage indices = (0...@lines.size).select{|i| is_code? i } return 0 if indices.size == 0 count = 0 indices.each {|i| count += 1 if @coverage[i] } 1.0 * count / indices.size end |
#code_coverage_for_report ⇒ Object
87 88 89 |
# File 'lib/rcov/file_statistics.rb', line 87 def code_coverage_for_report code_coverage * 100 end |
#is_code?(lineno) ⇒ Boolean
Returns true if the given line number corresponds to code, as opposed to a comment (either # or =begin/=end blocks).
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/rcov/file_statistics.rb', line 107 def is_code?(lineno) unless @is_begin_comment @is_begin_comment = Array.new(@lines.size, false) pending = [] state = :code @lines.each_with_index do |line, index| line.force_encoding("utf-8") if line.respond_to?(:force_encoding) case state when :code if /^=begin\b/ =~ line state = :comment pending << index end when :comment pending << index if /^=end\b/ =~ line state = :code pending.each{|idx| @is_begin_comment[idx] = true} pending.clear end end end end @lines[lineno] && !@is_begin_comment[lineno] && @lines[lineno] !~ /^\s*(#|$)/ end |
#merge(lines, coverage, counts) ⇒ Object
Merge code coverage and execution count information. As for code coverage, a line will be considered
-
covered for sure (true) if it is covered in either
self
or in thecoverage
array -
considered
:inferred
if the neitherself
nor thecoverage
array indicate that it was definitely executed, but it wasinferred
in either one -
not covered (
false
) if it was uncovered in both
Execution counts are just summated on a per-line basis.
55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/rcov/file_statistics.rb', line 55 def merge(lines, coverage, counts) coverage.each_with_index do |v, idx| case @coverage[idx] when :inferred @coverage[idx] = v || @coverage[idx] when false @coverage[idx] ||= v end end counts.each_with_index{|v, idx| @counts[idx] += v } precompute_coverage false end |
#num_code_lines ⇒ Object
Number of lines of code (loc).
96 97 98 |
# File 'lib/rcov/file_statistics.rb', line 96 def num_code_lines (0...@lines.size).select{|i| is_code? i}.size end |
#num_lines ⇒ Object
Total number of lines.
101 102 103 |
# File 'lib/rcov/file_statistics.rb', line 101 def num_lines @lines.size end |
#total_coverage ⇒ Object
Total coverage rate if comments are also considered “executable”, given as a fraction, i.e. from 0 to 1.0. A comment is attached to the code following it (RDoc-style): it will be considered executed if the the next statement was executed.
72 73 74 75 |
# File 'lib/rcov/file_statistics.rb', line 72 def total_coverage return 0 if @coverage.size == 0 @coverage.inject(0.0) {|s,a| s + (a ? 1:0) } / @coverage.size end |
#total_coverage_for_report ⇒ Object
91 92 93 |
# File 'lib/rcov/file_statistics.rb', line 91 def total_coverage_for_report total_coverage * 100 end |