From 8fc9f2cb0708e999d1d3d8275430bb3e809a58fc Mon Sep 17 00:00:00 2001 From: David Wessman Date: Sun, 11 Feb 2024 15:08:33 +0100 Subject: [PATCH] Reporter: Outputs XML with Ox - Fixes part of #6 - Adds version tag to XML-document - Updates gemspec versions to work with Ruby 3 --- lib/minitest/junit.rb | 77 ++++++++++++++++++++------------- minitest-junit.gemspec | 6 +-- test/reporter_test.rb | 8 +++- test/testcase_formatter_test.rb | 7 ++- 4 files changed, 61 insertions(+), 37 deletions(-) diff --git a/lib/minitest/junit.rb b/lib/minitest/junit.rb index 02c187c..642bff1 100644 --- a/lib/minitest/junit.rb +++ b/lib/minitest/junit.rb @@ -1,6 +1,6 @@ require 'minitest/junit/version' require 'minitest' -require 'builder' +require 'ox' require 'socket' require 'time' @@ -28,38 +28,51 @@ def record(result) end def report - xml = Builder::XmlMarkup.new(:indent => 2) - xml.testsuite(name: 'minitest', - timestamp: @options[:timestamp], - hostname: @options[:hostname], - tests: @results.count, - skipped: @results.count { |result| result.skipped? }, - failures: @results.count { |result| !result.error? && result.failure }, - errors: @results.count { |result| result.error? }, - time: format_time(@results.inject(0) { |a, e| a += e.time })) do - @results.each { |result| format(result, xml) } - end - @io.puts xml.target! + doc = Ox::Document.new(:version => '1.0') + instruct = Ox::Instruct.new(:xml) + instruct[:version] = '1.0' + instruct[:encoding] = 'UTF-8' + doc << instruct + testsuite = Ox::Element.new('testsuite') + testsuite['name'] = @options[:name] || 'minitest' + testsuite['timestamp'] = @options[:timestamp] + testsuite['hostname'] = @options[:hostname] + testsuite['tests'] = @results.size + testsuite['skipped'] = @results.count(&:skipped?) + testsuite['failures'] = @results.count { |result| !result.error? && result.failure } + testsuite['errors'] = @results.count(&:error?) + testsuite['time'] = format_time(@results.map(&:time).inject(0, :+)) + @results.each do |result| + testsuite << format(result) + end + + doc << testsuite + @io << Ox.dump(doc) end def format(result, parent = nil) - xml = Builder::XmlMarkup.new(:target => parent, :indent => 2) - xml.testcase classname: format_class(result), - name: format_name(result), - time: format_time(result.time), - file: result.source_location.first, - line: result.source_location.last, - assertions: result.assertions do |t| - if result.skipped? - t.skipped message: result - else - result.failures.each do |failure| - type = classify failure - xml.tag! type, format_backtrace(failure), message: failure_message(result) - end + testcase = Ox::Element.new('testcase') + testcase['classname'] = format_class(result) + testcase['name'] = format_name(result) + testcase['time'] = format_time(result.time) + testcase['file'] = relative_to_cwd(result.source_location.first) + testcase['line'] = result.source_location.last + testcase['assertions'] = result.assertions + if result.skipped? + skipped = Ox::Element.new('skipped') + skipped['message'] = result + skipped << "" + testcase << skipped + else + result.failures.each do |failure| + failure_tag = Ox::Element.new(classify(failure)) + failure_tag['message'] = result + failure_tag << format_backtrace(failure) + testcase << failure_tag end end - xml + + testcase end private @@ -77,12 +90,16 @@ def working_directory end def failure_message(result) - "#{result.klass}##{result.name}: #{result.failure.to_s}" + "#{result.klass}##{result.name}: #{result.failure}" + end + + def relative_to_cwd(path) + path.sub(working_directory, '.') end def format_backtrace(failure) Minitest.filter_backtrace(failure.backtrace).map do |line| - line.gsub(working_directory, '.') + relative_to_cwd(line) end.join("\n") end diff --git a/minitest-junit.gemspec b/minitest-junit.gemspec index 425ac9a..3c35752 100644 --- a/minitest-junit.gemspec +++ b/minitest-junit.gemspec @@ -19,11 +19,11 @@ Gem::Specification.new do |spec| spec.require_paths = ['lib'] spec.add_dependency 'minitest', '~> 5.11' - spec.add_dependency 'builder', '~> 3.2' + spec.add_dependency 'ox', '~> 2', '>= 2.14.2' spec.add_development_dependency 'bundler' spec.add_development_dependency 'nokogiri' spec.add_development_dependency 'pry-byebug' - spec.add_development_dependency 'rake', '~> 10.3.2' - spec.add_development_dependency 'rubocop', '~> 0.24.1' + spec.add_development_dependency 'rake', '~> 13' + spec.add_development_dependency 'rubocop', '~> 1' end diff --git a/test/reporter_test.rb b/test/reporter_test.rb index 38deb36..fec4b48 100644 --- a/test/reporter_test.rb +++ b/test/reporter_test.rb @@ -1,18 +1,22 @@ require 'minitest/autorun' -require 'builder' require 'stringio' require 'time' require 'nokogiri' require 'minitest/junit' +class FakeTestName; end + class ReporterTest < Minitest::Test def test_no_tests_generates_an_empty_suite reporter = create_reporter reporter.report - assert_match(/^\n<\/testsuite>\n$/, reporter.output) + assert_match( + %r{\n}, + reporter.output + ) end def test_formats_each_successful_result_with_a_formatter diff --git a/test/testcase_formatter_test.rb b/test/testcase_formatter_test.rb index fcbba5f..2a9d937 100644 --- a/test/testcase_formatter_test.rb +++ b/test/testcase_formatter_test.rb @@ -17,7 +17,10 @@ def test_all_tests_generate_testcase_tag test = create_test_result reporter = create_reporter - assert_match test.name, reporter.format(test).target! + assert_match( + test.name, + reporter.format(test).attributes['name'] + ) end def test_skipped_tests_generates_skipped_tag @@ -28,7 +31,7 @@ def test_skipped_tests_generates_skipped_tag reporter.report - assert_match(/\n<\/testcase>\n<\/testsuite>\n/, reporter.output) + assert_match(/<\/skipped>\n\s+<\/testcase>\n\s*<\/testsuite>\n/, reporter.output) end def test_failing_tests_creates_failure_tag