• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.testng.reporters;
2 
3 import java.lang.reflect.Method;
4 import java.util.List;
5 import org.testng.ITestContext;
6 import org.testng.ITestNGMethod;
7 import org.testng.ITestResult;
8 import org.testng.TestListenerAdapter;
9 import org.testng.internal.Utils;
10 
11 /**
12  * Reporter printing out detailed messages about what TestNG
13  * is going to run and what is the status of what has been just run.
14  *
15  * To see messages from this reporter, either run Ant in verbose mode ('ant -v')
16  * or set verbose level to 5 or higher
17  *
18  * @author Lukas Jungmann
19  * @since 6.4
20  */
21 public class VerboseReporter extends TestListenerAdapter {
22 
23     /**
24      * Default prefix for messages printed out by this reporter
25      *
26      */
27     public static final String LISTENER_PREFIX = "[VerboseTestNG] ";
28     private String suiteName;
29     private final String prefix;
30 
31     private enum Status {
32 
33         SUCCESS(ITestResult.SUCCESS), FAILURE(ITestResult.FAILURE), SKIP(ITestResult.SKIP),
34         SUCCESS_PERCENTAGE_FAILURE(ITestResult.SUCCESS_PERCENTAGE_FAILURE), STARTED(ITestResult.STARTED);
35         private int status;
36 
Status(int i)37         private Status(int i) {
38             status = i;
39         }
40     }
41 
42     /**
43      * Default constructor
44      */
VerboseReporter()45     public VerboseReporter() {
46         this(LISTENER_PREFIX);
47     }
48 
49     /**
50      * Create VerboseReporter with custom prefix
51      *
52      * @param prefix prefix for messages printed out by this reporter
53      */
VerboseReporter(String prefix)54     public VerboseReporter(String prefix) {
55         this.prefix = prefix;
56     }
57 
58     @Override
beforeConfiguration(ITestResult tr)59     public void beforeConfiguration(ITestResult tr) {
60         super.beforeConfiguration(tr);
61         logTestResult(Status.STARTED, tr, true);
62     }
63 
64     @Override
onConfigurationFailure(ITestResult tr)65     public void onConfigurationFailure(ITestResult tr) {
66         super.onConfigurationFailure(tr);
67         logTestResult(Status.FAILURE, tr, true);
68     }
69 
70     @Override
onConfigurationSkip(ITestResult tr)71     public void onConfigurationSkip(ITestResult tr) {
72         super.onConfigurationSkip(tr);
73         logTestResult(Status.SKIP, tr, true);
74     }
75 
76     @Override
onConfigurationSuccess(ITestResult tr)77     public void onConfigurationSuccess(ITestResult tr) {
78         super.onConfigurationSuccess(tr);
79         logTestResult(Status.SUCCESS, tr, true);
80     }
81 
82     @Override
onTestStart(ITestResult tr)83     public void onTestStart(ITestResult tr) {
84         logTestResult(Status.STARTED, tr, false);
85     }
86 
87     @Override
onTestFailure(ITestResult tr)88     public void onTestFailure(ITestResult tr) {
89         super.onTestFailure(tr);
90         logTestResult(Status.FAILURE, tr, false);
91     }
92 
93     @Override
onTestFailedButWithinSuccessPercentage(ITestResult tr)94     public void onTestFailedButWithinSuccessPercentage(ITestResult tr) {
95         super.onTestFailedButWithinSuccessPercentage(tr);
96         logTestResult(Status.SUCCESS_PERCENTAGE_FAILURE, tr, false);
97     }
98 
99     @Override
onTestSkipped(ITestResult tr)100     public void onTestSkipped(ITestResult tr) {
101         super.onTestSkipped(tr);
102         logTestResult(Status.SKIP, tr, false);
103     }
104 
105     @Override
onTestSuccess(ITestResult tr)106     public void onTestSuccess(ITestResult tr) {
107         super.onTestSuccess(tr);
108         logTestResult(Status.SUCCESS, tr, false);
109     }
110 
111     @Override
onStart(ITestContext ctx)112     public void onStart(ITestContext ctx) {
113         suiteName = ctx.getName();//ctx.getSuite().getXmlSuite().getFileName();
114         log("RUNNING: Suite: \"" + suiteName + "\" containing \"" + ctx.getAllTestMethods().length + "\" Tests (config: " + ctx.getSuite().getXmlSuite().getFileName() + ")");
115     }
116 
117     @Override
onFinish(ITestContext context)118     public void onFinish(ITestContext context) {
119         logResults();
120         suiteName = null;
121     }
122 
resultsToMethods(List<ITestResult> results)123     private ITestNGMethod[] resultsToMethods(List<ITestResult> results) {
124         ITestNGMethod[] result = new ITestNGMethod[results.size()];
125         int i = 0;
126         for (ITestResult tr : results) {
127             result[i++] = tr.getMethod();
128         }
129         return result;
130     }
131 
132     /**
133      * Print out test summary
134      */
logResults()135     private void logResults() {
136         //
137         // Log test summary
138         //
139         ITestNGMethod[] ft = resultsToMethods(getFailedTests());
140         StringBuilder sb = new StringBuilder("\n===============================================\n");
141         sb.append("    ").append(suiteName).append("\n");
142         sb.append("    Tests run: ").append(Utils.calculateInvokedMethodCount(getAllTestMethods()));
143         sb.append(", Failures: ").append(Utils.calculateInvokedMethodCount(ft));
144         sb.append(", Skips: ").append(Utils.calculateInvokedMethodCount(resultsToMethods(getSkippedTests())));
145         int confFailures = getConfigurationFailures().size();
146         int confSkips = getConfigurationSkips().size();
147         if (confFailures > 0 || confSkips > 0) {
148             sb.append("\n").append("    Configuration Failures: ").append(confFailures);
149             sb.append(", Skips: ").append(confSkips);
150         }
151         sb.append("\n===============================================");
152         log(sb.toString());
153     }
154 
155     /**
156      * Log meaningful message for passed in arguments.
157      * Message itself is of form:
158      * $status: "$suiteName" - $methodDeclaration ($actualArguments) finished in $x ms ($run of $totalRuns)
159      *
160      * @param st status of passed in itr
161      * @param itr test result to be described
162      * @param isConfMethod is itr describing configuration method
163      */
logTestResult(Status st, ITestResult itr, boolean isConfMethod)164     private void logTestResult(Status st, ITestResult itr, boolean isConfMethod) {
165         StringBuilder sb = new StringBuilder();
166         StringBuilder succRate = null;
167         String stackTrace = "";
168         switch (st) {
169             case STARTED:
170                 sb.append("INVOKING");
171                 break;
172             case SKIP:
173                 sb.append("SKIPPED");
174                 stackTrace = itr.getThrowable() != null
175                         ? Utils.stackTrace(itr.getThrowable(), false)[0] : "";
176                 break;
177             case FAILURE:
178                 sb.append("FAILED");
179                 stackTrace = itr.getThrowable() != null
180                         ? Utils.stackTrace(itr.getThrowable(), false)[0] : "";
181                 break;
182             case SUCCESS:
183                 sb.append("PASSED");
184                 break;
185             case SUCCESS_PERCENTAGE_FAILURE:
186                 sb.append("PASSED with failures");
187                 break;
188             default:
189                 //not happen
190                 throw new RuntimeException("Unsupported test status:" + itr.getStatus());
191         }
192         if (isConfMethod) {
193             sb.append(" CONFIGURATION: ");
194         } else {
195             sb.append(": ");
196         }
197         ITestNGMethod tm = itr.getMethod();
198         int identLevel = sb.length();
199         sb.append(getMethodDeclaration(tm));
200         Object[] params = itr.getParameters();
201         Class[] paramTypes = tm.getMethod().getParameterTypes();
202         if (null != params && params.length > 0) {
203             // The error might be a data provider parameter mismatch, so make
204             // a special case here
205             if (params.length != paramTypes.length) {
206                 sb.append("Wrong number of arguments were passed by the Data Provider: found ");
207                 sb.append(params.length);
208                 sb.append(" but expected ");
209                 sb.append(paramTypes.length);
210             } else {
211                 sb.append("(value(s): ");
212                 for (int i = 0; i < params.length; i++) {
213                     if (i > 0) {
214                         sb.append(", ");
215                     }
216                     sb.append(Utils.toString(params[i], paramTypes[i]));
217                 }
218                 sb.append(")");
219 
220             }
221         }
222         if (Status.STARTED != st) {
223             sb.append(" finished in ");
224             sb.append(itr.getEndMillis() - itr.getStartMillis());
225             sb.append(" ms");
226             if (!Utils.isStringEmpty(tm.getDescription())) {
227                 sb.append("\n");
228                 for (int i = 0; i < identLevel; i++) {
229                     sb.append(" ");
230                 }
231                 sb.append(tm.getDescription());
232             }
233             if (tm.getInvocationCount() > 1) {
234                 sb.append(" (");
235                 sb.append(tm.getCurrentInvocationCount());
236                 sb.append(" of ");
237                 sb.append(tm.getInvocationCount());
238                 sb.append(")");
239             }
240             if (!Utils.isStringEmpty(stackTrace)) {
241                 sb.append("\n").append(stackTrace.substring(0, stackTrace.lastIndexOf(System.getProperty("line.separator"))));
242             }
243         } else {
244             if (!isConfMethod && tm.getInvocationCount() > 1) {
245                 sb.append(" success: ");
246                 sb.append(tm.getSuccessPercentage());
247                 sb.append("%");
248             }
249         }
250         log(sb.toString());
251     }
252 
log(String message)253     protected void log(String message) {
254         //prefix all output lines
255         System.out.println(message.replaceAll("(?m)^", prefix));
256     }
257 
258     /**
259      *
260      * @param method method to be described
261      * @return FQN of a class + method declaration for a method passed in
262      *      ie. test.triangle.CheckCount.testCheckCount(java.lang.String)
263      */
getMethodDeclaration(ITestNGMethod method)264     private String getMethodDeclaration(ITestNGMethod method) {
265         //see Utils.detailedMethodName
266         //perhaps should rather adopt the original method instead
267         Method m = method.getMethod();
268         StringBuilder buf = new StringBuilder();
269         buf.append("\"");
270         if (suiteName != null) {
271             buf.append(suiteName);
272         } else {
273             buf.append("UNKNOWN");
274         }
275         buf.append("\"");
276         buf.append(" - ");
277         if (method.isBeforeSuiteConfiguration()) {
278             buf.append("@BeforeSuite ");
279         } else if (method.isBeforeTestConfiguration()) {
280             buf.append("@BeforeTest ");
281         } else if (method.isBeforeClassConfiguration()) {
282             buf.append("@BeforeClass ");
283         } else if (method.isBeforeGroupsConfiguration()) {
284             buf.append("@BeforeGroups ");
285         } else if (method.isBeforeMethodConfiguration()) {
286             buf.append("@BeforeMethod ");
287         } else if (method.isAfterMethodConfiguration()) {
288             buf.append("@AfterMethod ");
289         } else if (method.isAfterGroupsConfiguration()) {
290             buf.append("@AfterGroups ");
291         } else if (method.isAfterClassConfiguration()) {
292             buf.append("@AfterClass ");
293         } else if (method.isAfterTestConfiguration()) {
294             buf.append("@AfterTest ");
295         } else if (method.isAfterSuiteConfiguration()) {
296             buf.append("@AfterSuite ");
297         }
298         buf.append(m.getDeclaringClass().getName());
299         buf.append(".");
300         buf.append(m.getName());
301         buf.append("(");
302         int i = 0;
303         for (Class<?> p : m.getParameterTypes()) {
304             if (i++ > 0) {
305                 buf.append(", ");
306             }
307             buf.append(p.getName());
308         }
309         buf.append(")");
310         return buf.toString();
311     }
312 
313     @Override
toString()314     public String toString() {
315         return "VerboseReporter{" + "suiteName=" + suiteName + '}';
316     }
317 }
318