VerboseReporter.java revision a7726191c419ea3086e36cf69207117c5a616e63
1/* 2 * To change this template, choose Tools | Templates 3 * and open the template in the editor. 4 */ 5package org.testng.reporters; 6 7import java.lang.reflect.Method; 8import java.util.List; 9import org.testng.ITestContext; 10import org.testng.ITestNGMethod; 11import org.testng.ITestResult; 12import org.testng.TestListenerAdapter; 13import org.testng.internal.Utils; 14 15/** 16 * 17 * @author Lukas Jungmann 18 */ 19//topic for discussion with Cedric 20//would be better to merge this class and org.testng.reporters.TextReporter 21//or keep this as separate listener? 22//main diferences are: 23// - format of the message being logged 24// - message is logged immediately instead of in onFinish event 25// - all messages have specific prefix 26public class VerboseReporter extends TestListenerAdapter { 27 28 public static final String LISTENER_PREFIX = "[VerboseTestNG] "; 29 private String testName; 30 private final String prefix; 31 32 public VerboseReporter() { 33 this(LISTENER_PREFIX); 34 } 35 36 public VerboseReporter(String prefix) { 37 this.prefix = prefix; 38 } 39 40 //see https://github.com/cbeust/testng/issues/124 41 private ITestResult r = null; 42 43 @Override 44 public void beforeConfiguration(ITestResult tr) { 45 if (tr.equals(r)) { 46 r = null; 47 System.out.println("BUG"); 48 return; 49 } 50 r = tr; 51 super.beforeConfiguration(tr); 52 logResult("INVOKING CONFIGURATION", detailedMethodName(tr.getMethod(), true)); 53 } 54 55 @Override 56 public void onConfigurationFailure(ITestResult tr) { 57 if (tr.equals(r)) { 58 r = null; 59 return; 60 } 61 r = tr; 62 super.onConfigurationFailure(tr); 63 Throwable ex = tr.getThrowable(); 64 String stackTrace = ""; 65 if (ex != null) { 66 stackTrace = Utils.stackTrace(ex, false)[0]; 67 } 68 long duration = tr.getEndMillis() - tr.getStartMillis(); 69 logResult("FAILED CONFIGURATION", detailedMethodName(tr.getMethod(), true), tr.getMethod().getDescription(), stackTrace, tr.getParameters(), tr.getMethod().getMethod().getParameterTypes(), duration); 70 } 71 72 @Override 73 public void onConfigurationSkip(ITestResult tr) { 74 if (tr.equals(r)) { 75 r = null; 76 System.out.println("BUG"); 77 return; 78 } 79 r = tr; 80 super.onConfigurationSkip(tr); 81 long duration = tr.getEndMillis() - tr.getStartMillis(); 82 logResult("SKIPPED CONFIGURATION", detailedMethodName(tr.getMethod(), true), tr.getMethod().getDescription(), null, tr.getParameters(), tr.getMethod().getMethod().getParameterTypes(), duration); 83 } 84 85 @Override 86 public void onConfigurationSuccess(ITestResult tr) { 87 if (tr.equals(r)) { 88 r = null; 89 return; 90 } 91 r = tr; 92 super.onConfigurationSuccess(tr); 93 long duration = tr.getEndMillis() - tr.getStartMillis(); 94 logResult("PASSED CONFIGURATION", detailedMethodName(tr.getMethod(), true), tr.getMethod().getDescription(), null, tr.getParameters(), tr.getMethod().getMethod().getParameterTypes(), duration); 95 } 96 97 @Override 98 public void onTestFailure(ITestResult tr) { 99 super.onTestFailure(tr); 100 Throwable ex = tr.getThrowable(); 101 String stackTrace = ""; 102 if (ex != null) { 103 stackTrace = Utils.stackTrace(ex, false)[0]; 104 } 105 logResult("FAILED", tr, stackTrace); 106 } 107 108 @Override 109 public void onTestFailedButWithinSuccessPercentage(ITestResult tr) { 110 super.onTestFailedButWithinSuccessPercentage(tr); 111 logResult("PASSED with failures", tr, null); 112 } 113 114 @Override 115 public void onTestSkipped(ITestResult tr) { 116 super.onTestSkipped(tr); 117 Throwable throwable = tr.getThrowable(); 118 logResult("SKIPPED", tr, throwable != null ? Utils.stackTrace(throwable, false)[0] : null); 119 } 120 121 @Override 122 public void onTestSuccess(ITestResult tr) { 123 super.onTestSuccess(tr); 124 logResult("PASSED", tr, null); 125 } 126 127 @Override 128 public void onStart(ITestContext ctx) { 129 testName = ctx.getName();//ctx.getSuite().getXmlSuite().getFileName(); 130 logResult("RUNNING", "Suite: \"" + testName + "\" containing \"" + ctx.getAllTestMethods().length + "\" Tests (config: " + ctx.getSuite().getXmlSuite().getFileName() + ")"); 131 132 } 133 134 @Override 135 public void onFinish(ITestContext context) { 136 logResults(); 137 testName = null; 138 } 139 140 @Override 141 public void onTestStart(ITestResult tr) { 142 logResult("INVOKING", detailedMethodName(tr.getMethod(), true)); 143 } 144 145 private ITestNGMethod[] resultsToMethods(List<ITestResult> results) { 146 ITestNGMethod[] result = new ITestNGMethod[results.size()]; 147 int i = 0; 148 for (ITestResult tr : results) { 149 result[i++] = tr.getMethod(); 150 } 151 return result; 152 } 153 154 private void logResults() { 155 // 156 // Log test summary 157 // 158 ITestNGMethod[] ft = resultsToMethods(getFailedTests()); 159 StringBuffer logBuf = new StringBuffer("\n===============================================\n"); 160 logBuf.append(" ").append(getName()).append("\n"); 161 logBuf.append(" Tests run: ").append(Utils.calculateInvokedMethodCount(getAllTestMethods())).append(", Failures: ").append(Utils.calculateInvokedMethodCount(ft)).append(", Skips: ").append(Utils.calculateInvokedMethodCount(resultsToMethods(getSkippedTests()))); 162 int confFailures = getConfigurationFailures().size(); 163 int confSkips = getConfigurationSkips().size(); 164 if (confFailures > 0 || confSkips > 0) { 165 logBuf.append("\n").append(" Configuration Failures: ").append(confFailures).append(", Skips: ").append(confSkips); 166 } 167 logBuf.append("\n==============================================="); 168 logResult("", logBuf.toString()); 169 } 170 171 private String getName() { 172 return testName; 173 } 174 175 private void logResult(String status, ITestResult tr, String stackTrace) { 176 long duration = tr.getEndMillis() - tr.getStartMillis(); 177 logResult(status, detailedMethodName(tr.getMethod(), true), tr.getMethod().getDescription(), stackTrace, tr.getParameters(), tr.getMethod().getMethod().getParameterTypes(), duration); 178 } 179 180 private void logResult(String status, String message) { 181 StringBuffer buf = new StringBuffer(); 182 if (Utils.isStringNotBlank(status)) { 183 buf.append(status).append(": "); 184 } 185 buf.append(message); 186// System.out.println("LOG: " + buf.toString()); 187 //prefix all output lines 188 System.out.println(buf.toString().replaceAll("(?m)^", prefix)); 189 } 190 191 private void logResult(String status, String name, String description, String stackTrace, Object[] params, Class[] paramTypes, long duration) { 192 StringBuffer msg = new StringBuffer(name); 193 if (null != params && params.length > 0) { 194 msg.append("(value(s): "); 195 // The error might be a data provider parameter mismatch, so make 196 // a special case here 197 if (params.length != paramTypes.length) { 198 msg.append(name + ": Wrong number of arguments were passed by " + "the Data Provider: found " + params.length + " but " + "expected " + paramTypes.length + ")"); 199 } else { 200 for (int i = 0; i < params.length; i++) { 201 if (i > 0) { 202 msg.append(", "); 203 } 204 msg.append(Utils.toString(params[i], paramTypes[i])); 205 } 206 msg.append(")"); 207 } 208 } 209 msg.append(" finished in "); 210 msg.append(duration); 211 msg.append(" ms"); 212 if (!Utils.isStringEmpty(description)) { 213 msg.append("\n"); 214 for (int i = 0; i < status.length() + 2; i++) { 215 msg.append(" "); 216 } 217 msg.append(description); 218 } 219 if (!Utils.isStringEmpty(stackTrace)) { 220 msg.append("\n").append(stackTrace.substring(0, stackTrace.lastIndexOf(System.getProperty("line.separator")))); 221 } 222 logResult(status, msg.toString()); 223 } 224 225 @Deprecated 226 //perhaps should rather to adopt the original method 227 private String detailedMethodName(ITestNGMethod method, boolean fqn) { 228 Method m = method.getMethod(); 229 StringBuffer buf = new StringBuffer(); 230 buf.append("\""); 231 if (getName() != null) { 232 buf.append(getName()); 233 } else { 234 buf.append("UNKNOWN"); 235 } 236 buf.append("\""); 237 buf.append(" - "); 238 if (method.isBeforeSuiteConfiguration()) { 239 buf.append("@BeforeSuite "); 240 } else if (method.isBeforeTestConfiguration()) { 241 buf.append("@BeforeTest "); 242 } else if (method.isBeforeClassConfiguration()) { 243 buf.append("@BeforeClass "); 244 } else if (method.isBeforeGroupsConfiguration()) { 245 buf.append("@BeforeGroups "); 246 } else if (method.isBeforeMethodConfiguration()) { 247 buf.append("@BeforeMethod "); 248 } else if (method.isAfterMethodConfiguration()) { 249 buf.append("@AfterMethod "); 250 } else if (method.isAfterGroupsConfiguration()) { 251 buf.append("@AfterGroups "); 252 } else if (method.isAfterClassConfiguration()) { 253 buf.append("@AfterClass "); 254 } else if (method.isAfterTestConfiguration()) { 255 buf.append("@AfterTest "); 256 } else if (method.isAfterSuiteConfiguration()) { 257 buf.append("@AfterSuite "); 258 } 259 buf.append(m.getDeclaringClass().getName()); 260 buf.append("."); 261 buf.append(m.getName()); 262 buf.append("("); 263 int i = 0; 264 for (Class<?> p : m.getParameterTypes()) { 265 if (i++ > 0) { 266 buf.append(", "); 267 } 268 buf.append(p.getName()); 269 } 270 buf.append(")"); 271 return buf.toString();//buf.append(fqn ? method.toString() : method.getMethodName()).toString(); 272 } 273 274 @Override 275 public String toString() { 276 return "VerboseReporter{" + "testName=" + testName + ", r=" + r + '}'; 277 } 278 279} 280