diff --git a/bin/annotate_test_failures b/bin/annotate_test_failures index 26234baf..b00a6ac5 100755 --- a/bin/annotate_test_failures +++ b/bin/annotate_test_failures @@ -10,6 +10,7 @@ require 'shellwords' require 'net/http' require 'json' require 'optparse' +require_relative '../lib/test_failure' ################### # Parse arguments @@ -43,67 +44,6 @@ end # Helper methods ################### -# Here's how report.junit XML files look like for failure vs success: -# -# -# <unknown>:0 -# -# -# Traceback (most recent call last): ... -# -# -# -class TestFailure - attr_reader :classname, :name, :message, :details - attr_accessor :count - - def initialize(node) - @classname = node['classname'] - @name = node['name'] - failure_node = node.elements['failure'] || node.elements['error'] - @message = failure_node['message'] - @details = failure_node.text - @count = 1 - end - - def to_s - times = @count > 1 ? " (#{@count} times)" : '' - - # Do not render a code block for the failure details if there are none - formatted_details = if @details.strip.empty? - '' - else - <<~DETAILS - - ``` - #{@details} - ``` - DETAILS - end - - <<~ENTRY -
#{@name} in #{@classname}#{times} -
#{@message}
- #{formatted_details} -
- ENTRY - end - - def key - "#{@classname}.#{@name}" - end - - def ultimately_succeeds?(parent_node:) - all_same_test_nodes = parent_node.get_elements("testcase[@classname='#{@classname}' and @name='#{@name}']") - # If last node found for that test doesn't have a or child, then test ultimately succeeded. - !(all_same_test_nodes.last.elements['failure'] || all_same_test_nodes.last.elements['error']) - end - - def ==(other) - @classname == other.classname && @name == other.name && @message == other.message && @details == other.details - end -end - # Add a test_failure into a given array, or increment its count if it already exists # def record(test_failure, into:) diff --git a/lib/test_failure.rb b/lib/test_failure.rb new file mode 100644 index 00000000..f6f06c97 --- /dev/null +++ b/lib/test_failure.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +# Here's how report.junit XML files look like for failure vs success: +# +# +# <unknown>:0 +# +# +# Traceback (most recent call last): ... +# +# +# +class TestFailure + attr_reader :classname, :name, :message, :details + attr_accessor :count + + def initialize(node) + @classname = node['classname'] + @name = node['name'] + failure_node = node.elements['failure'] || node.elements['error'] + @message = failure_node['message'] + @details = failure_node.text + @count = 1 + end + + def to_s + times = @count > 1 ? " (#{@count} times)" : '' + + # Do not render a code block for the failure details if there are none + formatted_details = if @details.strip.empty? + '' + else + <<~DETAILS + + ``` + #{@details} + ``` + DETAILS + end + + <<~ENTRY +
#{@name} in #{@classname}#{times} +
#{@message}
+ #{formatted_details} +
+ ENTRY + end + + def key + "#{@classname}.#{@name}" + end + + def ultimately_succeeds?(parent_node:) + all_same_test_nodes = parent_node.get_elements("testcase[@classname='#{@classname}' and @name='#{@name}']") + # If last node found for that test doesn't have a or child, then test ultimately succeeded. + !(all_same_test_nodes.last.elements['failure'] || all_same_test_nodes.last.elements['error']) + end + + def ==(other) + @classname == other.classname && @name == other.name && @message == other.message && @details == other.details + end +end