summaryrefslogtreecommitdiffstats
path: root/tinyusb/test/vendor/ceedling/plugins/junit_tests_report/lib/junit_tests_report.rb
blob: a777d07d78c3baf6039d9d3a2e042ae1e5263fa6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
require 'ceedling/plugin'
require 'ceedling/constants'

class JunitTestsReport < Plugin

  def setup
    @results_list = {}
    @test_counter = 0
    @time_result = []
  end

  def post_test_fixture_execute(arg_hash)
    context = arg_hash[:context]

    @results_list[context] = [] if (@results_list[context].nil?)

    @results_list[context] << arg_hash[:result_file]
    @time_result << arg_hash[:shell_result][:time]

  end

  def post_build
    @results_list.each_key do |context|
      results = @ceedling[:plugin_reportinator].assemble_test_results(@results_list[context])

      artifact_filename = @ceedling[:configurator].project_config_hash[:junit_tests_report_artifact_filename] || 'report.xml'
      artifact_fullpath = @ceedling[:configurator].project_config_hash[:junit_tests_report_path] || File.join(PROJECT_BUILD_ARTIFACTS_ROOT, context.to_s)
      file_path = File.join(artifact_fullpath, artifact_filename)

      @ceedling[:file_wrapper].open( file_path, 'w' ) do |f|
        @testsuite_counter = 0
        @testcase_counter = 0
        suites = reorganise_results( results )

        write_header( results, f )
        suites.each{|suite| write_suite( suite, f ) }
        write_footer( f )
      end
    end
  end

  private

  def write_header( results, stream )
    results[:counts][:time] = @time_result.reduce(0, :+)
    stream.puts '<?xml version="1.0" encoding="utf-8" ?>'
    stream.puts('<testsuites tests="%<total>d" failures="%<failed>d" skipped="%<ignored>d" time="%<time>f">' % results[:counts])
  end

  def write_footer( stream )
    stream.puts '</testsuites>'
  end

  def reorganise_results( results )
    # Reorganise the output by test suite instead of by result
    suites = Hash.new{ |h,k| h[k] = {collection: [], total: 0, success: 0, failed: 0, ignored: 0, stdout: []} }
    results[:successes].each do |result|
      source = result[:source]
      name = source[:file].sub(/\..{1,4}$/, "")
      suites[name][:collection] += result[:collection].map{|test| test.merge(result: :success)}
      suites[name][:total] += result[:collection].length
      suites[name][:success] += result[:collection].length
    end
    results[:failures].each do |result|
      source = result[:source]
      name = source[:file].sub(/\..{1,4}$/, "")
      suites[name][:collection] += result[:collection].map{|test| test.merge(result: :failed)}
      suites[name][:total] += result[:collection].length
      suites[name][:failed] += result[:collection].length
    end
    results[:ignores].each do |result|
      source = result[:source]
      name = source[:file].sub(/\..{1,4}$/, "")
      suites[name][:collection] += result[:collection].map{|test| test.merge(result: :ignored)}
      suites[name][:total] += result[:collection].length
      suites[name][:ignored] += result[:collection].length
    end
    results[:stdout].each do |result|
      source = result[:source]
      name = source[:file].sub(/\..{1,4}$/, "")
      suites[name][:stdout] += result[:collection]
    end
    suites.map{|name, data| data.merge(name: name) }
  end

  def write_suite( suite, stream )
    suite[:time] = @time_result.shift
    stream.puts('  <testsuite name="%<name>s" tests="%<total>d" failures="%<failed>d" skipped="%<ignored>d" time="%<time>f">' % suite)

    suite[:collection].each do |test|
      write_test( test, stream )
    end

    unless suite[:stdout].empty?
      stream.puts('    <system-out>')
      suite[:stdout].each do |line|
        line.gsub!(/&/, '&amp;')
        line.gsub!(/</, '&lt;')
        line.gsub!(/>/, '&gt;')
        line.gsub!(/"/, '&quot;')
        line.gsub!(/'/, '&apos;')
        stream.puts(line)
      end
      stream.puts('    </system-out>')
    end

    stream.puts('  </testsuite>')
  end

  def write_test( test, stream )
    test[:test].gsub!('"', '&quot;')
    case test[:result]
    when :success
      stream.puts('    <testcase name="%<test>s" />' % test)
    when :failed
      stream.puts('    <testcase name="%<test>s">' % test)
      if test[:message].empty?
        stream.puts('      <failure />')
      else
        stream.puts('      <failure message="%s" />' % test[:message])
      end
      stream.puts('    </testcase>')
    when :ignored
      stream.puts('    <testcase name="%<test>s">' % test)
      stream.puts('      <skipped />')
      stream.puts('    </testcase>')
    end
  end
end