module Beaker::LoggerJunit

The Beaker JUnit Logger class This module handles message reporting from Beaker to the JUnit format

There is a specific pattern for using this class. Here’s a list of example usages:

Public Class Methods

copy_stylesheet_into_xml_dir(stylesheet, xml_file) click to toggle source

copies given stylesheet into the directory of the xml file given

@param [String] stylesheet Path to the stylesheet file @param [String] xml_file Path to the xml file

@return nil

# File lib/beaker/logger_junit.rb, line 69
def self.copy_stylesheet_into_xml_dir(stylesheet, xml_file)
  return if File.file?(File.join(File.dirname(xml_file), File.basename(stylesheet)))

  FileUtils.copy(stylesheet, File.join(File.dirname(xml_file), File.basename(stylesheet)))
end
escape_invalid_xml_chars(string) click to toggle source

Escape invalid XML UTF-8 codes from provided string, see www.w3.org/TR/xml/#charsets for valid character specification @param [String] string The string to remove invalid codes from @return [String] Properly escaped string

# File lib/beaker/logger_junit.rb, line 127
def self.escape_invalid_xml_chars string
  escaped_string = ""
  string.chars.each do |i|
    char_as_codestring = i.unpack("U*").join
    escaped_string << if self.is_valid_xml(char_as_codestring.to_i)
                        i
                      else
                        "\\#{char_as_codestring}"
                      end
  end
  escaped_string
end
finish(doc, xml_file) click to toggle source

writes out xml content for a doc

@param [REXML::Document] doc doc containing content to write @param [String] xml_file Path to the xml file to write

@return nil

# File lib/beaker/logger_junit.rb, line 41
def self.finish(doc, xml_file)
  # junit/name.xml will be created in a directory relative to the CWD

  File.open(xml_file, 'w') { |f| doc.write(f, 2) }
end
format_cdata(string) click to toggle source

Remove color codes and invalid XML characters from provided string @param [String] string The string to format @return [String] the correctly formatted cdata

# File lib/beaker/logger_junit.rb, line 119
def self.format_cdata string
  self.escape_invalid_xml_chars(Logger.strip_color_codes(string))
end
get_doc_for_filename(filename, stylesheet, already_exists) click to toggle source

gives the document object for a particular file

@param [String] filename Path to the file that you’re opening @param [String] stylesheet Path to the stylesheet for this doc @param [Boolean] already_exists Whether or not the file already exists

@return [REXML::Document] Doc that you want to write in

# File lib/beaker/logger_junit.rb, line 103
def self.get_doc_for_filename(filename, stylesheet, already_exists)
  if already_exists
    doc = REXML::Document.new File.open(filename)
  else
    # no existing file, create a new one
    doc = REXML::Document.new
    doc << REXML::XMLDecl.new(version = "1.0", encoding = "UTF-8")
    instruction_content = "type='text/xsl' href='#{File.basename(stylesheet)}'"
    doc << REXML::Instruction.new(target = "xml-stylesheet", content = instruction_content)
  end
  return doc
end
get_testsuites_from_doc(doc, name, already_existed) click to toggle source

sets up doc & gives us the suites for the testsuite named

@param [REXML::Document] doc Doc that you’re getting suites from @param [String] name Testsuite node name @param [Boolean] already_existed Whether or not the doc already existed

@return [Rexml::Element] testsuites

# File lib/beaker/logger_junit.rb, line 82
def self.get_testsuites_from_doc(doc, name, already_existed)
  # check to see if an output file already exists, if it does add or replace test suite data
  if already_existed
    suites = REXML::XPath.first(doc, "testsuites")
    # remove old data
    suites.elements.each("testsuite") do |e|
      suites.delete_element e if /#{name}/.match?(e.name)
    end
  else
    suites = doc.add_element(REXML::Element.new('testsuites'))
  end
  return suites
end
get_xml_contents(xml_file, name, stylesheet) click to toggle source

gets the xml doc & suites in order to build your xml output on top of

@param [String] xml_file Path to the xml file @param [String] name Name of the testsuite you’re writing @param [String] stylesheet Path to the stylesheet file

@return [REXML::Document] doc to use for your xml content @return [REXML::Element] suites to add your content to

# File lib/beaker/logger_junit.rb, line 55
def self.get_xml_contents(xml_file, name, stylesheet)
  self.copy_stylesheet_into_xml_dir(stylesheet, xml_file)
  xml_file_already_exists = File.file?(xml_file)
  doc = self.get_doc_for_filename(xml_file, stylesheet, xml_file_already_exists)
  suites = self.get_testsuites_from_doc(doc, name, xml_file_already_exists)
  return doc, suites
end
is_valid_xml(int) click to toggle source

Determine if the provided number falls in the range of accepted xml unicode values See www.w3.org/TR/xml/#charsets for valid for valid character specifications. @param [Integer] int The number to check against @return [Boolean] True, if the number corresponds to a valid xml unicode character, otherwise false

# File lib/beaker/logger_junit.rb, line 144
def self.is_valid_xml(int)
  return (int == 0x9 or
    int == 0xA or
    (int >= 0x0020 and int <= 0xD7FF) or
    (int >= 0xE000 and int <= 0xFFFD) or
    (int >= 0x100000 and int <= 0x10FFFF)
         )
end
write_xml(xml_file, stylesheet) { |doc, suites| ... } click to toggle source

writes the xml created in the block to the xml file given

Note: Error Recovery should take place in the caller of this method in order to recover gracefully

@param [String] xml_file Path to the xml file @param [String] stylesheet Path to the stylesheet file @param [Proc] block XML message construction block

@return nil

# File lib/beaker/logger_junit.rb, line 20
def self.write_xml(xml_file, stylesheet, &block)
  doc, suites = self.get_xml_contents(xml_file, name, stylesheet)

  if block
    case block.arity
    when 2
      yield doc, suites
    else
      raise ArgumentError.new "write_xml block takes 2 arguments, not #{block.arity}"
    end
  end

  self.finish(doc, xml_file)
end