1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.tap4j.ext.testng;
25
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.InputStream;
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.text.SimpleDateFormat;
33 import java.util.Date;
34 import java.util.Iterator;
35 import java.util.LinkedHashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.StringTokenizer;
40
41 import org.apache.commons.lang.StringUtils;
42 import org.testng.ITestResult;
43 import org.testng.xml.XmlClass;
44 import org.testng.xml.XmlInclude;
45 import org.testng.xml.XmlPackage;
46 import org.testng.xml.XmlSuite;
47 import org.testng.xml.XmlTest;
48 import org.yaml.snakeyaml.DumperOptions.LineBreak;
49 import org.yaml.snakeyaml.JavaBeanLoader;
50 import org.yaml.snakeyaml.reader.UnicodeReader;
51
52
53
54
55
56
57 @SuppressWarnings("unchecked")
58 public final class TestNGYAMLishUtils {
59
60
61
62
63 private static final int EXTRA_SPACE = 3;
64
65
66
67
68 public static final SimpleDateFormat ISO_8061_DATE_FORMAT = new SimpleDateFormat(
69 "yyyy-MM-dd'T'HH:mm:ss");
70
71 public static final String LINE_SEPARATOR = LineBreak.UNIX.getString();
72
73
74
75
76 private TestNGYAMLishUtils() {
77 super();
78 }
79
80
81
82
83
84 public static String getMessage(ITestResult testNgTestResult) {
85 return "TestNG Test " + testNgTestResult.getName();
86 }
87
88
89
90
91
92 public static String getSeverity(ITestResult testNgTestResult) {
93 String severity = "~";
94 if (testNgTestResult.getThrowable() != null) {
95 severity = "High";
96 }
97 return severity;
98 }
99
100
101
102
103
104 public static String getSource(ITestResult testNgTestResult) {
105 String source = testNgTestResult.getTestClass().getName() + "#" +
106 testNgTestResult.getMethod().getMethodName();
107 return source;
108 }
109
110
111
112
113
114
115 public static String getDatetime(ITestResult testNgTestResult) {
116 long ms = testNgTestResult.getStartMillis();
117 Date date = new Date(ms);
118 return ISO_8061_DATE_FORMAT.format(date);
119 }
120
121
122
123
124
125 public static String getFile(ITestResult testNgTestResult) {
126 return testNgTestResult.getTestClass().getName();
127 }
128
129
130
131
132
133 public static String getLine(ITestResult testNgTestResult) {
134 String line = "~";
135 Throwable testNGException = testNgTestResult.getThrowable();
136 if (testNGException != null) {
137 StringBuilder lookFor = new StringBuilder();
138 lookFor.append(testNgTestResult.getTestClass().getName());
139 lookFor.append('.');
140 lookFor.append(testNgTestResult.getMethod().getMethodName());
141 lookFor.append('(');
142 lookFor.append(testNgTestResult.getTestClass().getClass()
143 .getSimpleName());
144 lookFor.append(".java:");
145
146 StackTraceElement[] els = testNGException.getStackTrace();
147
148 for (int i = 0; i < els.length; i++) {
149 StackTraceElement el = els[i];
150 line = getLineNumberFromExceptionTraceLine(el.toString(),
151 lookFor.toString());
152 if (line.equals("") == Boolean.FALSE) {
153 break;
154 }
155 }
156 }
157 return line;
158 }
159
160
161
162
163
164
165
166
167 public static String getLineNumberFromExceptionTraceLine(String exceptionTraceLine,
168 String substrToSearch) {
169 String lineNumber = "";
170 int index = exceptionTraceLine.indexOf(substrToSearch);
171 if (index >= 0) {
172 int length = substrToSearch.length() + index;
173 if (exceptionTraceLine.lastIndexOf(')') > length) {
174 lineNumber = exceptionTraceLine
175 .substring(length, exceptionTraceLine.lastIndexOf(')'));
176 }
177 }
178 return lineNumber;
179 }
180
181
182
183
184
185 public static String getName(ITestResult testNgTestResult) {
186 return testNgTestResult.getName();
187 }
188
189
190
191
192
193 public static Object getExtensions(ITestResult testNgTestResult) {
194 Object extensions = null;
195 Set<String> attributeNames = testNgTestResult.getAttributeNames();
196 Iterator<String> iterator = attributeNames.iterator();
197 if (iterator.hasNext()) {
198 extensions = new LinkedHashMap<String, Object>();
199 for (; iterator.hasNext();) {
200 String attributeName = iterator.next();
201 Object attributeValue = testNgTestResult
202 .getAttribute(attributeName);
203 ((Map<String, Object>) extensions).put(attributeName,
204 attributeValue);
205 }
206 } else {
207 extensions = '~';
208 }
209 return extensions;
210 }
211
212
213
214
215
216 public static String getExpected(ITestResult testNgTestResult) {
217 Throwable throwable = testNgTestResult.getThrowable();
218
219 String expected = null;
220
221 if (throwable != null) {
222 StringWriter sw = new StringWriter();
223 PrintWriter pw = new PrintWriter(sw);
224 throwable.printStackTrace(pw);
225
226 String stringException = sw.toString();
227
228 String expectedToken = "expected:";
229 String butWasToken = " but was:";
230 int index = stringException.indexOf(expectedToken);
231
232 if (index > 0) {
233 expected = stringException
234 .substring(index + expectedToken.length(),
235 stringException.lastIndexOf(butWasToken));
236 index = stringException.indexOf(butWasToken);
237 }
238 }
239 return expected;
240 }
241
242
243
244
245
246 public static String getActual(ITestResult testNgTestResult) {
247 Throwable throwable = testNgTestResult.getThrowable();
248
249 String actual = "~";
250
251 if (throwable != null) {
252 StringWriter sw = new StringWriter();
253 PrintWriter pw = new PrintWriter(sw);
254 throwable.printStackTrace(pw);
255
256 String stringException = sw.toString();
257
258 String expectedToken = "expected:";
259 String butWasToken = " but was:";
260 int index = stringException.indexOf(expectedToken);
261 if (index > 0) {
262 index = stringException.indexOf(butWasToken);
263 int eolIndex = stringException.indexOf(System
264 .getProperty("line.separator"), index);
265 actual = stringException
266 .substring(index + butWasToken.length(), eolIndex);
267 }
268 }
269
270 return actual;
271 }
272
273
274
275
276
277
278
279 public static String getDisplay(ITestResult testNgTestResult) {
280
281 StringBuilder displayBuffer = new StringBuilder();
282
283 String expected = getExpected(testNgTestResult);
284 String actual = getActual(testNgTestResult);
285
286 if (StringUtils.isNotEmpty(expected) && StringUtils.isNotEmpty(actual)) {
287 int expectedLength = expected.length();
288 int actualLength = actual.length();
289
290 int greater = expectedLength;
291 if (actualLength > expectedLength) {
292 greater = actualLength;
293 } else if ("Expected".length() > greater) {
294 greater = "Expected".length();
295 }
296
297
298 int greaterPlus3 = greater + EXTRA_SPACE;
299
300 displayBuffer.append("+" + fill(greaterPlus3, '-') + "+" +
301 fill(greaterPlus3, '-') + "+");
302 displayBuffer.append(LINE_SEPARATOR);
303
304 displayBuffer.append("+" + fill(greater, "Got") + "|" +
305 fill(greater, "Expected") + "+");
306 displayBuffer.append(LINE_SEPARATOR);
307
308 displayBuffer.append("+" + fill(greaterPlus3, '-') + "+" +
309 fill(greaterPlus3, '-') + "+");
310 displayBuffer.append(LINE_SEPARATOR);
311
312 displayBuffer.append("+" + fill(greater, actual) + "|" +
313 fill(greater, expected) + "+");
314 displayBuffer.append(LINE_SEPARATOR);
315
316 displayBuffer.append("+" + fill(greaterPlus3, '-') + "+" +
317 fill(greaterPlus3, '-') + "+");
318
319 } else {
320 displayBuffer.append('~');
321 }
322
323 return displayBuffer.toString();
324
325 }
326
327
328
329
330
331 private static String fill(int greater, char c) {
332 StringBuilder sb = new StringBuilder();
333 for (int i = 0; i < greater; ++i) {
334 sb.append(Character.toString(c));
335 }
336 return sb.toString();
337 }
338
339
340
341
342
343 private static String fill(int greater, String s) {
344 StringBuilder sb = new StringBuilder();
345 sb.append(' ');
346 sb.append(s);
347 int newgreater = greater - s.length();
348 sb.append(fill(newgreater + 1, ' '));
349 sb.append(' ');
350 return sb.toString();
351 }
352
353
354
355
356
357 public static Object getDump(ITestResult testNgTestResult) {
358 Object returnObject = null;
359
360 Object[] parameters = testNgTestResult.getParameters();
361 if (parameters.length > 0) {
362 returnObject = new LinkedHashMap<String, Object>();
363 for (int i = 0; i < parameters.length; i++) {
364 Object parameter = parameters[i];
365 ((Map<String, Object>) returnObject).put("param" + (i + 1),
366 parameter);
367 }
368 } else {
369 returnObject = "~";
370 }
371 return returnObject.toString();
372 }
373
374
375
376
377
378 public static String getError(ITestResult testNgTestResult) {
379 String error = "~";
380
381 Throwable t = testNgTestResult.getThrowable();
382
383 if (t != null) {
384 error = t.getMessage();
385 }
386
387 return error;
388 }
389
390
391
392
393
394 public static String getBacktrace(ITestResult testNgTestResult) {
395 StringBuilder stackTrace = new StringBuilder();
396
397 Throwable throwable = testNgTestResult.getThrowable();
398
399 if (throwable != null) {
400 StringWriter sw = new StringWriter();
401 PrintWriter pw = new PrintWriter(sw);
402 throwable.printStackTrace(pw);
403 String stackTraceString = sw.toString();
404 stackTraceString = stackTraceString.trim().replaceAll("\\r\\n",
405 "\n");
406
407 StringTokenizer st = new StringTokenizer(stackTraceString,
408 LINE_SEPARATOR);
409 while (st.hasMoreTokens()) {
410 String stackTraceLine = st.nextToken();
411 stackTrace.append(stackTraceLine);
412 stackTrace.append(LINE_SEPARATOR);
413 }
414
415 } else {
416 stackTrace.append('~');
417 }
418
419 return stackTrace.toString();
420 }
421
422
423
424
425
426
427 public static StringBuilder toYaml(XmlSuite suite) {
428 StringBuilder result = new StringBuilder();
429
430 maybeAdd(result, "name", suite.getName(), null);
431 maybeAdd(result, "junit", suite.isJUnit(), XmlSuite.DEFAULT_JUNIT);
432 maybeAdd(result, "verbose", suite.getVerbose(),
433 XmlSuite.DEFAULT_VERBOSE);
434 maybeAdd(result, "threadCount", suite.getThreadCount(),
435 XmlSuite.DEFAULT_THREAD_COUNT);
436 maybeAdd(result, "dataProviderThreadCount",
437 suite.getDataProviderThreadCount(),
438 XmlSuite.DEFAULT_DATA_PROVIDER_THREAD_COUNT);
439 maybeAdd(result, "timeOut", suite.getTimeOut(), null);
440 maybeAdd(result, "parallel", suite.getParallel(),
441 XmlSuite.DEFAULT_PARALLEL);
442 maybeAdd(result, "skipFailedInvocationCounts",
443 suite.skipFailedInvocationCounts(),
444 XmlSuite.DEFAULT_SKIP_FAILED_INVOCATION_COUNTS);
445
446 toYaml(result, "parameters", "", suite.getParameters());
447 toYaml(result, suite.getPackages());
448
449 if (suite.getListeners().size() > 0) {
450 result.append("listeners:\n");
451 toYaml(result, " ", suite.getListeners());
452 }
453
454 if (suite.getPackages().size() > 0) {
455 result.append("packages:\n");
456 toYaml(result, suite.getPackages());
457 }
458 toYaml(result, "listeners", suite.getListeners());
459 if (suite.getTests().size() > 0) {
460 result.append("tests:\n");
461 for (XmlTest t : suite.getTests()) {
462 toYaml(result, " ", t);
463 }
464 }
465
466 if (suite.getChildSuites().size() > 0) {
467 result.append("suite-files:\n");
468 toYaml(result, " ", suite.getSuiteFiles());
469 }
470
471 return result;
472 }
473
474
475
476
477
478
479
480 private static void maybeAdd(StringBuilder sb, String key, Object value,
481 Object def) {
482 maybeAdd(sb, "", key, value, def);
483 }
484
485
486
487
488
489
490
491
492 private static void maybeAdd(StringBuilder sb, String sp, String key,
493 Object value, Object def) {
494 if (value != null && !value.equals(def)) {
495 sb.append(sp).append(key).append(": ").append(value.toString())
496 .append("\n");
497 }
498 }
499
500
501
502
503
504
505 private static void toYaml(StringBuilder result, String sp, XmlTest t) {
506 String sp2 = sp + " ";
507 result.append(sp).append("- name: ").append(t.getName()).append("\n");
508
509 maybeAdd(result, sp2, "junit", t.isJUnit(), XmlSuite.DEFAULT_JUNIT);
510 maybeAdd(result, sp2, "verbose", t.getVerbose(),
511 XmlSuite.DEFAULT_VERBOSE);
512 maybeAdd(result, sp2, "timeOut", t.getTimeOut(), null);
513 maybeAdd(result, sp2, "parallel", t.getParallel(),
514 XmlSuite.DEFAULT_PARALLEL);
515 maybeAdd(result, sp2, "skipFailedInvocationCounts",
516 t.skipFailedInvocationCounts(),
517 XmlSuite.DEFAULT_SKIP_FAILED_INVOCATION_COUNTS);
518
519 maybeAdd(result, "preserveOrder", sp2, t.getPreserveOrder(), "false");
520
521
522
523
524
525
526 toYaml(result, "parameters", sp2, t.getParameters());
527
528 if (t.getIncludedGroups().size() > 0) {
529 result.append(sp2).append("includedGroups: [ ")
530 .append(StringUtils.join(t.getIncludedGroups(), ","))
531 .append(" ]\n");
532 }
533
534 if (t.getExcludedGroups().size() > 0) {
535 result.append(sp2).append("excludedGroups: [ ")
536 .append(StringUtils.join(t.getExcludedGroups(), ","))
537 .append(" ]\n");
538 }
539
540 Map<String, List<String>> mg = t.getMetaGroups();
541 if (mg.size() > 0) {
542 result.append(sp2).append("metaGroups: { ");
543 boolean first = true;
544 for (String group : mg.keySet()) {
545 if (!first) {
546 result.append(", ");
547 }
548 result.append(group).append(": [ ")
549 .append(StringUtils.join(mg.get(group), ",")).append(" ] ");
550 first = false;
551 }
552 result.append(" }\n");
553 }
554
555 if (t.getXmlPackages().size() > 0) {
556 result.append(sp2).append("xmlPackages:\n");
557 for (XmlPackage xp : t.getXmlPackages()) {
558 toYaml(result, sp2 + " - ", xp);
559 }
560 }
561
562 if (t.getXmlClasses().size() > 0) {
563 result.append(sp2).append("classes:\n");
564 for (XmlClass xc : t.getXmlClasses()) {
565 toYaml(result, sp2 + " ", xc);
566 }
567 }
568
569 result.append("\n");
570 }
571
572
573
574
575
576
577 private static void toYaml(StringBuilder result, String sp2, XmlClass xc) {
578 List<XmlInclude> im = xc.getIncludedMethods();
579 List<String> em = xc.getExcludedMethods();
580 String name = im.size() > 0 || em.size() > 0 ? "name: " : "";
581
582 result.append(sp2).append("- " + name).append(xc.getName())
583 .append("\n");
584 if (im.size() > 0) {
585 result.append(sp2 + " includedMethods:\n");
586 for (XmlInclude xi : im) {
587 toYaml(result, sp2 + " ", xi);
588 }
589 }
590
591 if (em.size() > 0) {
592 result.append(sp2 + " excludedMethods:\n");
593 toYaml(result, sp2 + " ", em);
594 }
595 }
596
597
598
599
600
601
602 private static void toYaml(StringBuilder result, String sp2, XmlInclude xi) {
603 result.append(sp2 + "- " + xi.getName()).append("\n");
604 }
605
606
607
608
609
610
611 private static void toYaml(StringBuilder result, String sp,
612 List<String> strings) {
613 for (String l : strings) {
614 result.append(sp).append("- ").append(l).append("\n");
615 }
616 }
617
618
619
620
621
622
623 private static void toYaml(StringBuilder sb, List<XmlPackage> packages) {
624 if (packages.size() > 0) {
625 sb.append("packages:\n");
626 for (XmlPackage p : packages) {
627 toYaml(sb, " ", p);
628 }
629 }
630 for (XmlPackage p : packages) {
631 toYaml(sb, " ", p);
632 }
633 }
634
635
636
637
638
639
640 private static void toYaml(StringBuilder sb, String sp, XmlPackage p) {
641 sb.append(sp).append("name: ").append(p.getName()).append("\n");
642
643 generateIncludeExclude(sb, sp, "includes", p.getInclude());
644 generateIncludeExclude(sb, sp, "excludes", p.getExclude());
645 }
646
647
648
649
650
651
652
653 private static void generateIncludeExclude(StringBuilder sb, String sp,
654 String key, List<String> includes) {
655 if (includes.size() > 0) {
656 sb.append(sp).append(" ").append(key).append("\n");
657 for (String inc : includes) {
658 sb.append(sp).append(" ").append(inc);
659 }
660 }
661 }
662
663
664
665
666
667 private static void mapToYaml(Map<String, String> map, StringBuilder out) {
668 if (map.size() > 0) {
669 out.append("{ ");
670 boolean first = true;
671 for (Map.Entry<String, String> e : map.entrySet()) {
672 if (!first) {
673 out.append(", ");
674 }
675 first = false;
676 out.append(e.getKey() + ": " + e.getValue());
677 }
678 out.append(" }\n");
679 }
680 }
681
682
683
684
685
686
687
688 private static void toYaml(StringBuilder sb, String key, String sp,
689 Map<String, String> parameters) {
690 if (parameters.size() > 0) {
691 sb.append(sp).append(key).append(": ");
692 mapToYaml(parameters, sb);
693 }
694 }
695
696
697
698
699
700
701 @SuppressWarnings({
702 "unused", "rawtypes"
703 })
704 private static void addToMap(Map suite, String name, Map target) {
705 List<Map<String, String>> parameters = (List<Map<String, String>>) suite
706 .get(name);
707 if (parameters != null) {
708 for (Map<String, String> parameter : parameters) {
709 for (Map.Entry p : parameter.entrySet()) {
710 target.put(p.getKey(), p.getValue().toString());
711 }
712 }
713 }
714 }
715
716
717
718
719
720
721 @SuppressWarnings({
722 "unused", "rawtypes"
723 })
724 private static void addToList(Map suite, String name, List target) {
725 List<Map<String, String>> parameters = (List<Map<String, String>>) suite
726 .get(name);
727 if (parameters != null) {
728 for (Map<String, String> parameter : parameters) {
729 for (Map.Entry p : parameter.entrySet()) {
730 target.add(p.getValue().toString());
731 }
732 }
733 }
734 }
735
736
737
738
739
740
741
742 public static XmlSuite parse(String filePath, InputStream is)
743 throws FileNotFoundException {
744 JavaBeanLoader<XmlSuite> loader = new JavaBeanLoader<XmlSuite>(
745 XmlSuite.class);
746 if (is == null) {
747 is = new FileInputStream(new File(filePath));
748 }
749 XmlSuite result = loader.load(new UnicodeReader(is));
750
751
752 result.setFileName(filePath);
753
754
755
756
757 for (XmlTest t : result.getTests()) {
758 t.setSuite(result);
759 }
760
761 return result;
762 }
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782 }