require 'libxml' require 'simplecov' class SimpleCov::Formatter::CoberturaFormatter RESULT_FILE_NAME = 'coverage.xml' DTD_URL = 'http://cobertura.sourceforge.net/xml/coverage-04.dtd' def format(result) xml = result_to_xml result result_path = File.join( SimpleCov.coverage_path, RESULT_FILE_NAME ) File.write(result_path, xml) puts "Coverage report generated for #{result.command_name} to #{result_path}" return xml end private def result_to_xml(result) root_dir = SimpleCov.root doc = LibXML::XML::Document.new() doc.root = LibXML::XML::Node.new('coverage') coverage = doc.root coverage['line-rate'] = (result.covered_percent/100).round(2).to_s coverage['branch-rate'] = '0' coverage['lines-covered'] = result.covered_lines.to_s coverage['lines-valid'] = (result.covered_lines + result.missed_lines).to_s coverage['branches-covered'] = '0' coverage['branches-valid'] = '0' coverage['branch-rate'] = '0' coverage['complexity'] = '0' coverage['version'] = '0' coverage['timestamp'] = Time.now.to_i.to_s coverage << sources = LibXML::XML::Node.new('sources') sources << source = LibXML::XML::Node.new('source') source << root_dir coverage << packages = LibXML::XML::Node.new('packages') packages << package = LibXML::XML::Node.new('package') package['name'] = 'simplecov-cobertura' package['line-rate'] = (result.covered_percent/100).round(2).to_s package['branch-rate'] = '0' package['complexity'] = '0' package << classes = LibXML::XML::Node.new('classes') result.files.each do |file| filename = file.filename path = filename.gsub(File.join(root_dir, ''), '') classes << class_ = LibXML::XML::Node.new('class') class_['name'] = File.basename(filename, '.*') class_['filename'] = path class_['line-rate'] = (file.covered_percent/100).round(2).to_s class_['branch-rate'] = '0' class_['complexity'] = '0' class_ << methods = LibXML::XML::Node.new('methods') class_ << lines = LibXML::XML::Node.new('lines') file.lines.each do |file_line| if file_line.covered? || file_line.missed? lines << line = LibXML::XML::Node.new('line') line['number'] = file_line.line_number.to_s line['branch'] = 'false' line['hits'] = file_line.coverage.to_s end end end text = doc.to_s lines = text.split("\n") lines.insert(1, "") lines.insert(2, '') lines.join("\n") end end