Class: Minitest::Distributed::Reporters::JUnitXMLReporter

Inherits:
Reporter
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/minitest/distributed/reporters/junitxml_reporter.rb

Overview

Reporter that generates a JUnit XML report of the results it is presented.

The JUnitXML schema is not very well standardized, and many implementations deviate from the schema (see www.ibm.com/support/knowledgecenter/SSQ2R2_14.2.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html).

This JunitXML importer embraces this flexibility, and extends the format with some additional information that we can use to create more meaningful annotations. For instance, the information can be use to set annotations on your build system or for annotations using the GitHub checks API.

For the implementation, we use REXML to prevent the need of additional dependencies on this gem. We also use XML 1.1, which allows more characters to be valid. We are primarily interested in this so e is an allowed character, which is used for ANSI color coding.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io, options) ⇒ JUnitXMLReporter

Returns a new instance of JUnitXMLReporter.



29
30
31
32
33
# File 'lib/minitest/distributed/reporters/junitxml_reporter.rb', line 29

def initialize(io, options)
  super
  @report_path = T.let(options.fetch(:junitxml), String)
  @results = T.let(Hash.new { |hash, key| hash[key] = [] }, T::Hash[String, T::Array[Minitest::Result]])
end

Instance Attribute Details

#resultsObject (readonly)

Returns the value of attribute results.



26
27
28
# File 'lib/minitest/distributed/reporters/junitxml_reporter.rb', line 26

def results
  @results
end

Instance Method Details

#format_document(doc, io) ⇒ Object



69
70
71
72
73
# File 'lib/minitest/distributed/reporters/junitxml_reporter.rb', line 69

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

#generate_documentObject



57
58
59
60
61
62
63
64
65
66
# File 'lib/minitest/distributed/reporters/junitxml_reporter.rb', line 57

def generate_document
  doc = REXML::Document.new(nil, prologue_quote: :quote, attribute_quote: :quote)
  doc << REXML::XMLDecl.new("1.1", "utf-8")

  testsuites = doc.add_element("testsuites")
  results.each do |suite, tests|
    add_tests_to(testsuites, suite, tests)
  end
  doc
end

#record(result) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
# File 'lib/minitest/distributed/reporters/junitxml_reporter.rb', line 36

def record(result)
  case (result_type = ResultType.of(result))
  when ResultType::Passed, ResultType::Failed, ResultType::Error
    T.must(results[result.klass]) << result
  when ResultType::Skipped, ResultType::Requeued, ResultType::Discarded
    # We will not include skipped, requeued, and discarded tests in JUnitXML reports,
    # because they will not fail builds, but also didn't pass.
  else
    T.absurd(result_type)
  end
end

#reportObject



49
50
51
52
53
54
# File 'lib/minitest/distributed/reporters/junitxml_reporter.rb', line 49

def report
  FileUtils.mkdir_p(File.dirname(@report_path))
  File.open(@report_path, "w+") do |file|
    format_document(generate_document, file)
  end
end