Class: Undercover::Result

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/undercover/result.rb

Overview

rubocop:disable Metrics/ClassLength

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node, coverage_adapter, file_path) ⇒ Result

rubocop:disable Metrics/MethodLength,Metrics/AbcSize



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/undercover/result.rb', line 14

def initialize(node, coverage_adapter, file_path) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
  @node = node
  @coverage_adapter = coverage_adapter
  file_cov = coverage_adapter.coverage(file_path)
  @coverage = file_cov.select do |ln, _|
    if first_line == last_line
      ln == first_line
    elsif node.empty_def? || node.is_a?(Imagen::Node::Block)
      ln >= first_line && ln <= last_line # rubocop:disable Style/ComparableBetween
    else
      ln > first_line && ln < last_line
    end
  end

  @file_path = file_path
  @flagged = false
end

Instance Attribute Details

#coverageObject (readonly)

Returns the value of attribute coverage.



9
10
11
# File 'lib/undercover/result.rb', line 9

def coverage
  @coverage
end

#coverage_adapterObject (readonly)

Returns the value of attribute coverage_adapter.



9
10
11
# File 'lib/undercover/result.rb', line 9

def coverage_adapter
  @coverage_adapter
end

#file_pathObject (readonly)

Returns the value of attribute file_path.



9
10
11
# File 'lib/undercover/result.rb', line 9

def file_path
  @file_path
end

#nodeObject (readonly)

Returns the value of attribute node.



9
10
11
# File 'lib/undercover/result.rb', line 9

def node
  @node
end

Instance Method Details

#coverage_fObject

Method ‘coverage_f` returns the total coverage of this Undercover::Result as a % value, taking into account missing branches. Line coverage will be counted as 0 if any branch is untested. rubocop:disable Metrics/AbcSize, Metrics/MethodLength



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/undercover/result.rb', line 58

def coverage_f
  return 0.0 if coverage.empty?

  lines = {}
  coverage.each do |ln, block_or_line_cov, _, branch_cov|
    if skipped?(file_path, ln)
      lines[ln] = 1
      next
    end

    lines[ln] = 1 unless lines.key?(ln)
    if branch_cov
      lines[ln] = 0 if branch_cov != 'ignored' && branch_cov.zero?
    elsif block_or_line_cov.zero?
      lines[ln] = 0
    end
  end

  (lines.values.sum.to_f / lines.keys.size).round(4)
end

#file_path_with_linesObject

rubocop:enable Metrics/MethodLength, Metrics/AbcSize



125
126
127
# File 'lib/undercover/result.rb', line 125

def file_path_with_lines
  "#{file_path}:#{first_line}:#{last_line}"
end

#flagObject



32
33
34
# File 'lib/undercover/result.rb', line 32

def flag
  @flagged = true
end

#flagged?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/undercover/result.rb', line 36

def flagged?
  @flagged
end

#inspectObject Also known as: to_s



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

def inspect
  "#<Undercover::Report::Result:#{object_id} " \
    "name: #{node.name}, coverage: #{coverage_f}>"
end

#pretty_printObject

TODO: move to formatter interface instead!



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/undercover/result.rb', line 100

def pretty_print
  pad = node.last_line.to_s.length
  pretty_print_lines.map do |covered, (num, line)|
    formatted_line = "#{num.to_s.rjust(pad)}: #{line}"
    if line.strip.empty?
      Rainbow(formatted_line).darkgray.dark
    elsif skipped?(file_path, num)
      Rainbow(formatted_line).darkgray.dark +
        Rainbow(' skipped with :nocov:').italic.darkgray.dark
    elsif covered.nil?
      Rainbow(formatted_line).darkgray.dark +
        Rainbow(' hits: n/a').italic.darkgray.dark
    elsif covered.positive?
      Rainbow(formatted_line).green +
        Rainbow(" hits: #{covered}").italic.darkgray.dark +
        count_covered_branches(num)
    elsif covered.zero?
      Rainbow(formatted_line).red +
        Rainbow(" hits: #{covered}").italic.darkgray.dark +
        count_covered_branches(num)
    end
  end.join("\n")
end

#pretty_print_linesObject

TODO: create a formatter interface instead and add some tests. TODO: re-enable rubocops rubocop:disable Metrics/MethodLength, Metrics/AbcSize

Zips coverage data (that doesn’t include any non-code lines) with full source for given code fragment (this includes non-code lines!)



86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/undercover/result.rb', line 86

def pretty_print_lines
  cov_enum = coverage.each
  cov_source_lines = (node.first_line..node.last_line).map do |line_no|
    cov_line_no = begin
      cov_enum.peek[0]
    rescue StopIteration
      -1
    end
    cov_enum.next[1] if cov_line_no == line_no
  end
  cov_source_lines.zip(node.source_lines_with_numbers)
end

#uncovered?(line_no) ⇒ Boolean

rubocop:disable Metrics/AbcSize

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/undercover/result.rb', line 40

def uncovered?(line_no) # rubocop:disable Metrics/AbcSize
  return false if skipped?(file_path, line_no)
  return true if coverage.empty?

  # check branch coverage for line_no
  coverage.each do |ln, _block, _branch, cov|
    return true if ln == line_no && cov && cov != 'ignored' && cov.zero?
  end

  # check line coverage for line_no
  line_cov = coverage.select { |cov| cov.size == 2 }.find { |ln, _cov| ln == line_no }
  line_cov && line_cov[1].zero?
end