org.testng.reporters.TestHTMLReporter Maven / Gradle / Ivy
Show all versions of testng Show documentation
package org.testng.reporters;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.TestRunner;
import org.testng.annotations.CustomAttribute;
import org.testng.internal.Utils;
import org.testng.log4testng.Logger;
/** This class implements an HTML reporter for individual tests. */
public class TestHTMLReporter implements ITestListener {
private static final Comparator NAME_COMPARATOR = new NameComparator();
private static final Comparator CONFIGURATION_COMPARATOR =
new ConfigurationComparator();
private ITestContext m_testContext = null;
/////
// implements ITestListener
//
@Override
public void onStart(ITestContext context) {
m_testContext = context;
}
@Override
public void onFinish(ITestContext context) {
generateLog(
m_testContext,
null /* host */,
m_testContext.getOutputDirectory(),
context.getFailedConfigurations().getAllResults(),
context.getSkippedConfigurations().getAllResults(),
context.getPassedTests().getAllResults(),
context.getFailedTests().getAllResults(),
context.getSkippedTests().getAllResults(),
context.getFailedButWithinSuccessPercentageTests().getAllResults());
}
//
// implements ITestListener
/////
private static String getOutputFile(ITestContext context) {
return context.getName() + ".html";
}
public static void generateTable(
PrintWriter pw,
String title,
Collection tests,
String cssClass,
Comparator comparator) {
pw.append("\n")
.append("")
.append(title)
.append(" \n")
.append("")
.append("Test method \n")
.append("Attribute(s) \n")
.append("Exception \n")
.append("Time (seconds) \n")
.append("Instance \n")
.append(" \n");
if (tests instanceof List) {
((List) tests).sort(comparator);
}
// User output?
String id;
Throwable tw;
for (ITestResult tr : tests) {
pw.append("\n");
// Test method
ITestNGMethod method = tr.getMethod();
String name = method.getMethodName();
pw.append("")
.append("")
.append(name)
.append("");
// Test class
String testClass = tr.getTestClass().getName();
if (testClass != null) {
pw.append("
").append("Test class: ").append(testClass);
// Test name
String testName = tr.getTestName();
if (testName != null) {
pw.append(" (").append(testName).append(")");
}
}
// Method description
if (!Utils.isStringEmpty(method.getDescription())) {
pw.append("
").append("Test method: ").append(method.getDescription());
}
Object[] parameters = tr.getParameters();
if (parameters != null && parameters.length > 0) {
pw.append("
Parameters: ");
for (int j = 0; j < parameters.length; j++) {
if (j > 0) {
pw.append(", ");
}
pw.append(parameters[j] == null ? "null" : parameters[j].toString());
}
}
//
// Output from the method, created by the user calling Reporter.log()
//
{
List output = Reporter.getOutput(tr);
if (!output.isEmpty()) {
pw.append("
");
// Method name
String divId = "Output-" + tr.hashCode();
pw.append("\n")
.append("Show output\n")
.append("\nShow all outputs\n");
// Method output
pw.append("\n");
for (String s : output) {
pw.append(s).append("
\n");
}
pw.append("\n");
}
}
pw.append(" \n");
// Custom attributes
CustomAttribute[] attributes = tr.getMethod().getAttributes();
if (attributes != null && attributes.length > 0) {
pw.append("");
String divId = "attributes-" + tr.hashCode();
pw.append("\n")
.append("Show attributes\n")
.append("\n");
pw.append("\n");
Arrays.stream(attributes)
.map(
attribute ->
"name: " + attribute.name() + ", value:" + Arrays.toString(attribute.values()))
.forEach(
line -> {
pw.append(Utils.escapeHtml(line));
pw.append("
");
});
pw.append("");
pw.append(" ");
}
// Exception
tw = tr.getThrowable();
String stackTrace;
String fullStackTrace;
id = "stack-trace" + tr.hashCode();
pw.append("");
if (null != tw) {
fullStackTrace = Utils.longStackTrace(tw, true);
stackTrace = "" + Utils.shortStackTrace(tw, true) + "
";
pw.append(stackTrace);
// JavaScript link
pw.append("")
.append("Click to show all stack frames")
.append("\n")
.append("")
.append("")
.append(fullStackTrace)
.append("
")
.append("");
}
pw.append(" \n");
// Time
long time = (tr.getEndMillis() - tr.getStartMillis()) / 1000;
String strTime = Long.toString(time);
pw.append("").append(strTime).append(" \n");
// Instance
Object instance = tr.getInstance();
pw.append("").append(Objects.toString(instance)).append(" ");
pw.append(" \n");
}
pw.append("
\n");
}
private static String arrayToString(String[] array) {
StringBuilder result = new StringBuilder();
for (String element : array) {
result.append(element).append(" ");
}
return result.toString();
}
private static final String HEAD =
"\n\n"
+ "\n"
+ "\n";
public static void generateLog(
ITestContext testContext,
String host,
String outputDirectory,
Collection failedConfs,
Collection skippedConfs,
Collection passedTests,
Collection failedTests,
Collection skippedTests,
Collection percentageTests) {
try (PrintWriter writer =
new PrintWriter(Utils.openWriter(outputDirectory, getOutputFile(testContext)))) {
writer
.append("\n\n")
.append("TestNG: ")
.append(testContext.getName())
.append(" \n")
.append(HtmlHelper.getCssString())
.append(HEAD)
.append("\n")
.append("\n");
Date startDate = testContext.getStartDate();
Date endDate = testContext.getEndDate();
long duration = (endDate.getTime() - startDate.getTime()) / 1000;
int passed =
testContext.getPassedTests().size()
+ testContext.getFailedButWithinSuccessPercentageTests().size();
int failed = testContext.getFailedTests().size();
int skipped = testContext.getSkippedTests().size();
String hostLine =
Utils.isStringEmpty(host) ? "" : "Remote host: " + host + " \n ";
writer
.append("")
.append(testContext.getName())
.append("
")
.append("\n")
.append("\n")
// .append("Property
// file: ").append(m_testRunner.getPropertyFileName()).append(" \n")
// .append(" \n")
.append("Tests passed/Failed/Skipped: ")
.append(Integer.toString(passed))
.append("/")
.append(Integer.toString(failed))
.append("/")
.append(Integer.toString(skipped))
.append(" \n")
.append(" \n")
.append("Started on: ")
.append(testContext.getStartDate().toString())
.append(" \n")
.append(" \n")
.append(hostLine)
.append("Total time: ")
.append(Long.toString(duration))
.append(" seconds (")
.append(Long.toString(endDate.getTime() - startDate.getTime()))
.append(" ms) \n")
.append("\n")
.append("Included groups: ")
.append(arrayToString(testContext.getIncludedGroups()))
.append(" \n")
.append(" \n")
.append("Excluded groups: ")
.append(arrayToString(testContext.getExcludedGroups()))
.append(" \n")
.append(" \n")
.append("
\n");
writer.append(
"(Hover the method name to see the test class name)\n");
if (!failedConfs.isEmpty()) {
generateTable(
writer, "FAILED CONFIGURATIONS", failedConfs, "failed", CONFIGURATION_COMPARATOR);
}
if (!skippedConfs.isEmpty()) {
generateTable(
writer, "SKIPPED CONFIGURATIONS", skippedConfs, "skipped", CONFIGURATION_COMPARATOR);
}
if (!failedTests.isEmpty()) {
generateTable(writer, "FAILED TESTS", failedTests, "failed", NAME_COMPARATOR);
}
if (!percentageTests.isEmpty()) {
generateTable(
writer,
"FAILED TESTS BUT WITHIN SUCCESS PERCENTAGE",
percentageTests,
"percent",
NAME_COMPARATOR);
}
if (!passedTests.isEmpty()) {
generateTable(writer, "PASSED TESTS", passedTests, "passed", NAME_COMPARATOR);
}
if (!skippedTests.isEmpty()) {
generateTable(writer, "SKIPPED TESTS", skippedTests, "skipped", NAME_COMPARATOR);
}
writer.append("\n");
} catch (IOException e) {
if (TestRunner.getVerbose() > 1) {
Logger.getLogger(TestRunner.class).error(e.getMessage(), e);
} else {
log(e.getMessage());
}
}
}
private static void log(String s) {
Logger.getLogger(TestHTMLReporter.class).info("[TestHTMLReporter] " + s);
}
private static class NameComparator implements Comparator {
@Override
public int compare(ITestResult o1, ITestResult o2) {
String c1 = o1.getMethod().getMethodName();
String c2 = o2.getMethod().getMethodName();
return c1.compareTo(c2);
}
}
private static class ConfigurationComparator implements Comparator {
@Override
public int compare(ITestResult o1, ITestResult o2) {
ITestNGMethod tm1 = o1.getMethod();
ITestNGMethod tm2 = o2.getMethod();
return annotationValue(tm2) - annotationValue(tm1);
}
private static int annotationValue(ITestNGMethod method) {
if (method.isBeforeSuiteConfiguration()) {
return 10;
}
if (method.isBeforeTestConfiguration()) {
return 9;
}
if (method.isBeforeClassConfiguration()) {
return 8;
}
if (method.isBeforeGroupsConfiguration()) {
return 7;
}
if (method.isBeforeMethodConfiguration()) {
return 6;
}
if (method.isAfterMethodConfiguration()) {
return 5;
}
if (method.isAfterGroupsConfiguration()) {
return 4;
}
if (method.isAfterClassConfiguration()) {
return 3;
}
if (method.isAfterTestConfiguration()) {
return 2;
}
if (method.isAfterSuiteConfiguration()) {
return 1;
}
return 0;
}
}
}