Class: SimpleCov::Result

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/simplecov/result.rb,
lib/simplecov/result/source_file_builder.rb,
lib/simplecov/result/missing_source_files_reporter.rb,
sig/simplecov.rbs

Overview

A coverage result built from the Hash Ruby's Coverage library produces: filename => per-criterion coverage data.

Defined Under Namespace

Classes: FilterConfig, MissingSourceFilesReporter, SourceFileBuilder

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(original_result, command_name: nil, created_at: nil, not_loaded_files: Set.new, tracked_files: [], run_id: nil, worker_id: nil, report: false, filter_config: FilterConfig.new) ⇒ Result

Initialize a new SimpleCov::Result from given Coverage.result (a Hash of filenames each containing an array of coverage data).

filter_config defaults to the SimpleCov singleton's filter / group configuration so existing call sites are unchanged. Pass a custom FilterConfig to opt out — useful for tests that build synthetic Results and don't want the project's filters or groups applied.

Parameters:

  • original_result (Hash[String, untyped])
  • command_name: (String, nil) (defaults to: nil)
  • created_at: (Time, nil) (defaults to: nil)
  • not_loaded_files: (Set[String]) (defaults to: Set.new)
  • tracked_files: (_ToA[String]) (defaults to: [])
  • run_id: (String, nil) (defaults to: nil)
  • worker_id: (String, nil) (defaults to: nil)
  • report: (Boolean) (defaults to: false)
  • filter_config: (FilterConfig) (defaults to: FilterConfig.new)


64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/simplecov/result.rb', line 64

def initialize(original_result, command_name: nil, created_at: nil, not_loaded_files: Set.new,
               tracked_files: [], run_id: nil, worker_id: nil, report: false, filter_config: FilterConfig.new)
  @original_result = original_result.freeze
  @command_name = command_name
  @created_at = created_at
  (tracked_files, run_id, worker_id)
  @groups_config = filter_config.groups
  builder = SourceFileBuilder.new(original_result, not_loaded_files: not_loaded_files)
  @files = builder.call
  warn_about_missing_source_files(builder.missing_source_files, original_result.size) if report
  apply_cover_filters!(filter_config.cover_filters)
  apply_filters!(filter_config.filters)
end

Instance Attribute Details

#command_nameString

The command name that launched this result. Delegated to SimpleCov.command_name if not set manually

Returns:

  • (String)


129
130
131
# File 'lib/simplecov/result.rb', line 129

def command_name
  @command_name ||= SimpleCov.command_name
end

#created_atTime

Defines when this result has been created. Defaults to Time.now

Returns:

  • (Time)


123
124
125
# File 'lib/simplecov/result.rb', line 123

def created_at
  @created_at ||= Time.now
end

#filesFileList (readonly) Also known as: source_files

Returns all files that are applicable to this result (sans filters!) as instances of SimpleCov::SourceFile. Aliased as :source_files

Returns:



27
28
29
# File 'lib/simplecov/result.rb', line 27

def files
  @files
end

#original_resultHash[String, untyped] (readonly)

Returns the original Coverage.result used for this instance of SimpleCov::Result

Returns:

  • (Hash[String, untyped])


17
18
19
# File 'lib/simplecov/result.rb', line 17

def original_result
  @original_result
end

#run_idString? (readonly)

Invocation and top-level worker identities used only for parallel-result coordination. They do not change which fresh suites are merged.

Returns:

  • (String, nil)


24
25
26
# File 'lib/simplecov/result.rb', line 24

def run_id
  @run_id
end

#tracked_filesArray[String] (readonly)

Every path the producing process was told to track, loaded or not.

Returns:

  • (Array[String])


21
22
23
# File 'lib/simplecov/result.rb', line 21

def tracked_files
  @tracked_files
end

#worker_idString? (readonly)

Invocation and top-level worker identities used only for parallel-result coordination. They do not change which fresh suites are merged.

Returns:

  • (String, nil)


24
25
26
# File 'lib/simplecov/result.rb', line 24

def worker_id
  @worker_id
end

Class Method Details

.from_hash(hash) ⇒ Array[Result]

Loads a SimpleCov::Result#to_hash dump

Parameters:

  • hash (Hash[String, untyped])

Returns:



145
146
147
148
149
150
151
# File 'lib/simplecov/result.rb', line 145

def self.from_hash(hash)
  hash.map do |command_name, data|
    new(data.fetch("coverage"), command_name: command_name, created_at: Time.at(data["timestamp"]),
                                tracked_files: data["tracked_files"] || [], run_id: data["run_id"],
                                worker_id: data["worker_id"])
  end
end

Instance Method Details

#apply_cover_filters!(cover_filters) ⇒ void

This method returns an undefined value.

When any cover matcher is configured, restrict @files to source files matching at least one of them. With no cover matchers configured this is a no-op, preserving the historical "everything required, then filtered" universe.

Parameters:

  • cover_filters (Array[Filter[untyped]])


205
206
207
208
209
210
211
# File 'lib/simplecov/result.rb', line 205

def apply_cover_filters!(cover_filters)
  return if cover_filters.empty?

  @files = SimpleCov::FileList.new(
    @files.select { |source_file| cover_filters.any? { |filter| filter.matches?(source_file) } }
  )
end

#apply_filters!(filters) ⇒ void

This method returns an undefined value.

Applies the given filter chain to @files, dropping each source file that any filter matches.

Parameters:

  • filters (Array[Filter[untyped]])


195
196
197
198
199
# File 'lib/simplecov/result.rb', line 195

def apply_filters!(filters)
  filters.each do |filter|
    @files = SimpleCov::FileList.new(@files.reject { |source_file| filter.matches?(source_file) })
  end
end

#coverageHash[String, untyped]

A live result's criterion keys are Symbols (:lines, :branches), while entries parsed back from .resultset.json carry Strings, and the combiners read only String keys. Serialize with String keys so a live result merged against a stored entry contributes its counts instead of being silently dropped for every shared file.

Returns:

  • (Hash[String, untyped])


187
188
189
190
191
# File 'lib/simplecov/result.rb', line 187

def coverage
  original_result.slice(*filenames).transform_values do |file_coverage|
    file_coverage.transform_keys(&:to_s)
  end
end

#coverage_for(path) ⇒ Hash[criterion, CoverageStatistics]?

Returns the line:/branch:/method: coverage_statistics hash for the given file path, or nil if no matching source file is in this result. See SimpleCov::Result#source_file_for for path resolution.

Parameters:

  • path (String)

Returns:



95
96
97
# File 'lib/simplecov/result.rb', line 95

def coverage_for(path)
  source_file_for(path)&.coverage_statistics
end

#coverage_statisticsHash[criterion, CoverageStatistics] #coverage_statistics(arg0) ⇒ CoverageStatistics?

Overloads:



844
845
# File 'sig/simplecov.rbs', line 844

def coverage_statistics: () -> Hash[criterion, CoverageStatistics]
| (criterion) -> CoverageStatistics?

#coverage_statistics_by_fileHash[criterion, Array[CoverageStatistics]]

Returns:



846
# File 'sig/simplecov.rbs', line 846

def coverage_statistics_by_file: () -> Hash[criterion, Array[CoverageStatistics]]

#covered_branchesInteger?

Returns:

  • (Integer, nil)


839
# File 'sig/simplecov.rbs', line 839

def covered_branches: () -> Integer?

#covered_linesInteger?

Returns:

  • (Integer, nil)


836
# File 'sig/simplecov.rbs', line 836

def covered_lines: () -> Integer?

#covered_methodsInteger?

Returns:

  • (Integer, nil)


842
# File 'sig/simplecov.rbs', line 842

def covered_methods: () -> Integer?

#covered_percentFloat?

Delegated to #files (see FileList).

Parameters:

  • (criterion)

Returns:

  • (Float, nil)


832
# File 'sig/simplecov.rbs', line 832

def covered_percent: (?criterion) -> Float?

#covered_percentagesArray[Float?]

Returns:

  • (Array[Float?])


833
# File 'sig/simplecov.rbs', line 833

def covered_percentages: () -> Array[Float?]

#covered_strengthFloat?

Parameters:

  • (criterion)

Returns:

  • (Float, nil)


835
# File 'sig/simplecov.rbs', line 835

def covered_strength: (?criterion) -> Float?

#filenamesArray[String]

Returns all filenames for source files contained in this result

Returns:

  • (Array[String])


79
80
81
# File 'lib/simplecov/result.rb', line 79

def filenames
  files.map(&:filename)
end

#format!Object

Returns nil when formatting is opted out of (formatter false / formatters []); otherwise whatever the configured formatter returns.

Returns:

  • (Object)


109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/simplecov/result.rb', line 109

def format!
  formatter = SimpleCov.formatter
  return nil if formatter.nil?

  formatted = Formatter.format(formatter, self)
  # Recorded regardless of how the run ends, so a parent process's
  # clobber-prevention backstop can tell a report was produced even
  # when this run's checks or tests failed (unlike .last_run.json,
  # which only successful runs write).
  SimpleCov::ReportStamp.touch
  formatted
end

#groupsHash[String, FileList]

Returns a Hash of groups for this result. Define groups using SimpleCov.group 'Models', 'app/models'

Returns:



100
101
102
# File 'lib/simplecov/result.rb', line 100

def groups
  @groups ||= SimpleCov.grouped(files, groups: @groups_config)
end

#initialize_coordination_metadata(tracked_files, run_id, worker_id) ⇒ void

This method returns an undefined value.

Parameters:

  • tracked_files (_ToA[String])
  • run_id (String, nil)
  • worker_id (String, nil)


155
156
157
158
159
# File 'lib/simplecov/result.rb', line 155

def (tracked_files, run_id, worker_id)
  @tracked_files = tracked_files.to_a
  @run_id = run_id
  @worker_id = worker_id
end

#least_covered_fileString?

Returns:

  • (String, nil)


834
# File 'sig/simplecov.rbs', line 834

def least_covered_file: () -> String?

#missed_branchesInteger?

Returns:

  • (Integer, nil)


840
# File 'sig/simplecov.rbs', line 840

def missed_branches: () -> Integer?

#missed_linesInteger?

Returns:

  • (Integer, nil)


837
# File 'sig/simplecov.rbs', line 837

def missed_lines: () -> Integer?

#missed_methodsInteger?

Returns:

  • (Integer, nil)


843
# File 'sig/simplecov.rbs', line 843

def missed_methods: () -> Integer?

#source_file_for(path) ⇒ SourceFile?

Accepts an absolute or project-relative path (resolved against SimpleCov.root).

Parameters:

  • path (String)

Returns:



87
88
89
90
# File 'lib/simplecov/result.rb', line 87

def source_file_for(path)
  target = File.expand_path(path, SimpleCov.root)
  files.find { |file| file.filename == target }
end

#to_hashHash[String, Hash[String, untyped]]

Returns a hash representation of this Result that can be used for marshalling it into JSON

Returns:

  • (Hash[String, Hash[String, untyped]])


134
135
136
137
138
139
140
141
142
# File 'lib/simplecov/result.rb', line 134

def to_hash
  data = {"coverage" => coverage, "timestamp" => created_at.to_f} #: Hash[String, untyped]
  data["run_id"] = run_id if run_id
  data["worker_id"] = worker_id if worker_id
  # Omitted when empty so a run that tracks nothing writes the shape it
  # always has, and so the key only appears where it carries information.
  data["tracked_files"] = tracked_files unless tracked_files.empty?
  {command_name => data}
end

#total_branchesInteger?

Returns:

  • (Integer, nil)


838
# File 'sig/simplecov.rbs', line 838

def total_branches: () -> Integer?

#total_linesInteger?

Returns:

  • (Integer, nil)


847
# File 'sig/simplecov.rbs', line 847

def total_lines: () -> Integer?

#total_methodsInteger?

Returns:

  • (Integer, nil)


841
# File 'sig/simplecov.rbs', line 841

def total_methods: () -> Integer?

#warn_about_missing_source_files(missing, input_size) ⇒ void

This method returns an undefined value.

Parameters:

  • missing (Array[String])
  • input_size (Integer)


161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/simplecov/result.rb', line 161

def warn_about_missing_source_files(missing, input_size)
  return if missing.empty?

  # Emit only from the process that writes the final report. The merged
  # result is rebuilt in every parallel worker (each one stores its own
  # slice), so without this gate the warning prints once per worker — this
  # is the same signal SimpleCov uses to pick the process that runs the
  # report and threshold checks. It's intentionally not gated on
  # print_errors: the default at_fork sets print_errors false on workers,
  # and in many parallel runners the final-report process is itself a
  # worker, so a print_errors gate would suppress the one warning we want.
  # See issues #980 and #1171.
  return unless SimpleCov.final_result_process?

  MissingSourceFilesReporter.new(
    missing,
    input_size: input_size,
    every_entry_dropped: @files.empty? && missing.size == input_size
  ).warn!
end