Class: Covered::Coverage
- Inherits:
-
Object
- Object
- Covered::Coverage
- Includes:
- Ratio
- Defined in:
- lib/covered/coverage.rb
Overview
Stores line execution counts and source metadata for a single file.
Instance Attribute Summary collapse
-
#annotations ⇒ Object
readonly
Returns the value of attribute annotations.
-
#counts ⇒ Object
readonly
Returns the value of attribute counts.
- #Line annotations indexed by line number.(annotationsindexedbylinenumber.) ⇒ Object readonly
- #Line execution counts indexed by line number.(executioncountsindexedbylinenumber.) ⇒ Object readonly
-
#source ⇒ Object
Returns the value of attribute source.
- #The covered source metadata.(coveredsourcemetadata.) ⇒ Object readonly
Class Method Summary collapse
-
.deserialize(unpacker) ⇒ Object
Deserialize a coverage object from the given unpacker.
-
.for(path, **options) ⇒ Object
Build coverage for the given source path.
Instance Method Summary collapse
-
#[](line_number) ⇒ Object
The raw coverage count for the given line number.
-
#annotate(line_number, annotation) ⇒ Object
Add an annotation to the given line number.
-
#as_json ⇒ Object
A JSON-compatible representation of this coverage object.
-
#empty ⇒ Object
Create an empty coverage with the same source.
-
#executable_count ⇒ Object
The number of executable lines.
-
#executable_lines ⇒ Object
Counts for lines that are executable.
-
#executed_count ⇒ Object
The number of executable lines that were executed.
-
#executed_lines ⇒ Object
Counts for executable lines that were executed.
-
#for_lines(line_numbers) ⇒ Object
Construct a new coverage object for the given line numbers.
-
#freeze ⇒ Object
Freeze this coverage and its mutable collections.
-
#fresh? ⇒ Boolean
Whether the source file has not changed since this coverage was recorded.
-
#initialize(source, counts = [], annotations = {}) ⇒ Coverage
constructor
Initialize coverage with the given source, line counts and annotations.
-
#mark(line_number, value = 1) ⇒ Object
Add the given execution count to one or more line numbers.
-
#merge!(other) ⇒ Object
Merge another coverage object into this coverage object.
-
#missing_count ⇒ Object
The number of executable lines that were not executed.
-
#path ⇒ Object
The covered source path.
-
#path=(value) ⇒ Object
Assign the covered source path.
-
#print(output) ⇒ Object
Print a human-readable coverage summary.
-
#read(&block) ⇒ Object
Read the covered source.
-
#serialize(packer) ⇒ Object
Serialize this coverage object with the given packer.
-
#to_a ⇒ Object
The raw coverage counts array.
-
#to_s ⇒ Object
A human-readable representation of this coverage object.
-
#total ⇒ Object
The total number of executions across all tracked lines.
-
#zero? ⇒ Boolean
Whether this coverage has no executions.
Methods included from Ratio
#complete?, #percentage, #ratio
Constructor Details
#initialize(source, counts = [], annotations = {}) ⇒ Coverage
Initialize coverage with the given source, line counts and annotations.
48 49 50 51 52 |
# File 'lib/covered/coverage.rb', line 48 def initialize(source, counts = [], annotations = {}) @source = source @counts = counts @annotations = annotations end |
Instance Attribute Details
#annotations ⇒ Object (readonly)
Returns the value of attribute annotations.
61 62 63 |
# File 'lib/covered/coverage.rb', line 61 def annotations @annotations end |
#counts ⇒ Object (readonly)
Returns the value of attribute counts.
58 59 60 |
# File 'lib/covered/coverage.rb', line 58 def counts @counts end |
#Line annotations indexed by line number.(annotationsindexedbylinenumber.) ⇒ Object (readonly)
61 |
# File 'lib/covered/coverage.rb', line 61 attr :annotations |
#Line execution counts indexed by line number.(executioncountsindexedbylinenumber.) ⇒ Object (readonly)
58 |
# File 'lib/covered/coverage.rb', line 58 attr :counts |
#source ⇒ Object
Returns the value of attribute source.
55 56 57 |
# File 'lib/covered/coverage.rb', line 55 def source @source end |
#The covered source metadata.(coveredsourcemetadata.) ⇒ Object (readonly)
55 |
# File 'lib/covered/coverage.rb', line 55 attr_accessor :source |
Class Method Details
.deserialize(unpacker) ⇒ Object
Deserialize a coverage object from the given unpacker.
263 264 265 266 267 268 269 |
# File 'lib/covered/coverage.rb', line 263 def self.deserialize(unpacker) source = unpacker.read counts = unpacker.read annotations = unpacker.read self.new(source, counts, annotations) end |
Instance Method Details
#[](line_number) ⇒ Object
The raw coverage count for the given line number.
195 196 197 |
# File 'lib/covered/coverage.rb', line 195 def [] line_number @counts[line_number] end |
#annotate(line_number, annotation) ⇒ Object
Add an annotation to the given line number.
78 79 80 81 |
# File 'lib/covered/coverage.rb', line 78 def annotate(line_number, annotation) @annotations[line_number] ||= [] @annotations[line_number] << annotation end |
#as_json ⇒ Object
A JSON-compatible representation of this coverage object.
243 244 245 246 247 248 249 250 |
# File 'lib/covered/coverage.rb', line 243 def as_json { counts: counts, executable_count: executable_count, executed_count: executed_count, percentage: percentage.to_f.round(2), } end |
#empty ⇒ Object
Create an empty coverage with the same source.
71 72 73 |
# File 'lib/covered/coverage.rb', line 71 def empty self.class.new(@source, [nil] * @counts.size) end |
#executable_count ⇒ Object
The number of executable lines.
207 208 209 |
# File 'lib/covered/coverage.rb', line 207 def executable_count executable_lines.count end |
#executable_lines ⇒ Object
Counts for lines that are executable.
201 202 203 |
# File 'lib/covered/coverage.rb', line 201 def executable_lines @counts.compact end |
#executed_count ⇒ Object
The number of executable lines that were executed.
219 220 221 |
# File 'lib/covered/coverage.rb', line 219 def executed_count executed_lines.count end |
#executed_lines ⇒ Object
Counts for executable lines that were executed.
213 214 215 |
# File 'lib/covered/coverage.rb', line 213 def executed_lines executable_lines.reject(&:zero?) end |
#for_lines(line_numbers) ⇒ Object
Construct a new coverage object for the given line numbers. Only the given line numbers will be considered for the purposes of computing coverage.
119 120 121 122 123 124 125 126 |
# File 'lib/covered/coverage.rb', line 119 def for_lines(line_numbers) counts = [nil] * @counts.size line_numbers.each do |line_number| counts[line_number] = @counts[line_number] end self.class.new(@source, counts, @annotations) end |
#freeze ⇒ Object
Freeze this coverage and its mutable collections.
171 172 173 174 175 176 177 178 |
# File 'lib/covered/coverage.rb', line 171 def freeze return self if frozen? @counts.freeze @annotations.freeze super end |
#fresh? ⇒ Boolean
Whether the source file has not changed since this coverage was recorded.
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/covered/coverage.rb', line 142 def fresh? if @source.modified_time.nil? # We don't know when the file was last modified, so we assume it is stale: return false end unless File.exist?(@source.path) # The file no longer exists, so we assume it is stale: return false end if @source.modified_time >= File.mtime(@source.path) # The file has not been modified since we last processed it, so we assume it is fresh: return true end return false end |
#mark(line_number, value = 1) ⇒ Object
Add the given execution count to one or more line numbers.
86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/covered/coverage.rb', line 86 def mark(line_number, value = 1) # As currently implemented, @counts is base-zero rather than base-one. # Line numbers generally start at line 1, so the first line, line 1, is at index 1. This means that index[0] is usually nil. Array(value).each_with_index do |value, index| offset = line_number + index if @counts[offset] @counts[offset] += value else @counts[offset] = value end end end |
#merge!(other) ⇒ Object
Merge another coverage object into this coverage object.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/covered/coverage.rb', line 101 def merge!(other) # If the counts are non-zero and don't match, that can indicate a problem. other.counts.each_with_index do |count, index| if count @counts[index] ||= 0 @counts[index] += count end end @annotations.merge!(other.annotations) do |line_number, a, b| Array(a) + Array(b) end end |
#missing_count ⇒ Object
The number of executable lines that were not executed.
225 226 227 |
# File 'lib/covered/coverage.rb', line 225 def missing_count executable_count - executed_count end |
#path ⇒ Object
The covered source path.
130 131 132 |
# File 'lib/covered/coverage.rb', line 130 def path @source.path end |
#path=(value) ⇒ Object
Assign the covered source path.
136 137 138 |
# File 'lib/covered/coverage.rb', line 136 def path= value @source.path = value end |
#print(output) ⇒ Object
Print a human-readable coverage summary.
231 232 233 |
# File 'lib/covered/coverage.rb', line 231 def print(output) output.puts "** #{executed_count}/#{executable_count} lines executed; #{percentage.to_f.round(2)}% covered." end |
#read(&block) ⇒ Object
Read the covered source.
165 166 167 |
# File 'lib/covered/coverage.rb', line 165 def read(&block) @source.read(&block) end |
#serialize(packer) ⇒ Object
Serialize this coverage object with the given packer.
254 255 256 257 258 |
# File 'lib/covered/coverage.rb', line 254 def serialize(packer) packer.write(@source) packer.write(@counts) packer.write(@annotations) end |
#to_a ⇒ Object
The raw coverage counts array.
182 183 184 |
# File 'lib/covered/coverage.rb', line 182 def to_a @counts end |
#to_s ⇒ Object
A human-readable representation of this coverage object.
237 238 239 |
# File 'lib/covered/coverage.rb', line 237 def to_s "\#<#{self.class} path=#{self.path} #{self.percentage.to_f.round(2)}% covered>" end |
#total ⇒ Object
The total number of executions across all tracked lines.
65 66 67 |
# File 'lib/covered/coverage.rb', line 65 def total counts.sum{|count| count || 0} end |
#zero? ⇒ Boolean
Whether this coverage has no executions.
188 189 190 |
# File 'lib/covered/coverage.rb', line 188 def zero? total.zero? end |