JUnitReportReporter.java revision 3c331730b067c4367825ba373dbcf0be02df6fe5
11df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustpackage org.testng.reporters; 21df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 31df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.IReporter; 41df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.ISuite; 51df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.ISuiteResult; 61df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.ITestContext; 71df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.ITestResult; 81df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.collections.Lists; 91df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.collections.Maps; 101df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.internal.Utils; 111df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.internal.annotations.Sets; 121df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport org.testng.xml.XmlSuite; 131df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 1406adacf0626ec131a81c342d2787bb5019ff5669Cédric Beustimport java.io.File; 15ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beustimport java.io.PrintWriter; 16ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beustimport java.io.StringWriter; 171df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport java.net.InetAddress; 181df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport java.net.UnknownHostException; 191df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport java.util.Calendar; 201df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport java.util.Date; 211df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport java.util.List; 221df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport java.util.Map; 231df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport java.util.Properties; 241df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustimport java.util.Set; 251df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 261df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beustpublic class JUnitReportReporter implements IReporter { 271df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 281df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust @Override 291df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, 3006adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust String defaultOutputDirectory) { 311df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 3206adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust String outputDirectory = defaultOutputDirectory + File.separator + "junitreports"; 331df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust Map<Class<?>, Set<ITestResult>> results = Maps.newHashMap(); 343c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust Map<Class<?>, Set<ITestResult>> failedConfigurations = Maps.newHashMap(); 351df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust for (ISuite suite : suites) { 361df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust Map<String, ISuiteResult> suiteResults = suite.getResults(); 371df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust for (ISuiteResult sr : suiteResults.values()) { 381df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust ITestContext tc = sr.getTestContext(); 391df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust addResults(tc.getPassedTests().getAllResults(), results); 401df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust addResults(tc.getFailedTests().getAllResults(), results); 411df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust addResults(tc.getSkippedTests().getAllResults(), results); 423c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust addResults(tc.getFailedConfigurations().getAllResults(), failedConfigurations); 431df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 441df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 451df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 461df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust for (Map.Entry<Class<?>, Set<ITestResult>> entry : results.entrySet()) { 471df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust Class<?> cls = entry.getKey(); 481df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust Properties p1 = new Properties(); 491df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust p1.setProperty("name", cls.getName()); 501df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust Date timeStamp = Calendar.getInstance().getTime(); 511df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust p1.setProperty(XMLConstants.ATTR_TIMESTAMP, timeStamp.toGMTString()); 521df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 53ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust List<TestTag> testCases = Lists.newArrayList(); 541df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust int failures = 0; 55ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust int errors = 0; 567a4393234fa0020e2137fd82f7d23e77d8e26300Cédric Beust int testCount = 0; 577a4393234fa0020e2137fd82f7d23e77d8e26300Cédric Beust int totalTime = 0; 581df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 591df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust for (ITestResult tr: entry.getValue()) { 60ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust TestTag testTag = new TestTag(); 61ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust 621df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust if (tr.getStatus() != ITestResult.SUCCESS) failures++; 631df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust Properties p2 = new Properties(); 641df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust p2.setProperty("classname", tr.getMethod().getMethod().getDeclaringClass().getName()); 651df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust p2.setProperty("name", tr.getMethod().getMethodName()); 667a4393234fa0020e2137fd82f7d23e77d8e26300Cédric Beust long time = tr.getEndMillis() - tr.getStartMillis(); 677a4393234fa0020e2137fd82f7d23e77d8e26300Cédric Beust p2.setProperty("time", "" + time); 683c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust Throwable t = getThrowable(tr, failedConfigurations); 69ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust if (t != null) { 70ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust t.fillInStackTrace(); 71ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust StringWriter sw = new StringWriter(); 72ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust PrintWriter pw = new PrintWriter(sw); 73ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust t.printStackTrace(pw); 74ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust testTag.message = t.getMessage(); 75ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust testTag.type = t.getClass().getName(); 76ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust testTag.stackTrace = sw.toString(); 77ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust errors++; 78ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust } 797a4393234fa0020e2137fd82f7d23e77d8e26300Cédric Beust totalTime += time; 807a4393234fa0020e2137fd82f7d23e77d8e26300Cédric Beust testCount++; 81ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust testTag.properties = p2; 82ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust testCases.add(testTag); 831df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 841df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 851df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust p1.setProperty("failures", "" + failures); 86ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust p1.setProperty("errors", "" + errors); 871df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust p1.setProperty("name", cls.getName()); 887a4393234fa0020e2137fd82f7d23e77d8e26300Cédric Beust p1.setProperty("tests", "" + testCount); 897a4393234fa0020e2137fd82f7d23e77d8e26300Cédric Beust p1.setProperty("time", "" + totalTime); 901df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust try { 911df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust p1.setProperty(XMLConstants.ATTR_HOSTNAME, InetAddress.getLocalHost().getHostName()); 921df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } catch (UnknownHostException e) { 931df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust // ignore 941df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 951df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 961df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust // 971df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust // Now that we have all the information we need, generate the file 981df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust // 9906adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust XMLStringBuffer xsb = new XMLStringBuffer(""); 10006adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust xsb.setXmlDetails("1.0", "UTF-8"); 10106adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust xsb.addComment("Generated by " + getClass().getName()); 10206adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust 1031df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust xsb.push("testsuite", p1); 104ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust for (TestTag testTag : testCases) { 105ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust if (testTag.stackTrace == null) xsb.addEmptyElement("testcase", testTag.properties); 106ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust else { 107ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust xsb.push("testcase", testTag.properties); 108ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust 109ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust Properties p = new Properties(); 110d0df5e66f8b809f6d4c0fd6b77f70a2081508394Cédric Beust if (testTag.message != null) p.setProperty("message", testTag.message); 111ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust p.setProperty("type", testTag.type); 112ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust xsb.push("error", p); 113ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust xsb.addCDATA(testTag.stackTrace); 114ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust xsb.pop("error"); 115ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust 116ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust xsb.pop("testcase"); 117ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust } 1181df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 1191df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust xsb.pop("testsuite"); 12006adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust 12106adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust String fileName = "TEST-" + cls.getName() + ".xml"; 12206adacf0626ec131a81c342d2787bb5019ff5669Cédric Beust Utils.writeFile(outputDirectory, fileName, xsb.toXML()); 1231df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 1241df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 1251df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust// System.out.println(xsb.toXML()); 1261df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust// System.out.println(""); 1271df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 1281df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 1291df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 1303c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust private Throwable getThrowable(ITestResult tr, 1313c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust Map<Class<?>, Set<ITestResult>> failedConfigurations) { 1323c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust Throwable result = tr.getThrowable(); 1333c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust if (result == null && tr.getStatus() == ITestResult.SKIP) { 1343c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust // Attempt to grab the stack trace from the configuration failure 1353c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust for (Set<ITestResult> failures : failedConfigurations.values()) { 1363c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust for (ITestResult failure : failures) { 1373c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust // Naive implementation for now, eventually, we need to try to find 1383c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust // out if it's this failure that caused the skip since (maybe by 1393c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust // seeing if the class of the configuration method is assignable to 1403c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust // the class of the test method, although that's not 100% fool proof 1413c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust if (failure.getThrowable() != null) return failure.getThrowable(); 1423c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust } 1433c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust } 1443c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust } 1453c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust 1463c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust return result; 1473c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust } 1483c331730b067c4367825ba373dbcf0be02df6fe5Cédric Beust 149ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust class TestTag { 150ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust public Properties properties; 151ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust public String message; 152ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust public String type; 153ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust public String stackTrace; 154ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust } 155ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust 1561df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust private void addResults(Set<ITestResult> allResults, Map<Class<?>, Set<ITestResult>> out) { 1571df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust for (ITestResult tr : allResults) { 158ac22b08f9aca9ce90e075fcefe596b6694e857acCédric Beust Class<?> cls = tr.getMethod().getTestClass().getRealClass(); 1591df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust Set<ITestResult> l = out.get(cls); 1601df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust if (l == null) { 1611df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust l = Sets.newHashSet(); 1621df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust out.put(cls, l); 1631df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 1641df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust l.add(tr); 1651df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 1661df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust } 1671df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust 1681df80918ae7b818e0f8abb1b442d7e93c6c11f70Cédric Beust} 169