Top Level Namespace

Defined Under Namespace

Modules: CoverUp

Instance Method Summary collapse

Instance Method Details

#coverage(options = {}, &block) ⇒ Object

This is the wrapper call that is used to run code coverage on Ruby code



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/cover-up.rb', line 73

def coverage(options = {}, &block)
  # We default the coverage scan to any Ruby files in the current directory, but that can be over-ridden
  files = options[:include].nil? ? Dir.glob("*.rb") : Dir.glob(options[:include])
  # This will hold the trace information
  trace = {}
  # Let's set a trace function so that every method call can be tracked
  set_trace_func(proc do |event, file, line, id, binding, klass|
    # We unify the filename to it's absolute path
    file = File.expand_path(file)
    # Add the line number that was hit for this file, if it hasn't already been hit
    trace[file] ||= []
    trace[file] << line unless trace[file].include?(line)
  end)
  # Now that we've set up the trace function, we can execute the code (trapping any exceptions)
  begin
    yield
  rescue Exception => ex
    puts "ERROR: exception \"#{ex.message}\" while running code coverage"
  end
  # Once that's run, we stop the trace function
  set_trace_func(nil)
  # Now we collate the results
  results = []
  # Loop through all files
  files.each do |file|
    # Expand the path, to unify it as we did before
    file = File.expand_path(file)
    # Grab the file data
    data = File.read(file)
    # Grab the amount of lines for the file
    lines = data.split("\n")
    # Keep track of which lines are hit, missed or excluded
    hit = []
    missed = []
    excluded = []
    # Loop through and analyse lines
    lines.each_with_index do |line, index|
      number = index + 1
      # If the line is a comment or an empty line, or it's the last line and it's "end", it's excluded
      if line.strip[0...1] == "#" || line.strip.empty? || (number == lines.length && line.strip == "end")
        excluded << number
      elsif (trace[file] || []).include?(number)
        # Otherwise, if it was in the trace, it was hit
        hit << number
      else
        # Lastly, if it isn't excluded or hit, it was missed
        missed << number
      end
    end
    # Create the file result with the file name, the total lines, the lines hit, the lines that weren't hit, and the lines that were excluded
    results << CoverUp::FileResult.new(file, lines.length, hit, missed, excluded)
  end
  # Return the coverage results
  CoverUp::Result.new(results)
end