This article provides two ways to generate test reports, the first using ReportNG, and the second rewriting Report Listener itself.
1:
First, use Reporting.
1. First download the ReportNG rack and add it to the project.
2. Then cancel using the default listener of TestNG and check Disable default listeners by right-clicking Project - > Properties - > TestNG - >.
3. Then add the following content in the testng.xml file to specify that report is generated at run time using report.
<listeners>
<listener class-name="org.uncommons.reportng.HTMLReporter" />
<listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
</listeners>
4. When you run the. xml file later, you will generate test reports similar to the following style.
Two:
Next, we introduce the second kind of rewriting Report Listener, which uses htlm splicing to generate report. This approach is currently used in this framework.
1. Create a class ReportListener under the util package.
package util;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;/**
* Generate test reports.
*/
public class ReportListener extends TestListenerAdapter{
private static String reportPath;
private static int pass = 0;
private static int fail = 0;
private static int skip = 0;
private static int all;
private static float successRate;
private static StringBuilder s1;
private static StringBuilder s2;
private static Date begin;
private static Date finish;
private static long duration;
static List<String> screenshotPaths = new ArrayList<String>();
@Override
public void onStart(ITestContext context) {
File htmlReportDir = new File("test-output/report");
if (!htmlReportDir.exists()) {
htmlReportDir.mkdirs();
}
String reportName = formateDate()+".html";
reportPath = htmlReportDir+"/"+reportName;
File report = new File(htmlReportDir,reportName);
if(report.exists()){
try {
report.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
s1 = new StringBuilder("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"
+ "<title >UI Automated test report</title></head><body>"
+ "<div id=\"top\" align=\"center\"><p style=\"font-weight:bold;font-size:150%\">Test Results Report</p>"
+ "<table width=\"90%\" height=\"80\" border=\"1\" align=\"center\" cellspacing=\"0\" rules=\"all\" style=\"table-layout:relative;\">"
+ "<thead style=\"background-color:#ADD8E6;\">"
+ "<tr>"
+ "<th>Overview</th>"
+ "<th>Tests</th>"
+ "<th>Passed</th>"
+ "<th>Skipped</th>"
+ "<th>Failed</th>"
+ "<th>Success rate</th>"
+ "<th>Duration(s)</th>"
+ "</tr>"
+ "</thead>");
s2 = new StringBuilder("<p style=\"font-weight:bold;\">List of details</p>"
+ "<table width=\"90%\" height=\"80\" border=\"1\" align=\"center\" cellspacing=\"0\" rules=\"all\" style=\"table-layout:relative;\">"
+ "<thead style=\"background-color:#ADD8E6;\">"
+ "<tr>"
+ "<th>test case</th>"
+ "<th>Test Case Results</th>"
+ "<th>Duration(s)</th>"
+ "</tr>"
+ "</thead>"
+ "<tbody style=\"word-wrap:break-word;font-weight:bold;\" align=\"center\">");
begin = new Date();
}
@Override
public void onTestSuccess(ITestResult result) {
StringBuilder sb2 = new StringBuilder("<tr><td align=\"center\">");
sb2.append((result.getMethod().getRealClass()+"."+result.getMethod().getMethodName()).substring(16));
sb2.append("</td><td align=\"center\"><font color=\"green\">Passed</font></td>");
long time =
(result.getEndMillis() - result.getStartMillis())/1000;
sb2.append("</td><td align=\"center\">" + time + "</td></tr>");
s2.append(sb2);
pass = pass+1;
}
@Override
public void onTestSkipped(ITestResult result) {
//After adding the method of brewing after case failure, the last case of failure is the state of faied, and the previous cases are skipped, so skipped report is removed. Although this may affect the real skipped case, it will not skipped if the setup method is guaranteed not to hang the normal case.
/* StringBuilder sb2 = new StringBuilder("<tr><td align=\"center\">");
sb2.append((result.getMethod().getRealClass()+"."+result.getMethod().getMethodName()).substring(16));
sb2.append("</td><td align=\"center\"><font color=\"#DAA520\">Skipped</font><br>");
sb2.append(result.getMethod().getMethodName());
sb2.append("<p align=\"center\">Test case <font color="red"> skip </font> </p> </td>;
long time =
(result.getEndMillis() - result.getStartMillis())/1000;
sb2.append("</td><td align=\"center\">" + time + "</td></tr>");
s2.append(sb2);
skip = skip+1;*/
}
@Override
public void onTestFailure(ITestResult result) {
String error;
try {
StringBuilder sb2 = new StringBuilder("<tr><td align=\"center\">");
sb2.append((result.getMethod().getRealClass()+"."+result.getMethod().getMethodName()).substring(16));
sb2.append("</td><td align=\"center\"><font color=\"red\">Failed</font><br>");
sb2.append(result.getTestName());
sb2.append("<p align=\"center\">Use case execution<font color=\"red\">fail</font>,Reason:<br>");
sb2.append("<br><a style=\"background-color:#CCCCCC;\">");
Throwable throwable = result.getThrowable();
if(throwable.getMessage().indexOf("Session info")!=-1)
{
int endIndex = throwable.getMessage().indexOf("(Session info");
error = throwable.getMessage().substring(0, endIndex);
}
else
{
error = throwable.getMessage();//Assertion failure prints only assertions
}
sb2.append(error);
sb2.append("</a></p></td>");
long time =
(result.getEndMillis() - result.getStartMillis())/1000;
sb2.append("</td><td align=\"center\">" + time + "</td></tr>");
s2.append(sb2);
fail = fail+1;
String classname = result.getTestClass().getName();
String methodname = result.getMethod().getMethodName();
TakeScreenshot shot = new TakeScreenshot();
String screenshotPath = shot.takeScreenShot(classname, methodname);
screenshotPaths.add(screenshotPath);
}
catch(Exception e) {
//When there is no Throwable, such as when login or logout hangs, exception s are caught and no Throwable is thrown out.
StringBuilder sb2 = new StringBuilder("<tr><td align=\"center\">");
sb2.append((result.getMethod().getRealClass()+"."+result.getMethod().getMethodName()).substring(16));
sb2.append("</td><td align=\"center\"><font color=\"red\">Failed</font><br>");
sb2.append(result.getTestName());
sb2.append("<p align=\"center\">Use case execution<font color=\"red\">fail</font>,Reason:<br>");
sb2.append("<br><a style=\"background-color:#CCCCCC;\">");
sb2.append(e);
sb2.append("</a></p></td>");
long time =
(result.getEndMillis() - result.getStartMillis())/1000;
sb2.append("</td><td align=\"center\">" + time + "</td></tr>");
s2.append(sb2);
fail = fail+1;
String classname = result.getTestClass().getName();
String methodname = result.getMethod().getMethodName();
TakeScreenshot shot = new TakeScreenshot();
String screenshotPath = shot.takeScreenShot(classname, methodname);
screenshotPaths.add(screenshotPath);
Log4jUtil.error(e);
}
}
@Override
public void onFinish(ITestContext testContext) {
all = fail + pass + skip;
successRate = (float)pass/(float)all*100;
finish = new Date();
duration = (finish.getTime()-begin.getTime())/1000;
StringBuilder sb1 = new StringBuilder("<tbody style=\"word-wrap:break-word;font-weight:bold;\" align=\"center\">"
+ "<tr>"
+ "<td align=\"center\">Smoke</td>"
+ "<td align=\"center\">" + all + "</td>"
+ "<td align=\"center\">" + pass + "</td>"
+ "<td align=\"center\">" + skip + "</td>"
+ "<td align=\"center\">" + fail + "</td>"
+ "<td align=\"center\">" + String.format("%.2f", successRate) + "%" + "</td>"
+ "<td align=\"center\">" + duration + "</td>"
+ "</tr>"
+ "</tbody>"
+ "</table>");StringBuilder sb2 = new StringBuilder("</tbody></table><a href=\"#Top"> Return to the top </a> </div> </body>";
sb2.append("</html>
2. Then add the following to the testng.xml file
<listeners>
<listener class-name="util.ReportListener"></listener>
</listeners>
3. Also cancel the default listener of TestNG, and then run the. xml file, you will generate test reports similar to the following style.