/
junit.rb
155 lines (128 loc) · 4.63 KB
/
junit.rb
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
require 'cucumber/formatter/ordered_xml_markup'
require 'cucumber/formatter/io'
require 'fileutils'
module Cucumber
module Formatter
# The formatter used for <tt>--format junit</tt>
class Junit
include Io
class UnNamedFeatureError < StandardError
def initialize(feature_file)
super("The feature in '#{feature_file}' does not have a name. The JUnit XML format requires a name for the testsuite element.")
end
end
def initialize(step_mother, io, options)
@reportdir = ensure_dir(io, "junit")
@options = options
end
def before_feature(feature)
@current_feature = feature
@failures = @errors = @tests = @skipped = 0
@builder = OrderedXmlMarkup.new( :indent => 2 )
@time = 0
end
def before_feature_element(feature_element)
@in_examples = Ast::ScenarioOutline === feature_element
end
def after_feature(feature)
@testsuite = OrderedXmlMarkup.new( :indent => 2 )
@testsuite.instruct!
@testsuite.testsuite(
:failures => @failures,
:errors => @errors,
:skipped => @skipped,
:tests => @tests,
:time => "%.6f" % @time,
:name => @feature_name ) do
@testsuite << @builder.target!
end
write_file(feature_result_filename(feature.file), @testsuite.target!)
end
def before_background(*args)
@in_background = true
end
def after_background(*args)
@in_background = false
end
def feature_name(keyword, name)
raise UnNamedFeatureError.new(@current_feature.file) if name.empty?
lines = name.split(/\r?\n/)
@feature_name = lines[0]
end
def scenario_name(keyword, name, file_colon_line, source_indent)
@scenario = (name.nil? || name == "") ? "Unnamed scenario" : name.split("\n")[0]
@output = "#{keyword}: #{@scenario}\n\n"
end
def before_steps(steps)
@steps_start = Time.now
end
def after_steps(steps)
return if @in_background || @in_examples
duration = Time.now - @steps_start
if steps.failed?
steps.each { |step| @output += "#{step.keyword}#{step.name}\n" }
@output += "\nMessage:\n"
end
build_testcase(duration, steps.status, steps.exception)
end
def before_examples(*args)
@header_row = true
@in_examples = true
end
def after_examples(*args)
@in_examples = false
end
def before_table_row(table_row)
return unless @in_examples
@table_start = Time.now
end
def after_table_row(table_row)
return unless @in_examples and Cucumber::Ast::OutlineTable::ExampleRow === table_row
duration = Time.now - @table_start
unless @header_row
name_suffix = " (outline example : #{table_row.name})"
if table_row.failed?
@output += "Example row: #{table_row.name}\n"
@output += "\nMessage:\n"
end
build_testcase(duration, table_row.status, table_row.exception, name_suffix)
end
@header_row = false if @header_row
end
private
def build_testcase(duration, status, exception = nil, suffix = "")
@time += duration
classname = "#{@feature_name}.#{@scenario}"
name = "#{@scenario}#{suffix}"
pending = [:pending, :undefined].include?(status)
passed = (status == :passed || (pending && !@options[:strict]))
@builder.testcase(:classname => classname, :name => name, :time => "%.6f" % duration) do
unless passed
@builder.failure(:message => "#{status.to_s} #{name}", :type => status.to_s) do
@builder.cdata! @output
@builder.cdata!(format_exception(exception)) if exception
end
@failures += 1
end
if passed and (status == :skipped || pending)
@builder.skipped
@skipped += 1
end
end
@tests += 1
end
def format_exception(exception)
(["#{exception.message} (#{exception.class})"] + exception.backtrace).join("\n")
end
def feature_result_filename(feature_file)
File.join(@reportdir, "TEST-#{basename(feature_file)}.xml")
end
def basename(feature_file)
File.basename(feature_file.gsub(/[\\\/]/, '-'), '.feature')
end
def write_file(feature_filename, data)
File.open(feature_filename, 'w') { |file| file.write(data) }
end
end
end
end