class TuneUpPlistToJunitUtils

Constants

END_FAILURE
END_SUCCESS
LOG_DEBUG

Constants that refer to the <Type> plist tag

LOG_DEFAULT
LOG_ERROR
SCREENSHOT
START_TEST

Public Instance Methods

generate_reports(plist_file_or_xml, junit_class_name) click to toggle source

Process the plist file and generates a JUnit style xml string

@param [String] plist_file_or_xml file name or xml of the UIAutomation plist file @param [String] junit_class_name the class name to append to each <testcase/> tag @return [String] the JUnit style xml

# File lib/tuneup_plist_to_junit_utils.rb, line 154
def generate_reports(plist_file_or_xml, junit_class_name)
  log_messages = parse_plist(plist_file_or_xml)
  tests = convert_log_messages_to_tests(log_messages)
  generate_junit_report(tests, junit_class_name)
end

Private Instance Methods

convert_log_messages_to_tests(log_messages) click to toggle source

Converts the log messages from the plist into an intermediate test array so that it can be processed with the (see generate_junit_report) method. The test hash should be similar to: {:name => 'test name',

:log_type => 'Pass|Fail|etc',
:log_message_type => 4|5|7,
:timestamp => '2014',
:messages => [ {:message => 'debug message',
                :log_type => 0|3|8,
                :log_message_type => 'ERROR|SCREENSHOT|DEBUG|ETC',
                :timestamp => '2014'} ]}

@param [Array] log_messages the unprocessed log messages from the plist @return [Array] the list of tests in an understandable format

# File lib/tuneup_plist_to_junit_utils.rb, line 51
def convert_log_messages_to_tests(log_messages)
  # The tests array to return
  tests = []

  # The current test we are processing
  current_test = nil

  log_messages.each do |log_message|
    # Pull our relevant fields from the log message in from the plist
    message = log_message['Message']
    log_type = log_message['LogType']
    timestamp = log_message['Timestamp']
    screenshot = log_message['Screenshot']
    log_message_type = log_message['Type']
    children = log_message['children']

    # If our log message type is the START type, initialize a new current test for us to use
    if !current_test && log_message_type == START_TEST
      current_test = {:name => message,
                      :log_type => log_type,
                      :log_message_type => log_message_type,
                      :timestamp => timestamp,
                      :messages => []}

      # In order to add a message to our current test, the message type can't be a begin or end node
    elsif current_test && log_message_type != END_FAILURE && log_message_type != END_SUCCESS && log_message_type != START_TEST
      message = log_message_type == SCREENSHOT ? screenshot : message
      message = "#{message} \nView Dump: \n#{JSON.pretty_generate(children)}\n" if children
      current_test[:messages] << {:message => message,
                                  :log_type => log_type,
                                  :log_message_type => log_message_type,
                                  :timestamp => timestamp}

      # If the current test is present and the message type is an end node, then add the current test to our tests and
      # reset the current test
    elsif current_test && (log_message_type == END_FAILURE || log_message_type == END_SUCCESS)
      current_test[:end_message_type] = log_message_type
      current_test[:elapsed_time] = timestamp.to_time - current_test[:timestamp].to_time
      tests << current_test
      current_test = nil
    end
  end

  tests
end
generate_junit_report(tests, junit_class_name) click to toggle source

After the tests have been processed into an intermediate state from (@see convert_log_messages_to_tests), the tests can then me transformed into a junit style xml output

@param tests [Array] array of processed plist tests as generated from (@see convert_log_messages_to_tests) @param [String] junit_class_name the class name to append to each <testcase/> tag @return [String] a junit xml string

# File lib/tuneup_plist_to_junit_utils.rb, line 103
def generate_junit_report(tests, junit_class_name)
  # Gather our root <testsuite/> tag information
  total_tests = tests.size
  total_errors = tests.reduce(0) { |sum, t| sum + t[:messages].count { |m| m[:log_message_type] == LOG_ERROR } }
  total_failures = tests.count { |t| t[:end_message_type] == END_FAILURE }
  starting_time = tests.empty? ? '' : tests[0][:timestamp]
  total_time = tests.reduce(0) { |sum, t| sum + t[:elapsed_time] }

  # Begin building our junit xml using Nokogiri
  builder = Nokogiri::XML::Builder.new do |xml|
    # Our root xml tag should be a <testsuite/> tag with the number of tests, duration, failures, etc
    xml.testsuite(:tests => total_tests, :errors => total_errors, :failures => total_failures, :timestamp => starting_time, :time => total_time) {
      # For each of our tests we want to create a <testcase/> tag
      tests.each do |test|
        xml.testcase(:name => test[:name], :time => test[:elapsed_time], :classname => junit_class_name) {

          # If the test case ended in a failure, we want to add a <failure/> tag
          if test[:end_message_type] == END_FAILURE
            xml.failure(:message => test[:name], :type => test[:log_type])
          end

          # Add the messages from the test to the test case tag
          test[:messages].each do |message|
            case message[:log_message_type]

              # For debug and screenshot, we'll convert the messages to a <system-out/> tag
              when LOG_DEBUG, LOG_DEFAULT, SCREENSHOT
                xml.send(:"system-out") {
                  xml.text message[:message]
                }

              # This is likely the LOG_ERROR case which we'll record it as an <error/> tag
              else
                xml.error(:message => message[:message], :type => message[:log_type])
            end
          end
        }
      end
    }
  end

  builder.to_xml
end
parse_plist(plist_file_or_xml) click to toggle source

Parses the plist file and returns just the test results array (log messages)

@param [String] plist_file_or_xml file name or xml of the UIAutomation plist file @return [Array] the unprocessed plist test results array, aka log messages

# File lib/tuneup_plist_to_junit_utils.rb, line 30
def parse_plist(plist_file_or_xml)
  plist_hash = Plist::parse_xml(plist_file_or_xml)

  # We want the 'All Samples' plist key which contains our test results
  plist_hash['All Samples']
end