Best Testng code snippet using org.testng.reporters.EmailableReporter2.writeTableHeader
Source:SpireEmailReportV2.java  
...233            writer.print("<tr bgcolor='00FFFF'>");234            writer.print("<th>Total</th>");235            writeTableData(integerFormat.format(totalTests), "num");236            237            writeTableHeader(integerFormat.format(totalPassedTests), "num");            238            writeTableHeader(integerFormat.format(totalFailedTests), (totalFailedTests > 0 ? "num attn" : "num"));239            writeTableHeader(integerFormat.format(totalSkippedTests), (totalSkippedTests > 0 ? "num attn" : "num"));240            /*writeTableHeader(decimalFormat.format(millisecondsToSeconds(totalDuration)), "num");*/241            writeTableHeader(ContextManager.getThreadContext().getTime(), "num");242            writeTableData(decimalFormat.format((((double)totalPassedTests/(double)totalTests))*100)+"%", "num");243            writer.print("<th colspan=\"2\"></th>");244            writer.print("</tr>");245        }246        writer.print("</table>");247        writer.print("</center>");248        249        if (totalTests==totalSkippedTests) {250			251        	writer.print("<br/><font color='red'><center><b><I>ALL TESTS SKIPPED DUE TO APPLICATION IS DOWN</I></b></<center></font>");252            253		}254        255        if (ContextManager.getGlobalContext()!=null && ContextManager.getGlobalContext().getHostAddress() !=null) {256        	writer.print("<br/><font color='black'><center><b><I>** APPLICATION SERVER USED TO RUN TESTS #     '"+ContextManager.getGlobalContext().getHostAddress()+"'</I></b></<center></font>");257		}258    }259    /**260     * Writes a summary of all the test scenarios.261     */262    protected void writeScenarioSummary() {263        writer.print("<center>");264        writer.print("<table>");265        writer.print("<thead>");266        writer.print("<tr>");267        writer.print("<th>Class</th>");268        writer.print("<th>Method</th>");269        writer.print("<th>Name</th>");270        writer.print("<th>Start</th>");271        writer.print("<th>Seconds</th>");272        writer.print("</tr>");273        writer.print("</thead>");274        int testIndex = 0;275        int scenarioIndex = 0;276        for (SuiteResult suiteResult : suiteResults) {277            writer.print("<tbody><tr><th colspan=\"5\">");278            writer.print(Utils.escapeHtml(suiteResult.getSuiteName()));279            writer.print("</th></tr></tbody>");280            for (TestResult testResult : suiteResult.getTestResults()) {281                writer.print("<tbody id=\"t");282                writer.print(testIndex);283                writer.print("\">");284 285                String testName = Utils.escapeHtml(testResult.getTestName());286                scenarioIndex += writeScenarioSummary(testName287                                + " — failed (configuration methods)",288                        testResult.getFailedConfigurationResults(), "failed",289                        scenarioIndex290                );291                scenarioIndex += writeScenarioSummary(testName292                                + " — failed", testResult.getFailedTestResults(),293                        "failed", scenarioIndex294                );295                scenarioIndex += writeScenarioSummary(testName296                                + " — skipped (configuration methods)",297                        testResult.getSkippedConfigurationResults(), "skipped",298                        scenarioIndex299                );300                scenarioIndex += writeScenarioSummary(testName301                                + " — skipped",302                        testResult.getSkippedTestResults(), "skipped",303                        scenarioIndex304                );305                scenarioIndex += writeScenarioSummary(testName306                                + " — passed", testResult.getPassedTestResults(),307                        "passed", scenarioIndex308                );309                writer.print("</tbody>");310                testIndex++;311            }312        }313        writer.print("</table>");314        writer.print("<center>");315    }316    /**317     * Writes the scenario summary for the results of a given state for a single318     * test.319     */320    private int writeScenarioSummary(String description, List<ClassResult> classResults,321                                     String cssClassPrefix, int startingScenarioIndex) {322        int scenarioCount = 0;323        if (!classResults.isEmpty()) {324            writer.print("<tr><th colspan=\"5\">");325            writer.print(description);326            writer.print("</th></tr>");327            int scenarioIndex = startingScenarioIndex;328            int classIndex = 0;329            for (ClassResult classResult : classResults) {330                String cssClass = cssClassPrefix + ((classIndex % 2) == 0 ? "even" : "odd");331                buffer.setLength(0);332                int scenariosPerClass = 0;333                int methodIndex = 0;334                for (MethodResult methodResult : classResult.getMethodResults()) {335                    List<ITestResult> results = methodResult.getResults();336                    int resultsCount = results.size();337                    assert resultsCount > 0;338                    ITestResult aResult = results.iterator().next();339                    String methodName = Utils.escapeHtml(aResult.getMethod().getMethodName());340                    long start = aResult.getStartMillis();341                    long duration = aResult.getEndMillis() - start;342                    // The first method per class shares a row with the class343                    // header344                    if (methodIndex > 0) {345                        buffer.append("<tr class=\"").append(cssClass)346                                .append("\">");347                    }348                    // Write the timing information with the first scenario per method349                    buffer.append("<td><a href=\"#m").append(scenarioIndex)350                            .append("\">").append(methodName + "</a></td>")351                            .append("<td rowspan=\"1\">" + aResult.getName() + "</td>")352                            .append("<td rowspan=\"")353                            .append(resultsCount).append("\">").append(parseUnixTimeToTimeOfDay(start))354                            .append("</td>").append("<td rowspan=\"")355                            .append(resultsCount).append("\">")356                            .append(decimalFormat.format(millisecondsToSeconds(duration))).append("</td></tr>");357                    scenarioIndex++;358                    // Write the remaining scenarios for the method359                    for (int i = 1; i < resultsCount; i++) {360                        buffer.append("<tr class=\"").append(cssClass)361                                .append("\">").append("<td><a href=\"#m")362                                .append(scenarioIndex).append("\">")363                                .append(methodName + "</a></td>")364                                .append("<td rowspan=\"1\">" + aResult.getName() + "</td></tr>");365                        scenarioIndex++;366                    }367                    scenariosPerClass += resultsCount;368                    methodIndex++;369                }370                // Write the test results for the class371                writer.print("<tr class=\"");372                writer.print(cssClass);373                writer.print("\">");374                writer.print("<td rowspan=\"");375                writer.print(scenariosPerClass);376                writer.print("\">");377                writer.print(Utils.escapeHtml(classResult.getClassName()));378                writer.print("</td>");379                writer.print(buffer);380                classIndex++;381            }382            scenarioCount = scenarioIndex - startingScenarioIndex;383        }384        return scenarioCount;385    }386    /**387     * Writes the details for all test scenarios.388     */389    protected void writeScenarioDetails() {390        int scenarioIndex = 0;391        for (SuiteResult suiteResult : suiteResults) {392            for (TestResult testResult : suiteResult.getTestResults()) {393                writer.print("<h2>");394                writer.print(Utils.escapeHtml(testResult.getTestName()));395                writer.print("</h2>");396                scenarioIndex += writeScenarioDetails(397                        testResult.getFailedConfigurationResults(), scenarioIndex);398                scenarioIndex += writeScenarioDetails(399                        testResult.getFailedTestResults(), scenarioIndex);400                scenarioIndex += writeScenarioDetails(401                        testResult.getSkippedConfigurationResults(), scenarioIndex);402                scenarioIndex += writeScenarioDetails(403                        testResult.getSkippedTestResults(), scenarioIndex);404                scenarioIndex += writeScenarioDetails(405                        testResult.getPassedTestResults(), scenarioIndex);406            }407        }408    }409    /**410     * Writes the scenario details for the results of a given state for a single411     * test.412     */413    private int writeScenarioDetails(List<ClassResult> classResults, int startingScenarioIndex) {414        int scenarioIndex = startingScenarioIndex;415        for (ClassResult classResult : classResults) {416            String className = classResult.getClassName();417            418            List<MethodResult> methods = classResult.getMethodResults();419            methods=removeFailedTest(methods);420            for (MethodResult methodResult : methods) {421                List<ITestResult> results1 = methodResult.getResults();422                Set<ITestResult> results=new HashSet<ITestResult>(results1);423                assert !results.isEmpty();424                ITestResult mResult = results.iterator().next();425                String label = Utils.escapeHtml(className + "#"426                        + mResult.getMethod().getMethodName() + " ( " + mResult.getName() + " )");427                for (ITestResult result : results) {428                    writeScenario(scenarioIndex, label, result);429                    scenarioIndex++;430                }431            }432        }433        return scenarioIndex - startingScenarioIndex;434    }435    436    public List<MethodResult> removeFailedTest(List<MethodResult> methods){437    	438    	List<MethodResult> newMethods = new ArrayList<SpireEmailReportV2.MethodResult>();439    	int i=0;440    	441    	for (MethodResult methodResult : methods) {442    		443    		List<ITestResult> newList = new ArrayList<ITestResult>();444    		445    		List<ITestResult> results=methodResult.getResults();446    		447    		MethodResult newMethod = new MethodResult(newList);448    		449    		for (ITestResult iTestResult : results) {450    			451    			boolean isDuplicate=false;452    			453    			System.out.println(iTestResult.getParameters()[0]);454    			455    			if (newList.size()==0) {456    				newList.add(iTestResult);457    			}458        		459    			for (ITestResult list : newList) {460    				461    				if (list!=null && list.getParameters()!=null && list.getParameters().length>0) {462    					463    					if ((list.getParameters()[0].toString()).equalsIgnoreCase(iTestResult.getParameters()[0].toString())) {464        					isDuplicate = true;465    					}466    					467    				}468    				469    				470    			}471    			472        		if (!isDuplicate){473        			newList.add(iTestResult);474        		}475				476			}477    		478    		System.out.println(results.size());479    		System.out.println(newList.size());480    		481    		newMethods.add(newMethod);482		}483    	484    	return newMethods;485    	486    }487    /**488     * Writes the details for an individual test scenario.489     */490    private void writeScenario(int scenarioIndex, String label,491                               ITestResult result) {492        writer.print("<h3 id=\"m");493        writer.print(scenarioIndex);494        writer.print("\">");495        writer.print(label);496        writer.print("</h3>");497        writer.print("<table class=\"result\">");498        // Write test parameters (if any)499        Object[] parameters = result.getParameters();500        int parameterCount = (parameters == null ? 0 : parameters.length);501        if (parameterCount > 0) {502            writer.print("<tr class=\"param\">");503            for (int i = 1; i <= parameterCount; i++) {504                writer.print("<th>Parameter #");505                writer.print(i);506                writer.print("</th>");507            }508            writer.print("</tr><tr class=\"param stripe\">");509            for (Object parameter : parameters) {510                writer.print("<td>");511                writer.print(Utils.escapeHtml(Utils.toString(parameter, Object.class)));512                writer.print("</td>");513            }514            writer.print("</tr>");515        }516        // Write reporter messages (if any)517        List<String> reporterMessages = Reporter.getOutput(result);518        if (!reporterMessages.isEmpty()) {519            writer.print("<tr><th");520            if (parameterCount > 1) {521                writer.print(" colspan=\"");522                writer.print(parameterCount);523                writer.print("\"");524            }525            writer.print(">Messages</th></tr>");526            writer.print("<tr><td");527            if (parameterCount > 1) {528                writer.print(" colspan=\"");529                writer.print(parameterCount);530                writer.print("\"");531            }532            writer.print(">");533            writeReporterMessages(reporterMessages);534            writer.print("</td></tr>");535        }536        // Write exception (if any)537        Throwable throwable = result.getThrowable();538        if (throwable != null) {539            writer.print("<tr><th");540            if (parameterCount > 1) {541                writer.print(" colspan=\"");542                writer.print(parameterCount);543                writer.print("\"");544            }545            writer.print(">");546            writer.print((result.getStatus() == ITestResult.SUCCESS ? "Expected Exception"547                    : "Exception"));548            writer.print("</th></tr>");549            writer.print("<tr><td");550            if (parameterCount > 1) {551                writer.print(" colspan=\"");552                writer.print(parameterCount);553                writer.print("\"");554            }555            writer.print(">");556            writeStackTrace(throwable);557            writer.print("</td></tr>");558        }559        writer.print("</table>");560        writer.print("<p class=\"totop\"><a href=\"#summary\">back to summary</a></p>");561    }562    protected void writeReporterMessages(List<String> reporterMessages) {563        writer.print("<div class=\"messages\">");564        Iterator<String> iterator = reporterMessages.iterator();565        assert iterator.hasNext();566        writer.print(Utils.escapeHtml(iterator.next()));567        while (iterator.hasNext()) {568            writer.print("<br/>");569            writer.print(Utils.escapeHtml(iterator.next()));570        }571        writer.print("</div>");572    }573    protected void writeStackTrace(Throwable throwable) {574        writer.print("<div class=\"stacktrace\">");575        writer.print(Utils.stackTrace(throwable, true)[0]);576        writer.print("</div>");577    }578    /**579     * Writes a TH element with the specified contents and CSS class names.580     *581     * @param html       the HTML contents582     * @param cssClasses the space-delimited CSS classes or null if there are no583     *                   classes to apply584     */585    protected void writeTableHeader(String html, String cssClasses) {586        writeTag("th", html, cssClasses);587    }588    /**589     * Writes a TD element with the specified contents.590     *591     * @param html the HTML contents592     */593    protected void writeTableData(String html) {594        writeTableData(html, null);595    }596    /**597     * Writes a TD element with the specified contents and CSS class names.598     *599     * @param html       the HTML contents...Source:CustomEmailableReporter.java  
...173        // Print totals if there was more than one test174        if (testIndex > 1) {175            writer.print("<tr>");176            writer.print("<th>Total</th>");177            writeTableHeader(integerFormat.format(totalPassedTests), "num");178            writeTableHeader(integerFormat.format(totalSkippedTests),179                    (totalSkippedTests > 0 ? "num attn" : "num"));180            writeTableHeader(integerFormat.format(totalFailedTests),181                    (totalFailedTests > 0 ? "num attn" : "num"));182            writeTableHeader(decimalFormat.format(totalDuration), "num");183            writer.print("<th colspan=\"2\"></th>");184            writer.print("</tr>");185        }186        writer.print("</table>");187    }188    /**189     * Writes a summary of all the test scenarios.190     */191    @Override192	protected void writeScenarioSummary() {193    	writer.print("</br>");194    	writer.print("<h1>Detailed Test Report</h1>");195        writer.print("<table>");196        writer.print("<thead>");197        writer.print("<tr>");198       /* writer.print("<th>Class</th>");*/199        writer.print("<th>Method</th>");200        writer.print("<th>Description</th>");201        writer.print("<th>Start</th>");202        writer.print("<th>Time (ms)</th>");203        writer.print("</tr>");204        writer.print("</thead>");205        int testIndex = 0;206        int scenarioIndex = 0;207        for (SuiteResult suiteResult : suiteResults) {208            writer.print("<tbody><tr><th colspan=\"4\">");209            writer.print(Utils.escapeHtml(suiteResult.getSuiteName()));210            writer.print("</th></tr></tbody>");211            for (TestResult testResult : suiteResult.getTestResults()) {212                writer.print("<tbody id=\"t");213                writer.print(testIndex);214                writer.print("\">");215                String testName = Utils.escapeHtml(testResult.getTestName());216                scenarioIndex += writeScenarioSummary(testName217                        + " — failed (configuration methods)",218                        testResult.getFailedConfigurationResults(), "failed",219                        scenarioIndex);220                scenarioIndex += writeScenarioSummary(testName221                        + " — failed", testResult.getFailedTestResults(),222                        "failed", scenarioIndex);223                scenarioIndex += writeScenarioSummary(testName224                        + " — skipped (configuration methods)",225                        testResult.getSkippedConfigurationResults(), "skipped",226                        scenarioIndex);227                scenarioIndex += writeScenarioSummary(testName228                        + " — skipped",229                        testResult.getSkippedTestResults(), "skipped",230                        scenarioIndex);231                scenarioIndex += writeScenarioSummary(testName232                        + " — passed", testResult.getPassedTestResults(),233                        "passed", scenarioIndex);234                writer.print("</tbody>");235                testIndex++;236            }237        }238        writer.print("</table>");239    }240    /**241     * Writes the scenario summary for the results of a given state for a single242     * test.243     */244    private int writeScenarioSummary(String description,245            List<ClassResult> classResults, String cssClassPrefix,246            int startingScenarioIndex) {247        int scenarioCount = 0;248        if (!classResults.isEmpty()) {249            writer.print("<tr><th colspan=\"4\">");250            writer.print(description);251            writer.print("</th></tr>");252            int scenarioIndex = startingScenarioIndex;253            int classIndex = 0;254            for (ClassResult classResult : classResults) {255                String cssClass = cssClassPrefix256                        + ((classIndex % 2) == 0 ? "even" : "odd");257                buffer.setLength(0);258                int scenariosPerClass = 0;259                int methodIndex = 0;260                for (MethodResult methodResult : classResult.getMethodResults()) {261                    List<ITestResult> results = methodResult.getResults();262                    int resultsCount = results.size();263                    assert resultsCount > 0;264                    ITestResult firstResult = results.iterator().next();265                    String methodName = Utils.escapeHtml(firstResult266                            .getMethod().getMethodName());267                    String descMethod = " ";268                    if(firstResult.getMethod().getDescription()!=null)269                    	descMethod = Utils.escapeHtml(firstResult270                            .getMethod().getDescription());271                    long start = firstResult.getStartMillis();272                    long duration = firstResult.getEndMillis() - start;273                    // The first method per class shares a row with the class274                    // header275                    if (methodIndex > 0) {276                        buffer.append("<tr class=\"").append(cssClass)277                                .append("\">");278                    }279                    // Write the timing information with the first scenario per280                    // method281                    buffer.append("<td><a href=\"#m").append(scenarioIndex)282                            .append("\">").append(methodName)283                            .append("</a></td>").append("<td rowspan=\"")284                            .append(resultsCount).append("\">").append(descMethod)285                            .append("</td>").append("<td rowspan=\"")286                            .append(resultsCount).append("\">").append(start)287                            .append("</td>").append("<td rowspan=\"")288                            .append(resultsCount).append("\">")289                            .append(duration).append("</td></tr>");290                    scenarioIndex++;291                    // Write the remaining scenarios for the method292                    for (int i = 1; i < resultsCount; i++) {293                        buffer.append("<tr class=\"").append(cssClass)294                                .append("\">").append("<td><a href=\"#m")295                                .append(scenarioIndex).append("\">")296                                .append(methodName).append("</a></td></tr>");297                        scenarioIndex++;298                    }299                    scenariosPerClass += resultsCount;300                    methodIndex++;301                }302                // Write the test results for the class303                writer.print("<tr class=\"");304                writer.print(cssClass);305                writer.print("\">");306/*                writer.print("<td rowspan=\"");307                writer.print(scenariosPerClass);308                writer.print("\">");309                writer.print(Utils.escapeHtml(classResult.getClassName()));310                writer.print("</td>");*/311                writer.print(buffer);312                classIndex++;313            }314            scenarioCount = scenarioIndex - startingScenarioIndex;315        }316        return scenarioCount;317    }318    /**319     * Writes the details for all test scenarios.320     */321    @Override322	protected void writeScenarioDetails() {323        int scenarioIndex = 0;324        for (SuiteResult suiteResult : suiteResults) {325            for (TestResult testResult : suiteResult.getTestResults()) {326                writer.print("<h2>");327                writer.print(Utils.escapeHtml(testResult.getTestName()));328                writer.print("</h2>");329                scenarioIndex += writeScenarioDetails(330                        testResult.getFailedConfigurationResults(),331                        scenarioIndex);332                scenarioIndex += writeScenarioDetails(333                        testResult.getFailedTestResults(), scenarioIndex);334                scenarioIndex += writeScenarioDetails(335                        testResult.getSkippedConfigurationResults(),336                        scenarioIndex);337                scenarioIndex += writeScenarioDetails(338                        testResult.getSkippedTestResults(), scenarioIndex);339                scenarioIndex += writeScenarioDetails(340                        testResult.getPassedTestResults(), scenarioIndex);341            }342        }343    }344    /**345     * Writes the scenario details for the results of a given state for a single346     * test.347     */348    private int writeScenarioDetails(List<ClassResult> classResults,349            int startingScenarioIndex) {350        int scenarioIndex = startingScenarioIndex;351        for (ClassResult classResult : classResults) {352            String className = classResult.getClassName();353            for (MethodResult methodResult : classResult.getMethodResults()) {354                List<ITestResult> results = methodResult.getResults();355                assert !results.isEmpty();356                String label = Utils357                        .escapeHtml(className358                                + "#"359                                + results.iterator().next().getMethod()360                                        .getMethodName());361                for (ITestResult result : results) {362                	if(!result.isSuccess())363                    {364                		writeScenario(scenarioIndex, label, result);365                		scenarioIndex++;366                    }367                }368            }369        }370        return scenarioIndex - startingScenarioIndex;371    }372    /**373     * Writes the details for an individual test scenario.374     */375    private void writeScenario(int scenarioIndex, String label,376            ITestResult result) {377        writer.print("<h3 id=\"m");378        writer.print(scenarioIndex);379        writer.print("\">");380        writer.print(label);381        writer.print("</h3>");382        writer.print("<table class=\"result\">");383        // Write test parameters (if any)384        Object[] parameters = result.getParameters();385        int parameterCount = (parameters == null ? 0 : parameters.length);386        if (parameterCount > 0) {387            writer.print("<tr class=\"param\">");388            for (int i = 1; i <= parameterCount; i++) {389                writer.print("<th>Parameter #");390                writer.print(i);391                writer.print("</th>");392            }393            writer.print("</tr><tr class=\"param stripe\">");394            for (Object parameter : parameters) {395                writer.print("<td>");396                writer.print(Utils.escapeHtml(Utils.toString(parameter)));397                writer.print("</td>");398            }399            writer.print("</tr>");400        }401        // Write reporter messages (if any)402        List<String> reporterMessages = Reporter.getOutput(result);403        if (!reporterMessages.isEmpty()) {404            writer.print("<tr><th");405            if (parameterCount > 1) {406                writer.print(" colspan=\"");407                writer.print(parameterCount);408                writer.print("\"");409            }410            writer.print(">Messages</th></tr>");411            writer.print("<tr><td");412            if (parameterCount > 1) {413                writer.print(" colspan=\"");414                writer.print(parameterCount);415                writer.print("\"");416            }417            writer.print(">");418            writeReporterMessages(reporterMessages);419            writer.print("</td></tr>");420        }421        // Write exception (if any)422        Throwable throwable = result.getThrowable();423        if (throwable != null) {424            writer.print("<tr><th");425            if (parameterCount > 1) {426                writer.print(" colspan=\"");427                writer.print(parameterCount);428                writer.print("\"");429            }430            writer.print(">");431            writer.print((result.getStatus() == ITestResult.SUCCESS ? "Expected Exception"432                    : "Exception"));433            writer.print("</th></tr>");434            writer.print("<tr><td");435            if (parameterCount > 1) {436                writer.print(" colspan=\"");437                writer.print(parameterCount);438                writer.print("\"");439            }440            writer.print(">");441            writeStackTrace(throwable);442            writer.print("</td></tr>");443        }444        writer.print("</table>");445        writer.print("<p class=\"totop\"><a href=\"#summary\">back to summary</a></p>");446    }447    @Override448	protected void writeReporterMessages(List<String> reporterMessages) {449        writer.print("<div class=\"messages\">");450        Iterator<String> iterator = reporterMessages.iterator();451        assert iterator.hasNext();452        writer.print(Utils.escapeHtml(iterator.next()));453        while (iterator.hasNext()) {454            writer.print("<br/>");455            writer.print(Utils.escapeHtml(iterator.next()));456        }457        writer.print("</div>");458    }459    @Override460	protected void writeStackTrace(Throwable throwable) {461        writer.print("<div class=\"stacktrace\">");462        writer.print(Utils.stackTrace(throwable, true)[0]);463        writer.print("</div>");464    }465    /**466     * Writes a TH element with the specified contents and CSS class names.467     * 468     * @param html469     *            the HTML contents470     * @param cssClasses471     *            the space-delimited CSS classes or null if there are no472     *            classes to apply473     */474    @Override475	protected void writeTableHeader(String html, String cssClasses) {476        writeTag("th", html, cssClasses);477    }478    /**479     * Writes a TD element with the specified contents.480     * 481     * @param html482     *            the HTML contents483     */484    @Override485	protected void writeTableData(String html) {486        writeTableData(html, null);487    }488    /**489     * Writes a TD element with the specified contents and CSS class names....Source:CustomReporter.java  
...151        // Print totals if there was more than one test152        if ( testIndex >= 1 ) {153            writer.print("<tr>");154            writer.print("<th>Total</th>");155            writeTableHeader( integerFormat.format(totalPassedTests), "num");156            writeTableHeader( integerFormat.format(totalSkippedTests), (totalSkippedTests > 0 ? "num attn" : "num"));157            writeTableHeader( integerFormat.format(totalFailedTests), (totalFailedTests > 0 ? "num attn" : "num"));158            writeTableHeader( decimalFormat.format(millisecondsToSeconds(totalDuration)), "num");159            writer.print("<th colspan=\"2\"></th>");160            writer.print("</tr>");161        }162        writer.print("</table>");163    }164    /**165     * Writes a summary of all the test scenarios.166     */167    protected void writeScenarioSummary() {168        writer.print("<table>");169        writer.print("<thead>");170        writer.print("<tr>");171        writer.print("<th>Class</th>");172        writer.print("<th>Method</th>");173        writer.print("<th>Name</th>");174        writer.print("<th>Start</th>");175        writer.print("<th>Seconds</th>");176        writer.print("</tr>");177        writer.print("</thead>");178        int testIndex = 0;179        int scenarioIndex = 0;180        for ( SuiteResult suiteResult : suiteResults ) {181            writer.print("<tbody><tr><th colspan=\"5\">");182            writer.print( Utils.escapeHtml( suiteResult.getSuiteName() ) );183            writer.print("</th></tr></tbody>");184            for ( TestResult testResult : suiteResult.getTestResults() ) {185                writer.print("<tbody id=\"t");186                writer.print(testIndex);187                writer.print("\">");188                String testName = Utils.escapeHtml( testResult.getTestName() );189                scenarioIndex += writeScenarioSummary(testName190                        + " — failed (configuration methods)",191                        testResult.getFailedConfigurationResults(), "failed",192                        scenarioIndex193                );194                scenarioIndex += writeScenarioSummary(testName195                        + " — failed", testResult.getFailedTestResults(),196                        "failed", scenarioIndex197                );198                scenarioIndex += writeScenarioSummary(testName199                        + " — skipped (configuration methods)",200                        testResult.getSkippedConfigurationResults(), "skipped",201                        scenarioIndex202                );203                scenarioIndex += writeScenarioSummary(testName204                        + " — skipped",205                        testResult.getSkippedTestResults(), "skipped",206                        scenarioIndex207                );208                scenarioIndex += writeScenarioSummary(testName209                        + " — passed", testResult.getPassedTestResults(),210                        "passed", scenarioIndex211                );212                writer.print("</tbody>");213                testIndex++;214            }215        }216        writer.print("</table>");217    }218    /**219     * Writes the scenario summary for the results of a given state for a single220     * test.221     */222    private int writeScenarioSummary( String description, List<ClassResult> classResults,223                                     String cssClassPrefix, int startingScenarioIndex ) {224        int scenarioCount = 0;225        if (!classResults.isEmpty()) {226            writer.print("<tr><th colspan=\"5\">");227            writer.print(description);228            writer.print("</th></tr>");229            int scenarioIndex = startingScenarioIndex;230            int classIndex = 0;231            for ( ClassResult classResult : classResults ) {232                String cssClass = cssClassPrefix + ((classIndex % 2) == 0 ? "even" : "odd");233                buffer.setLength(0);234                int scenariosPerClass = 0;235                int methodIndex = 0;236                for ( MethodResult methodResult : classResult.getMethodResults() ) {237                    List<ITestResult> results = methodResult.getResults();238                    int resultsCount = results.size();239                    assert resultsCount > 0;240                    ITestResult aResult = results.iterator().next();241                    String methodName = Utils.escapeHtml(aResult.getMethod().getMethodName());242                    long start = aResult.getStartMillis();243                    long duration = aResult.getEndMillis() - start;244                    // The first method per class shares a row with the class245                    // header246                    if (methodIndex > 0) {247                        buffer.append("<tr class=\"").append(cssClass)248                                .append("\">");249                    }250                    // Write the timing information with the first scenario per method251                    buffer.append("<td><a href=\"#m").append(scenarioIndex)252                            .append("\">").append( methodName + "</a></td>" )253                            .append( "<td rowspan=\"1\">" + aResult.getName() + "</td>" )254                            .append( "<td rowspan=\"")255                            .append(resultsCount).append("\">").append( parseUnixTimeToTimeOfDay(start) )256                            .append( "</td>").append("<td rowspan=\"" )257                            .append(resultsCount).append("\">")258                            .append( decimalFormat.format( millisecondsToSeconds( duration ) ) ).append("</td></tr>");259                    scenarioIndex++;260                    // Write the remaining scenarios for the method261                    for ( int i = 1; i < resultsCount; i++ ) {262                        buffer.append("<tr class=\"").append(cssClass)263                                .append("\">").append("<td><a href=\"#m")264                                .append(scenarioIndex).append("\">")265                                .append( methodName + "</a></td>" )266                                .append("<td rowspan=\"1\">" + aResult.getName() + "</td></tr>" );267                        scenarioIndex++;268                    }269                    scenariosPerClass += resultsCount;270                    methodIndex++;271                }272                // Write the test results for the class273                writer.print("<tr class=\"");274                writer.print(cssClass);275                writer.print("\">");276                writer.print("<td rowspan=\"");277                writer.print(scenariosPerClass);278                writer.print("\">");279                writer.print(Utils.escapeHtml(classResult.getClassName()));280                writer.print("</td>");281                writer.print(buffer);282                classIndex++;283            }284            scenarioCount = scenarioIndex - startingScenarioIndex;285        }286        return scenarioCount;287    }288    /**289     * Writes the details for all test scenarios.290     */291    protected void writeScenarioDetails() {292        int scenarioIndex = 0;293        for ( SuiteResult suiteResult : suiteResults ) {294            for ( TestResult testResult : suiteResult.getTestResults() ) {295                writer.print("<h2>");296                writer.print( Utils.escapeHtml( testResult.getTestName() ) );297                writer.print("</h2>");298                scenarioIndex += writeScenarioDetails(299                        testResult.getFailedConfigurationResults(), scenarioIndex);300                scenarioIndex += writeScenarioDetails(301                        testResult.getFailedTestResults(), scenarioIndex);302                scenarioIndex += writeScenarioDetails(303                        testResult.getSkippedConfigurationResults(), scenarioIndex);304                scenarioIndex += writeScenarioDetails(305                        testResult.getSkippedTestResults(), scenarioIndex);306                scenarioIndex += writeScenarioDetails(307                        testResult.getPassedTestResults(), scenarioIndex);308            }309        }310    }311    /**312     * Writes the scenario details for the results of a given state for a single313     * test.314     */315    private int writeScenarioDetails( List<ClassResult> classResults, int startingScenarioIndex ) {316        int scenarioIndex = startingScenarioIndex;317        for ( ClassResult classResult : classResults ) {318            String className = classResult.getClassName();319            for ( MethodResult methodResult : classResult.getMethodResults() ) {320                List<ITestResult> results = methodResult.getResults();321                assert !results.isEmpty();322                ITestResult mResult = results.iterator().next();323                String label = Utils.escapeHtml( className + "#"324                     + mResult.getMethod().getMethodName() + " ( " + mResult.getName() +" )" );325                for ( ITestResult result : results ) {326                    writeScenario( scenarioIndex, label, result );327                    scenarioIndex++;328                }329            }330        }331        return scenarioIndex - startingScenarioIndex;332    }333    /**334     * Writes the details for an individual test scenario.335     */336    private void writeScenario(int scenarioIndex, String label,337                               ITestResult result) {338        writer.print("<h3 id=\"m");339        writer.print(scenarioIndex);340        writer.print("\">");341        writer.print(label);342        writer.print("</h3>");343        writer.print("<table class=\"result\">");344        // Write test parameters (if any)345        Object[] parameters = result.getParameters();346        int parameterCount = (parameters == null ? 0 : parameters.length);347        if (parameterCount > 0) {348            writer.print("<tr class=\"param\">");349            for (int i = 1; i <= parameterCount; i++) {350                writer.print("<th>Parameter #");351                writer.print(i);352                writer.print("</th>");353            }354            writer.print("</tr><tr class=\"param stripe\">");355            for (Object parameter : parameters) {356                writer.print("<td>");357                writer.print( Utils.escapeHtml( Utils.toString( parameter, Object.class ) ) );358                writer.print("</td>");359            }360            writer.print("</tr>");361        }362        // Write reporter messages (if any)363        List<String> reporterMessages = Reporter.getOutput(result);364        if (!reporterMessages.isEmpty()) {365            writer.print("<tr><th");366            if (parameterCount > 1) {367                writer.print(" colspan=\"");368                writer.print(parameterCount);369                writer.print("\"");370            }371            writer.print(">Messages</th></tr>");372            writer.print("<tr><td");373            if (parameterCount > 1) {374                writer.print(" colspan=\"");375                writer.print(parameterCount);376                writer.print("\"");377            }378            writer.print(">");379            writeReporterMessages(reporterMessages);380            writer.print("</td></tr>");381        }382        // Write exception (if any)383        Throwable throwable = result.getThrowable();384        if (throwable != null) {385            writer.print("<tr><th");386            if (parameterCount > 1) {387                writer.print(" colspan=\"");388                writer.print(parameterCount);389                writer.print("\"");390            }391            writer.print(">");392            writer.print((result.getStatus() == ITestResult.SUCCESS ? "Expected Exception"393                    : "Exception"));394            writer.print("</th></tr>");395            writer.print("<tr><td");396            if (parameterCount > 1) {397                writer.print(" colspan=\"");398                writer.print(parameterCount);399                writer.print("\"");400            }401            writer.print(">");402            writeStackTrace(throwable);403            writer.print("</td></tr>");404        }405        writer.print("</table>");406        writer.print("<p class=\"totop\"><a href=\"#summary\">back to summary</a></p>");407    }408    protected void writeReporterMessages(List<String> reporterMessages) {409        writer.print("<div class=\"messages\">");410        Iterator<String> iterator = reporterMessages.iterator();411        assert iterator.hasNext();412        writer.print(Utils.escapeHtml(iterator.next()));413        while (iterator.hasNext()) {414            writer.print("<br/>");415            writer.print(Utils.escapeHtml(iterator.next()));416        }417        writer.print("</div>");418    }419    protected void writeStackTrace(Throwable throwable) {420        writer.print("<div class=\"stacktrace\">");421        writer.print(Utils.stackTrace(throwable, true)[0]);422        writer.print("</div>");423    }424    /**425     * Writes a TH element with the specified contents and CSS class names.426     *427     * @param html       the HTML contents428     * @param cssClasses the space-delimited CSS classes or null if there are no429     *                   classes to apply430     */431    protected void writeTableHeader(String html, String cssClasses) {432        writeTag("th", html, cssClasses);433    }434    /**435     * Writes a TD element with the specified contents.436     *437     * @param html the HTML contents438     */439    protected void writeTableData(String html) {440        writeTableData(html, null);441    }442    /**443     * Writes a TD element with the specified contents and CSS class names.444     *445     * @param html       the HTML contents...Source:EmailableReporter2.java  
...161        // Print totals if there was more than one test162        if (testIndex > 1) {163            writer.print("<tr>");164            writer.print("<th>Total</th>");165            writeTableHeader(integerFormat.format(totalPassedTests), "num");166            writeTableHeader(integerFormat.format(totalSkippedTests),167                    (totalSkippedTests > 0 ? "num attn" : "num"));168            writeTableHeader(integerFormat.format(totalFailedTests),169                    (totalFailedTests > 0 ? "num attn" : "num"));170            writeTableHeader(decimalFormat.format(totalDuration), "num");171            writer.print("<th colspan=\"2\"></th>");172            writer.println("</tr>");173        }174        writer.println("</table>");175    }176    /**177     * Writes a summary of all the test scenarios.178     */179    protected void writeScenarioSummary() {180        writer.print("<table id='summary'>");181        writer.print("<thead>");182        writer.print("<tr>");183        writer.print("<th>Class</th>");184        writer.print("<th>Method</th>");185        writer.print("<th>Start</th>");186        writer.print("<th>Time (ms)</th>");187        writer.print("</tr>");188        writer.print("</thead>");189        int testIndex = 0;190        int scenarioIndex = 0;191        for (SuiteResult suiteResult : suiteResults) {192            writer.print("<tbody><tr><th colspan=\"4\">");193            writer.print(Utils.escapeHtml(suiteResult.getSuiteName()));194            writer.print("</th></tr></tbody>");195            for (TestResult testResult : suiteResult.getTestResults()) {196                writer.printf("<tbody id=\"t%d\">", testIndex);197                String testName = Utils.escapeHtml(testResult.getTestName());198                int startIndex = scenarioIndex;199                scenarioIndex += writeScenarioSummary(testName200                        + " — failed (configuration methods)",201                        testResult.getFailedConfigurationResults(), "failed",202                        scenarioIndex);203                scenarioIndex += writeScenarioSummary(testName204                        + " — failed", testResult.getFailedTestResults(),205                        "failed", scenarioIndex);206                scenarioIndex += writeScenarioSummary(testName207                        + " — skipped (configuration methods)",208                        testResult.getSkippedConfigurationResults(), "skipped",209                        scenarioIndex);210                scenarioIndex += writeScenarioSummary(testName211                        + " — skipped",212                        testResult.getSkippedTestResults(), "skipped",213                        scenarioIndex);214                scenarioIndex += writeScenarioSummary(testName215                        + " — passed", testResult.getPassedTestResults(),216                        "passed", scenarioIndex);217                if (scenarioIndex == startIndex) {218                    writer.print("<tr><th colspan=\"4\" class=\"invisible\"/></tr>");219                }220                writer.println("</tbody>");221                testIndex++;222            }223        }224        writer.println("</table>");225    }226    /**227     * Writes the scenario summary for the results of a given state for a single228     * test.229     */230    private int writeScenarioSummary(String description,231            List<ClassResult> classResults, String cssClassPrefix,232            int startingScenarioIndex) {233        int scenarioCount = 0;234        if (!classResults.isEmpty()) {235            writer.print("<tr><th colspan=\"4\">");236            writer.print(description);237            writer.print("</th></tr>");238            int scenarioIndex = startingScenarioIndex;239            int classIndex = 0;240            for (ClassResult classResult : classResults) {241                String cssClass = cssClassPrefix242                        + ((classIndex % 2) == 0 ? "even" : "odd");243                buffer.setLength(0);244                int scenariosPerClass = 0;245                int methodIndex = 0;246                for (MethodResult methodResult : classResult.getMethodResults()) {247                    List<ITestResult> results = methodResult.getResults();248                    int resultsCount = results.size();249                    assert resultsCount > 0;250                    ITestResult firstResult = results.iterator().next();251                    String methodName = Utils.escapeHtml(firstResult252                            .getMethod().getMethodName());253                    long start = firstResult.getStartMillis();254                    long duration = firstResult.getEndMillis() - start;255                    // The first method per class shares a row with the class256                    // header257                    if (methodIndex > 0) {258                        buffer.append("<tr class=\"").append(cssClass)259                                .append("\">");260                    }261                    // Write the timing information with the first scenario per262                    // method263                    buffer.append("<td><a href=\"#m").append(scenarioIndex)264                            .append("\">").append(methodName)265                            .append("</a></td>").append("<td rowspan=\"")266                            .append(resultsCount).append("\">").append(start)267                            .append("</td>").append("<td rowspan=\"")268                            .append(resultsCount).append("\">")269                            .append(duration).append("</td></tr>");270                    scenarioIndex++;271                    // Write the remaining scenarios for the method272                    for (int i = 1; i < resultsCount; i++) {273                        buffer.append("<tr class=\"").append(cssClass)274                                .append("\">").append("<td><a href=\"#m")275                                .append(scenarioIndex).append("\">")276                                .append(methodName).append("</a></td></tr>");277                        scenarioIndex++;278                    }279                    scenariosPerClass += resultsCount;280                    methodIndex++;281                }282                // Write the test results for the class283                writer.print("<tr class=\"");284                writer.print(cssClass);285                writer.print("\">");286                writer.print("<td rowspan=\"");287                writer.print(scenariosPerClass);288                writer.print("\">");289                writer.print(Utils.escapeHtml(classResult.getClassName()));290                writer.print("</td>");291                writer.print(buffer);292                classIndex++;293            }294            scenarioCount = scenarioIndex - startingScenarioIndex;295        }296        return scenarioCount;297    }298    /**299     * Writes the details for all test scenarios.300     */301    protected void writeScenarioDetails() {302        int scenarioIndex = 0;303        for (SuiteResult suiteResult : suiteResults) {304            for (TestResult testResult : suiteResult.getTestResults()) {305                writer.print("<h2>");306                writer.print(Utils.escapeHtml(testResult.getTestName()));307                writer.print("</h2>");308                scenarioIndex += writeScenarioDetails(309                        testResult.getFailedConfigurationResults(),310                        scenarioIndex);311                scenarioIndex += writeScenarioDetails(312                        testResult.getFailedTestResults(), scenarioIndex);313                scenarioIndex += writeScenarioDetails(314                        testResult.getSkippedConfigurationResults(),315                        scenarioIndex);316                scenarioIndex += writeScenarioDetails(317                        testResult.getSkippedTestResults(), scenarioIndex);318                scenarioIndex += writeScenarioDetails(319                        testResult.getPassedTestResults(), scenarioIndex);320            }321        }322    }323    /**324     * Writes the scenario details for the results of a given state for a single325     * test.326     */327    private int writeScenarioDetails(List<ClassResult> classResults,328            int startingScenarioIndex) {329        int scenarioIndex = startingScenarioIndex;330        for (ClassResult classResult : classResults) {331            String className = classResult.getClassName();332            for (MethodResult methodResult : classResult.getMethodResults()) {333                List<ITestResult> results = methodResult.getResults();334                assert !results.isEmpty();335                String label = Utils336                        .escapeHtml(className337                                + "#"338                                + results.iterator().next().getMethod()339                                        .getMethodName());340                for (ITestResult result : results) {341                    writeScenario(scenarioIndex, label, result);342                    scenarioIndex++;343                }344            }345        }346        return scenarioIndex - startingScenarioIndex;347    }348    /**349     * Writes the details for an individual test scenario.350     */351    private void writeScenario(int scenarioIndex, String label,352            ITestResult result) {353        writer.print("<h3 id=\"m");354        writer.print(scenarioIndex);355        writer.print("\">");356        writer.print(label);357        writer.print("</h3>");358        writer.print("<table class=\"result\">");359        boolean hasRows = false;360        // Write test parameters (if any)361        Object[] parameters = result.getParameters();362        int parameterCount = (parameters == null ? 0 : parameters.length);363        if (parameterCount > 0) {364            writer.print("<tr class=\"param\">");365            for (int i = 1; i <= parameterCount; i++) {366                writer.print("<th>Parameter #");367                writer.print(i);368                writer.print("</th>");369            }370            writer.print("</tr><tr class=\"param stripe\">");371            for (Object parameter : parameters) {372                writer.print("<td>");373                writer.print(Utils.escapeHtml(Utils.toString(parameter)));374                writer.print("</td>");375            }376            writer.print("</tr>");377            hasRows = true;378        }379        // Write reporter messages (if any)380        List<String> reporterMessages = Reporter.getOutput(result);381        if (!reporterMessages.isEmpty()) {382            writer.print("<tr><th");383            if (parameterCount > 1) {384                writer.printf(" colspan=\"%d\"", parameterCount);385            }386            writer.print(">Messages</th></tr>");387            writer.print("<tr><td");388            if (parameterCount > 1) {389                writer.printf(" colspan=\"%d\"", parameterCount);390            }391            writer.print(">");392            writeReporterMessages(reporterMessages);393            writer.print("</td></tr>");394            hasRows = true;395        }396        // Write exception (if any)397        Throwable throwable = result.getThrowable();398        if (throwable != null) {399            writer.print("<tr><th");400            if (parameterCount > 1) {401                writer.printf(" colspan=\"%d\"", parameterCount);402            }403            writer.print(">");404            writer.print((result.getStatus() == ITestResult.SUCCESS ? "Expected Exception"405                    : "Exception"));406            writer.print("</th></tr>");407            writer.print("<tr><td");408            if (parameterCount > 1) {409                writer.printf(" colspan=\"%d\"", parameterCount);410            }411            writer.print(">");412            writeStackTrace(throwable);413            writer.print("</td></tr>");414            hasRows = true;415        }416        if (!hasRows) {417            writer.print("<tr><th");418            if (parameterCount > 1) {419                writer.printf(" colspan=\"%d\"", parameterCount);420            }421            writer.print(" class=\"invisible\"/></tr>");422        }423        writer.print("</table>");424        writer.println("<p class=\"totop\"><a href=\"#summary\">back to summary</a></p>");425    }426    protected void writeReporterMessages(List<String> reporterMessages) {427        writer.print("<div class=\"messages\">");428        Iterator<String> iterator = reporterMessages.iterator();429        assert iterator.hasNext();430        if (Reporter.getEscapeHtml()) {431        	writer.print(Utils.escapeHtml(iterator.next()));432        } else {433        	writer.print(iterator.next());434        }435        while (iterator.hasNext()) {436            writer.print("<br/>");437            if (Reporter.getEscapeHtml()) {438            	writer.print(Utils.escapeHtml(iterator.next()));439            } else {440            	writer.print(iterator.next());441            }442        }443        writer.print("</div>");444    }445    protected void writeStackTrace(Throwable throwable) {446        writer.print("<div class=\"stacktrace\">");447        writer.print(Utils.shortStackTrace(throwable, true));448        writer.print("</div>");449    }450    /**451     * Writes a TH element with the specified contents and CSS class names.452     * 453     * @param html454     *            the HTML contents455     * @param cssClasses456     *            the space-delimited CSS classes or null if there are no457     *            classes to apply458     */459    protected void writeTableHeader(String html, String cssClasses) {460        writeTag("th", html, cssClasses);461    }462    /**463     * Writes a TD element with the specified contents.464     * 465     * @param html466     *            the HTML contents467     */468    protected void writeTableData(String html) {469        writeTableData(html, null);470    }471    /**472     * Writes a TD element with the specified contents and CSS class names.473     * ...Source:CustomReport.java  
...208		// Print totals if there was more than one test209		if (testIndex >= 1) {210			writer.print("<tr>");211			writer.print("<th>Total</th>");212			writeTableHeader(integerFormat.format(totalPassedTests), "num");213			writeTableHeader(integerFormat.format(totalSkippedTests), (totalSkippedTests > 0 ? "num attn" : "num"));214			writeTableHeader(integerFormat.format(totalFailedTests), (totalFailedTests > 0 ? "num attn" : "num"));215			writeTableHeader(decimalFormat.format(millisecondsToSeconds(totalDuration)), "num");216			writer.print("<th colspan=\"2\"></th>");217			writer.print("</tr>");218		}219220		writer.print("</table>");221	}222223	/**224	 * Writes a summary of all the test scenarios.225	 */226	protected void writeScenarioSummary() {227		writer.print("<table>");228		writer.print("<thead>");229		writer.print("<tr>");230		writer.print("<th>Class</th>");231		writer.print("<th>Method</th>");232		writer.print("<th>Name</th>");233		writer.print("<th>Start</th>");234		writer.print("<th>Seconds</th>");235		writer.print("</tr>");236		writer.print("</thead>");237238		int testIndex = 0;239		int scenarioIndex = 0;240		for (SuiteResult suiteResult : suiteResults) {241			writer.print("<tbody><tr><th colspan=\"5\">");242			writer.print(Utils.escapeHtml(suiteResult.getSuiteName()));243			writer.print("</th></tr></tbody>");244245			for (TestResult testResult : suiteResult.getTestResults()) {246				writer.print("<tbody id=\"t");247				writer.print(testIndex);248				writer.print("\">");249250				String testName = Utils.escapeHtml(testResult.getTestName());251252				scenarioIndex += writeScenarioSummary(testName + " — failed (configuration methods)",253						testResult.getFailedConfigurationResults(), "failed", scenarioIndex);254				scenarioIndex += writeScenarioSummary(testName + " — failed", testResult.getFailedTestResults(),255						"failed", scenarioIndex);256				scenarioIndex += writeScenarioSummary(testName + " — skipped (configuration methods)",257						testResult.getSkippedConfigurationResults(), "skipped", scenarioIndex);258				scenarioIndex += writeScenarioSummary(testName + " — skipped", testResult.getSkippedTestResults(),259						"skipped", scenarioIndex);260				scenarioIndex += writeScenarioSummary(testName + " — passed", testResult.getPassedTestResults(),261						"passed", scenarioIndex);262263				writer.print("</tbody>");264265				testIndex++;266			}267		}268269		writer.print("</table>");270	}271272	/**273	 * Writes the scenario summary for the results of a given state for a single274	 * test.275	 */276	private int writeScenarioSummary(String description, List<ClassResult> classResults, String cssClassPrefix,277			int startingScenarioIndex) {278		int scenarioCount = 0;279		if (!classResults.isEmpty()) {280			writer.print("<tr><th colspan=\"5\">");281			writer.print(description);282			writer.print("</th></tr>");283284			int scenarioIndex = startingScenarioIndex;285			int classIndex = 0;286			for (ClassResult classResult : classResults) {287				String cssClass = cssClassPrefix + ((classIndex % 2) == 0 ? "even" : "odd");288289				buffer.setLength(0);290291				int scenariosPerClass = 0;292				int methodIndex = 0;293				for (MethodResult methodResult : classResult.getMethodResults()) {294					List<ITestResult> results = methodResult.getResults();295					int resultsCount = results.size();296					assert resultsCount > 0;297298					ITestResult aResult = results.iterator().next();299					String methodName = Utils.escapeHtml(aResult.getMethod().getMethodName());300					long start = aResult.getStartMillis();301					long duration = aResult.getEndMillis() - start;302303					// The first method per class shares a row with the class304					// header305					if (methodIndex > 0) {306						buffer.append("<tr class=\"").append(cssClass).append("\">");307308					}309310					// Write the timing information with the first scenario per311					// method312					buffer.append("<td><a href=\"#m").append(scenarioIndex).append("\">")313							.append(methodName + "</a></td>").append("<td rowspan=\"1\">" + aResult.getName() + "</td>")314							.append("<td rowspan=\"").append(resultsCount).append("\">")315							.append(parseUnixTimeToTimeOfDay(start)).append("</td>").append("<td rowspan=\"")316							.append(resultsCount).append("\">")317							.append(decimalFormat.format(millisecondsToSeconds(duration))).append("</td></tr>");318					scenarioIndex++;319320					// Write the remaining scenarios for the method321					for (int i = 1; i < resultsCount; i++) {322						buffer.append("<tr class=\"").append(cssClass).append("\">").append("<td><a href=\"#m")323								.append(scenarioIndex).append("\">").append(methodName + "</a></td>")324								.append("<td rowspan=\"1\">" + aResult.getName() + "</td></tr>");325						scenarioIndex++;326					}327328					scenariosPerClass += resultsCount;329					methodIndex++;330				}331332				// Write the test results for the class333				writer.print("<tr class=\"");334				writer.print(cssClass);335				writer.print("\">");336				writer.print("<td rowspan=\"");337				writer.print(scenariosPerClass);338				writer.print("\">");339				writer.print(Utils.escapeHtml(classResult.getClassName()));340				writer.print("</td>");341				writer.print(buffer);342343				classIndex++;344			}345			scenarioCount = scenarioIndex - startingScenarioIndex;346		}347		return scenarioCount;348	}349350	/**351	 * Writes the details for all test scenarios.352	 */353	protected void writeScenarioDetails() {354		int scenarioIndex = 0;355		for (SuiteResult suiteResult : suiteResults) {356			for (TestResult testResult : suiteResult.getTestResults()) {357				writer.print("<h2>");358				writer.print(Utils.escapeHtml(testResult.getTestName()));359				writer.print("</h2>");360361				scenarioIndex += writeScenarioDetails(testResult.getFailedConfigurationResults(), scenarioIndex);362				scenarioIndex += writeScenarioDetails(testResult.getFailedTestResults(), scenarioIndex);363				scenarioIndex += writeScenarioDetails(testResult.getSkippedConfigurationResults(), scenarioIndex);364				scenarioIndex += writeScenarioDetails(testResult.getSkippedTestResults(), scenarioIndex);365				scenarioIndex += writeScenarioDetails(testResult.getPassedTestResults(), scenarioIndex);366			}367		}368	}369370	/**371	 * Writes the scenario details for the results of a given state for a single372	 * test.373	 */374	private int writeScenarioDetails(List<ClassResult> classResults, int startingScenarioIndex) {375		int scenarioIndex = startingScenarioIndex;376		for (ClassResult classResult : classResults) {377			String className = classResult.getClassName();378			for (MethodResult methodResult : classResult.getMethodResults()) {379				List<ITestResult> results = methodResult.getResults();380				assert !results.isEmpty();381382				ITestResult mResult = results.iterator().next();383				String label = Utils.escapeHtml(384						className + "#" + mResult.getMethod().getMethodName() + " ( " + mResult.getName() + " )");385				for (ITestResult result : results) {386					writeScenario(scenarioIndex, label, result);387					scenarioIndex++;388				}389			}390		}391392		return scenarioIndex - startingScenarioIndex;393	}394395	/**396	 * Writes the details for an individual test scenario.397	 */398	private void writeScenario(int scenarioIndex, String label, ITestResult result) {399		writer.print("<h3 id=\"m");400		writer.print(scenarioIndex);401		writer.print("\">");402		writer.print(label);403		writer.print("</h3>");404405		writer.print("<table class=\"result\">");406407		// Write test parameters (if any)408		Object[] parameters = result.getParameters();409		int parameterCount = (parameters == null ? 0 : parameters.length);410		if (parameterCount > 0) {411			writer.print("<tr class=\"param\">");412			for (int i = 1; i <= parameterCount; i++) {413				writer.print("<th>Parameter #");414				writer.print(i);415				writer.print("</th>");416			}417			writer.print("</tr><tr class=\"param stripe\">");418			for (Object parameter : parameters) {419				writer.print("<td>");420				writer.print(Utils.escapeHtml(Utils.toString(parameter, Object.class)));421				writer.print("</td>");422			}423			writer.print("</tr>");424		}425426		// Write reporter messages (if any)427		List<String> reporterMessages = Reporter.getOutput(result);428		if (!reporterMessages.isEmpty()) {429			writer.print("<tr><th");430			if (parameterCount > 1) {431				writer.print(" colspan=\"");432				writer.print(parameterCount);433				writer.print("\"");434			}435			writer.print(">Messages</th></tr>");436437			writer.print("<tr><td");438			if (parameterCount > 1) {439				writer.print(" colspan=\"");440				writer.print(parameterCount);441				writer.print("\"");442			}443			writer.print(">");444			writeReporterMessages(reporterMessages);445			writer.print("</td></tr>");446		}447448		// Write exception (if any)449		Throwable throwable = result.getThrowable();450		if (throwable != null) {451			writer.print("<tr><th");452			if (parameterCount > 1) {453				writer.print(" colspan=\"");454				writer.print(parameterCount);455				writer.print("\"");456			}457			writer.print(">");458			writer.print((result.getStatus() == ITestResult.SUCCESS ? "Expected Exception" : "Exception"));459			writer.print("</th></tr>");460461			writer.print("<tr><td");462			if (parameterCount > 1) {463				writer.print(" colspan=\"");464				writer.print(parameterCount);465				writer.print("\"");466			}467			writer.print(">");468			writeStackTrace(throwable);469			writer.print("</td></tr>");470		}471472		writer.print("</table>");473		writer.print("<p class=\"totop\"><a href=\"#summary\">back to summary</a></p>");474	}475476	protected void writeReporterMessages(List<String> reporterMessages) {477		writer.print("<div class=\"messages\">");478		Iterator<String> iterator = reporterMessages.iterator();479		assert iterator.hasNext();480		writer.print(Utils.escapeHtml(iterator.next()));481		while (iterator.hasNext()) {482			writer.print("<br/>");483			writer.print(Utils.escapeHtml(iterator.next()));484		}485		writer.print("</div>");486	}487488	protected void writeStackTrace(Throwable throwable) {489		writer.print("<div class=\"stacktrace\">");490		writer.print(Utils.stackTrace(throwable, true)[0]);491		writer.print("</div>");492	}493494	/**495	 * Writes a TH element with the specified contents and CSS class names.496	 *497	 * @param html498	 *            the HTML contents499	 * @param cssClasses500	 *            the space-delimited CSS classes or null if there are no501	 *            classes to apply502	 */503	protected void writeTableHeader(String html, String cssClasses) {504		writeTag("th", html, cssClasses);505	}506507	/**508	 * Writes a TD element with the specified contents.509	 *510	 * @param html511	 *            the HTML contents512	 */513	protected void writeTableData(String html) {514		writeTableData(html, null);515	}516517	/**
...Source:CustomSummaryReport.java  
...186		// Print totals if there was more than one test187		if ( testIndex >= 1 ) {188			writer.print("<tr>");189			writer.print("<th>Total</th>");190			writeTableHeader( integerFormat.format(totalPassedTests), "num");191			writeTableHeader( integerFormat.format(totalSkippedTests), (totalSkippedTests > 0 ? "num attn" : "num"));192			writeTableHeader( integerFormat.format(totalFailedTests), (totalFailedTests > 0 ? "num attn" : "num"));193			writeTableHeader( decimalFormat.format(millisecondsToSeconds(totalDuration)), "num");194			writer.print("<th colspan=\"2\"></th>");195			writer.print("</tr>");196		}197198		writer.print("</table>");199	}200	/**201	 * Writes a summary of all the test scenarios.202	 */203	protected void writeUserSummary() {204205		TreeMap<String,TreeMap<String,Integer>> userToTestCaseCntMap = new TreeMap<String,TreeMap<String,Integer>>();206207		for ( SuiteResult suiteResult : suiteResults ) {208209			for ( TestResult testResult : suiteResult.getTestResults() ) {210211				@SuppressWarnings("unused")212				String testName = Utils.escapeHtml( testResult.getTestName() );213214				for ( ClassResult classResult : testResult.getFailedTestResults() ) {215					for ( MethodResult methodResult : classResult.getMethodResults() ) {216						List<ITestResult> results = methodResult.getResults();217						int resultsCount = results.size();218						assert resultsCount > 0;219220						ITestResult aResult = results.iterator().next();221						updateUserEntry(aResult,userToTestCaseCntMap,"failure");222					}223				}224				for ( ClassResult classResult : testResult.getSkippedTestResults() ) {225					for ( MethodResult methodResult : classResult.getMethodResults() ) {226						List<ITestResult> results = methodResult.getResults();227						int resultsCount = results.size();228						assert resultsCount > 0;229230						ITestResult aResult = results.iterator().next();231						updateUserEntry(aResult,userToTestCaseCntMap,"skipped");232					}233				}234				for ( ClassResult classResult : testResult.getPassedTestResults() ) {235					for ( MethodResult methodResult : classResult.getMethodResults() ) {236						List<ITestResult> results = methodResult.getResults();237						int resultsCount = results.size();238						assert resultsCount > 0;239240						ITestResult aResult = results.iterator().next();241						updateUserEntry(aResult,userToTestCaseCntMap,"success");242					}243				}244245			}246		}247		writer.print("<table>");248		writer.print("<thead>");249		writer.print("<tr>");250		writer.print("<th>XXX</th>");251		HashMap<String,Integer> hm = new HashMap<String,Integer>();252		for(String user: userToTestCaseCntMap.keySet()){253			writer.print("<th>"+user+"</th>");254			hm.put(user, userToTestCaseCntMap.get(user).get("success")+userToTestCaseCntMap.get(user).get("failure")+userToTestCaseCntMap.get(user).get("skipped"));255			256		}257		writer.print("</tr>");258		writer.print("</thead>");259		writer.print("<tbody>");260		261		writer.print("<tr>");262		writer.print("<td>SUCCESS</td>");263		for(String user: userToTestCaseCntMap.keySet()){264			writer.print("<td>"+userToTestCaseCntMap.get(user).get("success")+"</td>");265		}266		writer.print("</tr>");267		writer.print("<tr>");268		writer.print("<td>FAILURE</td>");269		for(String user: userToTestCaseCntMap.keySet()){270			writer.print("<td>"+userToTestCaseCntMap.get(user).get("failure")+"</td>");271		}272		writer.print("</tr>");273		writer.print("<tr>");274		writer.print("<td>SKIPPED</td>");275		for(String user: userToTestCaseCntMap.keySet()){276			writer.print("<td>"+userToTestCaseCntMap.get(user).get("skipped")+"</td>");277		}278		writer.print("</tr>");279		writer.print("<tr>");280		writer.print("<td>TOTAL</td>");281		for(String user: userToTestCaseCntMap.keySet()){282			writer.print("<td>"+hm.get(user)+"</td>");283		}284		writer.print("</tr>");285		writer.print("</tbody>");286		writer.print("</table>");287	}288289	protected void updateUserEntry(ITestResult aResult, TreeMap<String,TreeMap<String,Integer>> userToTestCaseCntMap, String type){290		String user = "unknown";291		if(aResult.getMethod().getConstructorOrMethod() != null && aResult.getMethod().getConstructorOrMethod().getMethod() != null && aResult.getMethod().getConstructorOrMethod().getMethod().getAnnotation(TestCase.class) != null && aResult.getMethod().getConstructorOrMethod().getMethod().getAnnotation(TestCase.class).Author() !=null){292			user = Utils.escapeHtml(aResult.getMethod().getConstructorOrMethod().getMethod().getAnnotation(TestCase.class).Author()).trim();293		}294		if(userToTestCaseCntMap.containsKey(user)){295			for(String key: userToTestCaseCntMap.keySet()){296				if(user.equalsIgnoreCase(key)){297					if(userToTestCaseCntMap.get(key) == null || userToTestCaseCntMap.get(key).isEmpty()){298						TreeMap<String,Integer> tm = new TreeMap<String,Integer>();299						tm.put("success", 0);300						tm.put("failure", 0);301						tm.put("skipped", 0);302						userToTestCaseCntMap.put(key,tm);303304					}else{305						TreeMap<String,Integer> tm = userToTestCaseCntMap.get(key);306						tm.put(type,tm.get(type)+1);307308						break;309					}310				}311			}312		}else{313			TreeMap<String,Integer> tm = new TreeMap<String,Integer>();314			tm.put("success", 0);315			tm.put("failure", 0);316			tm.put("skipped", 0);317			tm.put(type,1);318			userToTestCaseCntMap.put(user,tm);319		}320321	}322	323	/**324	 * Writes a TH element with the specified contents and CSS class names.325	 *326	 * @param html       the HTML contents327	 * @param cssClasses the space-delimited CSS classes or null if there are no328	 *                   classes to apply329	 */330	protected void writeTableHeader(String html, String cssClasses) {331		writeTag("th", html, cssClasses);332	}333334	/**335	 * Writes a TD element with the specified contents.336	 *337	 * @param html the HTML contents338	 */339	protected void writeTableData(String html) {340		writeTableData(html, null);341	}342343	/**344	 * Writes a TD element with the specified contents and CSS class names.
...writeTableHeader
Using AI Code Generation
1writeTableHeader()2writeTableFooter()3writeTableHeader()4writeTableFooter()5writeTableHeader()6writeTableFooter()7writeTableHeader()8writeTableFooter()9writeTableHeader()10writeTableFooter()11writeTableHeader()12writeTableFooter()13writeTableHeader()14writeTableFooter()writeTableHeader
Using AI Code Generation
1org.testng.reporters.EmailableReporter2 reporter = new org.testng.reporters.EmailableReporter2();2Class clazz = reporter.getClass();3Method method = clazz.getDeclaredMethod("writeTableHeader", new Class[] { java.lang.String.class, java.lang.String.class });4method.setAccessible(true);5method.invoke(reporter, new Object[] { "TestNG Report", "TestNG Report" });6org.testng.reporters.EmailableReporter2 reporter = new org.testng.reporters.EmailableReporter2();7Class clazz = reporter.getClass();8Method method = clazz.getDeclaredMethod("writeTableFooter", new Class[] {});9method.setAccessible(true);10method.invoke(reporter, new Object[] {});11org.testng.reporters.EmailableReporter2 reporter = new org.testng.reporters.EmailableReporter2();12Class clazz = reporter.getClass();13Method method = clazz.getDeclaredMethod("writeTableHeader", new Class[] { java.lang.String.class, java.lang.String.class });14method.setAccessible(true);15method.invoke(reporter, new Object[] { "TestNG Report", "TestNG Report"TestNG is a Java-based open-source framework for test automation that includes various test types, such as unit testing, functional testing, E2E testing, etc. TestNG is in many ways similar to JUnit and NUnit. But in contrast to its competitors, its extensive features make it a lot more reliable framework. One of the major reasons for its popularity is its ability to structure tests and improve the scripts' readability and maintainability. Another reason can be the important characteristics like the convenience of using multiple annotations, reliance, and priority that make this framework popular among developers and testers for test design. You can refer to the TestNG tutorial to learn why you should choose the TestNG framework.
You can push your abilities to do automated testing using TestNG and advance your career by earning a TestNG certification. Check out our TestNG certification.
Watch this complete tutorial to learn how you can leverage the capabilities of the TestNG framework for Selenium automation testing.
Get 100 minutes of automation test minutes FREE!!
