@@ -46,6 +46,7 @@ class JUnitFormatter implements Formatter, Reporter, StrictAware {
46
46
47
47
public JUnitFormatter (URL out ) throws IOException {
48
48
this .out = new UTF8OutputStreamWriter (new URLOutputStream (out ));
49
+ TestCase .treatSkippedAsFailure = false ;
49
50
try {
50
51
doc = DocumentBuilderFactory .newInstance ().newDocumentBuilder ().newDocument ();
51
52
rootElement = doc .createElement ("testsuite" );
@@ -62,13 +63,15 @@ public void feature(Feature feature) {
62
63
63
64
@ Override
64
65
public void background (Background background ) {
65
- testCase = new TestCase ();
66
- root = testCase .createElement (doc );
66
+ if (!isCurrentTestCaseCreatedNameless ()) {
67
+ testCase = new TestCase ();
68
+ root = testCase .createElement (doc );
69
+ }
67
70
}
68
71
69
72
@ Override
70
73
public void scenario (Scenario scenario ) {
71
- if (testCase != null && testCase . scenario == null ) {
74
+ if (isCurrentTestCaseCreatedNameless () ) {
72
75
testCase .scenario = scenario ;
73
76
} else {
74
77
testCase = new TestCase (scenario );
@@ -80,6 +83,10 @@ public void scenario(Scenario scenario) {
80
83
increaseAttributeValue (rootElement , "tests" );
81
84
}
82
85
86
+ private boolean isCurrentTestCaseCreatedNameless () {
87
+ return testCase != null && testCase .scenario == null ;
88
+ }
89
+
83
90
@ Override
84
91
public void step (Step step ) {
85
92
if (testCase != null ) testCase .steps .add (step );
@@ -110,6 +117,10 @@ public void result(Result result) {
110
117
111
118
@ Override
112
119
public void before (Match match , Result result ) {
120
+ if (!isCurrentTestCaseCreatedNameless ()) {
121
+ testCase = new TestCase ();
122
+ root = testCase .createElement (doc );
123
+ }
113
124
handleHook (result );
114
125
}
115
126
@@ -119,10 +130,8 @@ public void after(Match match, Result result) {
119
130
}
120
131
121
132
private void handleHook (Result result ) {
122
- if (result .getStatus ().equals (Result .FAILED )) {
123
- testCase .results .add (result );
124
- }
125
-
133
+ testCase .hookResults .add (result );
134
+ testCase .updateElement (doc , root );
126
135
}
127
136
128
137
private void increaseAttributeValue (Element element , String attribute ) {
@@ -135,6 +144,7 @@ private void increaseAttributeValue(Element element, String attribute) {
135
144
136
145
@ Override
137
146
public void scenarioOutline (ScenarioOutline scenarioOutline ) {
147
+ testCase = null ;
138
148
}
139
149
140
150
@ Override
@@ -195,6 +205,7 @@ private TestCase() {
195
205
static boolean treatSkippedAsFailure = false ;
196
206
final List <Step > steps = new ArrayList <Step >();
197
207
final List <Result > results = new ArrayList <Result >();
208
+ final List <Result > hookResults = new ArrayList <Result >();
198
209
199
210
private Element createElement (Document doc ) {
200
211
return doc .createElement ("testcase" );
@@ -206,49 +217,31 @@ private void writeElement(Document doc, Element tc) {
206
217
}
207
218
208
219
public void updateElement (Document doc , Element tc ) {
209
- long totalDurationNanos = 0 ;
210
- for (Result r : results ) {
211
- totalDurationNanos += r .getDuration () == null ? 0 : r .getDuration ();
212
- }
213
-
214
- double totalDurationSeconds = ((double ) totalDurationNanos ) / 1000000000 ;
215
- String time = NUMBER_FORMAT .format (totalDurationSeconds );
216
- tc .setAttribute ("time" , time );
220
+ tc .setAttribute ("time" , calculateTotalDurationString ());
217
221
218
222
StringBuilder sb = new StringBuilder ();
223
+ addStepAndResultListing (sb );
219
224
Result skipped = null , failed = null ;
220
- for (int i = 0 ; i < steps .size (); i ++) {
221
- int length = sb .length ();
222
- Result result = results .get (i );
225
+ for (Result result : results ) {
223
226
if ("failed" .equals (result .getStatus ())) failed = result ;
224
227
if ("undefined" .equals (result .getStatus ()) || "pending" .equals (result .getStatus ())) skipped = result ;
225
- sb .append (steps .get (i ).getKeyword ());
226
- sb .append (steps .get (i ).getName ());
227
- for (int j = 0 ; sb .length () - length + j < 140 ; j ++) sb .append ("." );
228
- sb .append (result .getStatus ());
229
- sb .append ("\n " );
228
+ }
229
+ for (Result result : hookResults ) {
230
+ if (failed == null && "failed" .equals (result .getStatus ())) failed = result ;
230
231
}
231
232
Element child ;
232
233
if (failed != null ) {
233
- sb .append ("\n StackTrace:\n " );
234
- StringWriter sw = new StringWriter ();
235
- failed .getError ().printStackTrace (new PrintWriter (sw ));
236
- sb .append (sw .toString ());
237
- child = doc .createElement ("failure" );
238
- child .setAttribute ("message" , failed .getErrorMessage ());
239
- child .appendChild (doc .createCDATASection (sb .toString ()));
234
+ addStackTrace (sb , failed );
235
+ child = createElementWithMessage (doc , sb , "failure" , failed .getErrorMessage ());
240
236
} else if (skipped != null ) {
241
237
if (treatSkippedAsFailure ) {
242
- child = doc .createElement ("failure" );
243
- child .setAttribute ("message" , "The scenario has pending or undefined step(s)" );
238
+ child = createElementWithMessage (doc , sb , "failure" , "The scenario has pending or undefined step(s)" );
244
239
}
245
240
else {
246
- child = doc . createElement ("skipped" );
241
+ child = createElement (doc , sb , "skipped" );
247
242
}
248
- child .appendChild (doc .createCDATASection (sb .toString ()));
249
243
} else {
250
- child = doc .createElement ("system-out" );
251
- child .appendChild (doc .createCDATASection (sb .toString ()));
244
+ child = createElement (doc , sb , "system-out" );
252
245
}
253
246
254
247
Node existingChild = tc .getFirstChild ();
@@ -259,6 +252,54 @@ public void updateElement(Document doc, Element tc) {
259
252
}
260
253
}
261
254
255
+ private String calculateTotalDurationString () {
256
+ long totalDurationNanos = 0 ;
257
+ for (Result r : results ) {
258
+ totalDurationNanos += r .getDuration () == null ? 0 : r .getDuration ();
259
+ }
260
+ for (Result r : hookResults ) {
261
+ totalDurationNanos += r .getDuration () == null ? 0 : r .getDuration ();
262
+ }
263
+ double totalDurationSeconds = ((double ) totalDurationNanos ) / 1000000000 ;
264
+ return NUMBER_FORMAT .format (totalDurationSeconds );
265
+ }
266
+
267
+ private void addStepAndResultListing (StringBuilder sb ) {
268
+ for (int i = 0 ; i < steps .size (); i ++) {
269
+ int length = sb .length ();
270
+ String resultStatus = "not executed" ;
271
+ if (i < results .size ()) {
272
+ resultStatus = results .get (i ).getStatus ();
273
+ }
274
+ sb .append (steps .get (i ).getKeyword ());
275
+ sb .append (steps .get (i ).getName ());
276
+ do {
277
+ sb .append ("." );
278
+ } while (sb .length () - length < 76 );
279
+ sb .append (resultStatus );
280
+ sb .append ("\n " );
281
+ }
282
+ }
283
+
284
+ private void addStackTrace (StringBuilder sb , Result failed ) {
285
+ sb .append ("\n StackTrace:\n " );
286
+ StringWriter sw = new StringWriter ();
287
+ failed .getError ().printStackTrace (new PrintWriter (sw ));
288
+ sb .append (sw .toString ());
289
+ }
290
+
291
+ private Element createElementWithMessage (Document doc , StringBuilder sb , String elementType , String message ) {
292
+ Element child = createElement (doc , sb , elementType );
293
+ child .setAttribute ("message" , message );
294
+ return child ;
295
+ }
296
+
297
+ private Element createElement (Document doc , StringBuilder sb , String elementType ) {
298
+ Element child = doc .createElement (elementType );
299
+ child .appendChild (doc .createCDATASection (sb .toString ()));
300
+ return child ;
301
+ }
302
+
262
303
}
263
304
264
305
}
0 commit comments