Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions ruby/lib/minitest/queue/build_status_reporter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,88 @@ module Queue
class BuildStatusReporter < Minitest::Reporters::BaseReporter
include ::CI::Queue::OutputHelpers

class JUnitReporter
def initialize(file, error_reports)
@file = file
@error_reports = error_reports
end

def write
File.open(@file, 'w+') do |file|
format_document(generate_document(@error_reports), file)
end
end

private

def generate_document(error_reports)
suites = error_reports.group_by { |error_report| error_report.test_suite }

doc = REXML::Document.new(nil, {
:prologue_quote => :quote,
:attribute_quote => :quote,
})
doc << REXML::XMLDecl.new('1.1', 'utf-8')

testsuites = doc.add_element('testsuites')
suites.each do |suite, error_reports|
add_tests_to(testsuites, suite, error_reports)
end

doc
end

def format_document(doc, io)
formatter = REXML::Formatters::Pretty.new
formatter.write(doc, io)
io << "\n"
end

def add_tests_to(testsuites, suite, error_reports)
testsuite = testsuites.add_element(
'testsuite',
'name' => suite,
'filepath' => Minitest::Queue.relative_path(error_reports.first.test_file),
'tests' => error_reports.count,
)

error_reports.each do |error_report|
attributes = {
'name' => error_report.test_name,
'classname' => error_report.test_suite,
}
attributes['lineno'] = error_report.test_line

testcase = testsuite.add_element('testcase', attributes)
add_xml_message_for(testcase, error_report)
rescue REXML::ParseException, RuntimeError => error
puts error
end
end

def add_xml_message_for(testcase, error_report)
failure = testcase.add_element('failure', 'type' => error_report.error_class, 'message' => truncate_message(error_report.to_s))
failure.add_text(REXML::CData.new(message_for(error_report)))
end

def truncate_message(message)
message.lines.first.chomp.gsub(/\e\[[^m]+m/, '')
end

def project_root_path_matcher
@project_root_path_matcher ||= %r{(?<=\s)#{Regexp.escape(Minitest::Queue.project_root)}/}
end

def message_for(error_report)
suite = error_report.test_suite
name = error_report.test_name
error = error_report.to_s

message_with_relative_paths = error.gsub(project_root_path_matcher, '')
"\nFailure:\n#{name}(#{suite}) [#{Minitest::Queue.relative_path(error_report.test_file)}]:\n#{message_with_relative_paths}\n"
end
end

def initialize(supervisor:, **options)
@supervisor = supervisor
@build = supervisor.build
Expand Down Expand Up @@ -110,6 +192,8 @@ def write_failure_file(file)
File.open(file, 'w') do |f|
JSON.dump(error_reports.map(&:to_h), f)
end
xml_file = File.join(File.dirname(file), "#{File.basename(file, File.extname(file))}.xml")
JUnitReporter.new(xml_file, error_reports).write
end

def write_flaky_tests_file(file)
Expand Down
4 changes: 4 additions & 0 deletions ruby/lib/minitest/queue/error_report.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ def test_name
@data[:test_name]
end

def error_class
@data[:error_class]
end

def test_and_module_name
@data[:test_and_module_name]
end
Expand Down
8 changes: 8 additions & 0 deletions ruby/test/integration/minitest_redis_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,14 @@ def test_redis_reporter_failure_file
.sort_by { |failure_report| failure_report[:test_line] }
.first

xml_file = File.join(File.dirname(failure_file), "#{File.basename(failure_file, File.extname(failure_file))}.xml")
xml_content = File.read(xml_file)
xml = REXML::Document.new(xml_content)
testcase = xml.elements['testsuites/testsuite/testcase[@name="test_bar"]']
assert_equal "ATest", testcase.attributes['classname']
assert_equal "test_bar", testcase.attributes['name']
assert_equal "test/dummy_test.rb", testcase.parent.attributes['filepath']
assert_equal "ATest", testcase.parent.attributes['name']

## output and test_file
expected = {
Expand Down
Loading