Simon Strandgaard said:
Thanks..
I have done some improvements to the original 'coverage.rb', so that
HTML is now generated. For an example have a look at:
http://neoneye.dk/parser.rb.coverage.html
As you may notice comments/arrays appears as if they are not executed!
How can I fix this?
Dunno whether it's worth the effort. I guess, comments could be fixed by
identifying regions of comment lines and marking them as reached if the
line above and below is reached. For arrays you could try to find the
matching "[" for a closing "]" and mark all lines in between if the line
of the closing "]" is marked.
Apart from that: nice output!
Ok.. I now propagate the marked status to comments.. output is much better
now. Still Arrays/Hashes/=begin=end needs to be fixed.
Try compare the new output agains the old:
http://neoneye.dk/parser.rb.coverage.ver2.html
Suggestions for improvements is welcome.. also patches is welcome.
For the courius; try to execute the attached code by
requiring it on the commandline.
ruby -rcoverage helloworld.rb
That should output a 'helloworld.rb.coverage.html' file.
--
Simon Strandgaard
module PrettyCoverage
class HTML
def initialize
@files = {}
end
def execute
puts "execute"
create_file_index
@files.each{|file, line_marked|
create_file(file, line_marked)
}
end
def mk_filename(name)
name+".coverage.html"
end
def create_file_index
output_filename = "index.html"
rows = []
@files.each{|file, line_marked|
filename = mk_filename(file)
rows << "<tr><td><a href=\"#{filename}\">#{file}</a></td></tr>"
}
result = rows.join("\n")
body = "<table>#{result}</table>"
title = "coverage"
css = <<EOCSS
body {
background-color: rgb(180, 180, 180);
}
div.marked {
background-color: rgb(185, 200, 200);
}
div.overview {
border-bottom: 8px solid black;
}
EOCSS
html = <<EOHTML
<html><head><title>#{title}</title>
<style type="text/css">#{css}</style></head>
<body>#{body}</body></html>
EOHTML
File.open(output_filename, "w+") do |f|
f.puts html
end
end
def add_file(file, line_marked)
percent = calc_coverage(line_marked)
printf("file=#{file} coverage=%02.1f%\n", percent)
# comments and empty lines.. we must
# propagate marked-value backwards
line_marked << ["", false]
(line_marked.size).downto(1) do |index|
line, marked = line_marked[index-1]
next_line, next_marked = line_marked[index]
if line =~ /^\s*(#|$)/ and marked == false
marked = next_marked
#line = "hest" + line
line_marked[index-1] = [line, marked]
end
end
line_marked.pop
@files[file] = line_marked
end
def calc_coverage(line_marked)
marked = line_marked.transpose[1]
n = marked.inject(0) {|r, i| (i) ? (r+1) : r }
percent = n.to_f * 100 / marked.size
end
def format_overview(file, line_marked)
percent = "%02.1f" % calc_coverage(line_marked)
html = <<EOHTML
<div class="overview">
<table>
<tr><td>filename</td><td><tt>#{file}</tt></td></tr>
<tr><td>coverage</td><td>#{percent}</td></tr>
</table>
</div>
EOHTML
html
end
def format_lines(line_marked)
result = ""
last = nil
end_of_div = ""
format_line = "%#{line_marked.size.to_s.size}d"
line_no = 1
line_marked.each {|(line, marked)|
if marked != last
result += end_of_div
case marked
when true
result += "<div class=\"marked\">"
end_of_div = "</div>"
when false
end_of_div = ""
end
end
result += (format_line % line_no) + " " + line + "\n"
last = marked
line_no += 1
}
result += end_of_div
"<pre>#{result}</pre>"
end
def create_file(file, line_marked)
output_filename = mk_filename(file)
puts "outputting #{output_filename.inspect}"
body =
format_overview(file, line_marked) +
format_lines(line_marked)
title = file + " - coverage"
css = <<EOCSS
body {
background-color: rgb(180, 180, 180);
}
div.marked {
background-color: rgb(185, 200, 200);
}
div.overview {
border-bottom: 8px solid black;
}
EOCSS
html = <<EOHTML
<html><head><title>#{title}</title>
<style type="text/css">#{css}</style></head>
<body>#{body}</body></html>
EOHTML
File.open(output_filename, "w+") do |f|
f.puts html
end
end
end
end
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
module COVERAGE__
COVER = {}
def self.trace_func(event, file, line, id, binding, klass)
case event
when 'c-call', 'c-return', 'class'
return
end
COVER[file] ||= []
COVER[file][line] ||= 0
COVER[file][line] += 1
end
END {
set_trace_func(nil)
printer = PrettyCoverage::HTML.new
COVER.each do |file, lines|
next if SCRIPT_LINES__.has_key?(file) == false
lines = SCRIPT_LINES__[file]
covers = COVER[file]
line_status = []
0.upto(lines.size - 1) do |c|
line = lines[c].chomp
marked = false
if covers[c + 1]
marked = true
elsif /^\s*(?:begin\s*(?:#.*)?|ensure\s*(?:#.*)?|else\s*(?:#.*)?)$/ =~ line and covers[c + 1 + 1]
covers[c + 1] = covers[c + 1 + 1]
marked = true
elsif /^\s*(?:end|})\s*$/ =~ line && covers[c + 1 - 1]
covers[c + 1] = covers[c + 1 - 1]
marked = true
end
line_status << [line, marked]
end
printer.add_file(file, line_status)
end
printer.execute
}
set_trace_func(COVERAGE__.method
trace_func).to_proc)
end