lib/simplecov/coverage_statistics.rb
# frozen_string_literal: true module SimpleCov # Holds the individual data of a coverage result. # # This is uniform across coverage criteria as they all have: # # * total - how many things to cover there are (total relevant loc/branches) # * covered - how many of the coverables are hit # * missed - how many of the coverables are missed # * omitted - how many lines cannot be covered (blank lines/comments); only meaningful for line coverage # * percent - percentage as covered/missed # * strength - average hits per/coverable (will not exist for one shot lines format) class CoverageStatistics attr_reader :total, :covered, :missed, :omitted, :strength, :percent # Seed for the reduce in `.from`: covered, missed, omitted, strength. ZERO_STATS = [0, 0, 0, 0.0].freeze #: [Integer, Integer, Integer, Float] def self.from(coverage_statistics) sum_covered, sum_missed, sum_omitted, sum_total_strength = coverage_statistics.reduce(ZERO_STATS) do |(covered, missed, omitted, total_strength), stats| [ covered + stats.covered, missed + stats.missed, omitted + stats.omitted, # gotta remultiply with loc because files have different strength and loc # giving them a different "weight" in total total_strength + (stats.strength * stats.total) ] end new(covered: sum_covered, missed: sum_missed, omitted: sum_omitted, total_strength: sum_total_strength) end # Requires only covered, missed and strength to be initialized. # # Other values are computed by this class. def initialize(covered:, missed:, omitted: 0, total_strength: 0.0, percent: nil) @covered = covered @missed = missed @omitted = omitted @total = covered + missed @percent = percent || compute_percent(covered, missed, total) @strength = compute_strength(total_strength, total) end private def compute_percent(covered, missed, total) return 100.0 if missed.zero? covered * 100.0 / total end def compute_strength(total_strength, total) return 0.0 if total.zero? total_strength.to_f / total end end end