Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.testng.reporters.SuiteHTMLReporter Maven / Gradle / Ivy
package org.testng.reporters;
import static org.testng.internal.Utils.isStringNotEmpty;
import org.testng.IInvokedMethod;
import org.testng.IReporter;
import org.testng.ISuite;
import org.testng.ISuiteResult;
import org.testng.ITestClass;
import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.Reporter;
import org.testng.collections.Maps;
import org.testng.internal.ConstructorOrMethod;
import org.testng.internal.Utils;
import org.testng.xml.XmlSuite;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
/**
* This class implements an HTML reporter for suites.
*
* @author cbeust
* @author Alexandru Popescu
*/
public class SuiteHTMLReporter implements IReporter {
public static final String METHODS_CHRONOLOGICAL = "methods.html";
public static final String METHODS_ALPHABETICAL = "methods-alphabetical.html";
public static final String GROUPS = "groups.html";
public static final String CLASSES = "classes.html";
public static final String REPORTER_OUTPUT = "reporter-output.html";
public static final String METHODS_NOT_RUN = "methods-not-run.html";
public static final String TESTNG_XML = "testng.xml.html";
private Map m_classes = Maps.newHashMap();
private String m_outputDirectory;
@Override
public void generateReport(List xmlSuites, List suites, String outputDirectory) {
m_outputDirectory = generateOutputDirectoryName(outputDirectory + File.separator + "old");
try {
HtmlHelper.generateStylesheet(outputDirectory);
} catch (IOException e) {
// TODO Propagate the exception properly.
e.printStackTrace();
}
for (ISuite suite : suites) {
//
// Generate the various reports
//
XmlSuite xmlSuite = suite.getXmlSuite();
if (xmlSuite.getTests().size() == 0) {
continue;
}
generateTableOfContents(xmlSuite, suite);
generateSuites(xmlSuite, suite);
generateIndex(xmlSuite, suite);
generateMain(xmlSuite, suite);
generateMethodsAndGroups(xmlSuite, suite);
generateMethodsChronologically(xmlSuite, suite, METHODS_CHRONOLOGICAL, false);
generateMethodsChronologically(xmlSuite, suite, METHODS_ALPHABETICAL, true);
generateClasses(xmlSuite, suite);
generateReporterOutput(xmlSuite, suite);
generateExcludedMethodsReport(xmlSuite, suite);
generateXmlFile(xmlSuite, suite);
}
generateIndex(suites);
}
/**
* Overridable by subclasses to create different directory names (e.g. with timestamps).
* @param outputDirectory the output directory specified by the user
*/
protected String generateOutputDirectoryName(String outputDirectory) {
return outputDirectory;
}
private void generateXmlFile(XmlSuite xmlSuite, ISuite suite) {
String content = xmlSuite.toXml().replaceAll("<", "<").replaceAll(">", ">")
.replaceAll(" ", " ").replaceAll("\n", " ");
StringBuffer sb = new StringBuffer("");
sb.append("").append("testng.xml for ")
.append(xmlSuite.getName()).append(" ")
.append(content)
.append(" ");
Utils.writeFile(getOutputDirectory(xmlSuite), TESTNG_XML, sb.toString());
}
/**
* Generate the main index.html file that lists all the suites
* and their result
*/
private void generateIndex(List suites) {
StringBuffer sb = new StringBuffer();
String title = "Test results";
sb.append("\n" + title + " ")
.append(HtmlHelper.getCssString("."))
.append("\n")
.append("").append(title).append("
\n")
.append("")
.append("Suite Passed Failed Skipped testng.xml \n");
int totalFailedTests = 0;
int totalPassedTests = 0;
int totalSkippedTests = 0;
StringBuffer suiteBuf= new StringBuffer();
for (ISuite suite : suites) {
if (suite.getResults().size() == 0) {
continue;
}
String name = suite.getName();
int failedTests= 0;
int passedTests= 0;
int skippedTests= 0;
Map results = suite.getResults();
for (ISuiteResult result : results.values()) {
ITestContext context = result.getTestContext();
failedTests += context.getFailedTests().size();
totalFailedTests += context.getFailedTests().size();
passedTests += context.getPassedTests().size();
totalPassedTests += context.getPassedTests().size();
skippedTests += context.getSkippedTests().size();
totalSkippedTests += context.getSkippedTests().size();
}
String cls = failedTests > 0 ? "invocation-failed"
: (passedTests > 0 ? "invocation-passed" : "invocation-failed");
suiteBuf.append("")
.append("")
.append(name).append(" \n");
suiteBuf.append("" + passedTests + " ")
.append("" + failedTests + " ")
.append("" + skippedTests + " ")
.append("Link").append(" ")
.append(" ");
}
String cls= totalFailedTests > 0 ? "invocation-failed"
: (totalPassedTests > 0 ? "invocation-passed" : "invocation-failed");
sb.append("")
.append("Total ")
.append("").append(totalPassedTests).append(" ")
.append("").append(totalFailedTests).append(" ")
.append("").append(totalSkippedTests).append(" ")
.append(" ")
.append(" \n");
sb.append(suiteBuf);
sb.append("
").append("\n");
Utils.writeFile(m_outputDirectory, "index.html", sb.toString());
}
private void generateExcludedMethodsReport(XmlSuite xmlSuite, ISuite suite) {
Collection excluded = suite.getExcludedMethods();
StringBuffer sb2 = new StringBuffer("Methods that were not run \n");
for (ITestNGMethod method : excluded) {
ConstructorOrMethod m = method.getConstructorOrMethod();
if (m != null) {
sb2.append("")
.append(m.getDeclaringClass().getName() + "." + m.getName());
String description = method.getDescription();
if(isStringNotEmpty(description)) {
sb2.append(" ").append(SP2).append("").append(description).append(" ");
}
sb2.append(" \n");
}
}
sb2.append("
");
Utils.writeFile(getOutputDirectory(xmlSuite), METHODS_NOT_RUN, sb2.toString());
}
private void generateReporterOutput(XmlSuite xmlSuite, ISuite suite) {
StringBuffer sb = new StringBuffer();
//
// Reporter output
//
sb.append("Reporter output ")
.append("");
List output = Reporter.getOutput();
for (String line : output) {
sb.append("").append(line).append(" \n");
}
sb.append("
");
Utils.writeFile(getOutputDirectory(xmlSuite), REPORTER_OUTPUT, sb.toString());
}
private void generateClasses(XmlSuite xmlSuite, ISuite suite) {
StringBuffer sb = new StringBuffer();
sb.append("\n")
.append("\n")
.append("Class name \n")
.append("Method name \n")
.append("Groups \n")
.append(" ")
;
for (ITestClass tc : m_classes.values()) {
sb.append(generateClass(tc));
}
sb.append("
\n");
Utils.writeFile(getOutputDirectory(xmlSuite), CLASSES, sb.toString());
}
private final static String SP = " ";
private final static String SP2 = SP + SP + SP + SP;
private final static String SP3 = SP2 + SP2;
private final static String SP4 = SP3 + SP3;
private String generateClass(ITestClass cls) {
StringBuffer sb = new StringBuffer();
sb.append("\n")
.append("").append(cls.getRealClass().getName()).append(" \n")
.append(" ")
.append(" ")
.append(" \n")
;
String[] tags = new String[] {
"@Test",
"@BeforeClass",
"@BeforeMethod",
"@AfterMethod",
"@AfterClass"
};
ITestNGMethod[][] methods = new ITestNGMethod[][] {
cls.getTestMethods(),
cls.getBeforeClassMethods(),
cls.getBeforeTestMethods(),
cls.getAfterTestMethods(),
cls.getAfterClassMethods()
};
for (int i = 0; i < tags.length; i++) {
sb.append("\n")
.append("").append(tags[i]).append(" \n")
.append(" \n")
.append(dumpMethods(methods[i]))
;
}
// sb.append(" ")
// .append("").append(cls.getRealClass().getName()).append(" \n");
//
// sb.append("").append(SP3).append("Test methods\n")
// .append(dumpMethods(cls.getTestMethods())).append("
\n")
// .append("").append(SP3).append("@BeforeClass\n")
// .append(dumpMethods(cls.getBeforeClassMethods())).append("
\n")
// .append("").append(SP3).append("@BeforeMethod\n")
// .append(dumpMethods(cls.getBeforeTestMethods())).append("
\n")
// .append("").append(SP3).append("@AfterMethod\n")
// .append(dumpMethods(cls.getAfterTestMethods())).append("
\n")
// .append("").append(SP3).append("@AfterClass\n")
// .append(dumpMethods(cls.getAfterClassMethods())).append("
\n")
// ;
String result = sb.toString();
return result;
}
private String dumpMethods(ITestNGMethod[] testMethods) {
StringBuffer sb = new StringBuffer();
if(null == testMethods || testMethods.length == 0) {
return "";
}
for (ITestNGMethod m : testMethods) {
sb.append("\n");
sb.append(" \n")
.append("").append(m.getMethodName()).append(" \n")
;
String[] groups = m.getGroups();
if (groups != null && groups.length > 0) {
sb.append("");
for (String g : groups) {
sb.append(g).append(" ");
}
sb.append(" \n");
}
else {
sb.append(" ");
}
sb.append(" \n");
}
// StringBuffer sb = new StringBuffer(" "); //"");
// for (ITestNGMethod tm : testMethods) {
// sb
// .append(SP4).append(tm.getMethodName()).append("()\n")
// .append(dumpGroups(tm.getGroups()))
// .append(" ");
// ;
// }
String result = sb.toString();
return result;
}
private String dumpGroups(String[] groups) {
StringBuffer sb = new StringBuffer();
if (null != groups && groups.length > 0) {
sb.append(SP4).append("[");
for (String g : groups) {
sb.append(g).append(" ");
}
sb.append("] \n");
}
String result = sb.toString();
return result;
}
/**
* Generate information about the methods that were run
*/
public static final String AFTER= "<<";
public static final String BEFORE = ">>";
private void generateMethodsChronologically(XmlSuite xmlSuite, ISuite suite,
String outputFileName, boolean alphabetical)
{
try (BufferedWriter bw = Utils.openWriter(getOutputDirectory(xmlSuite), outputFileName)) {
bw.append("Methods run, sorted chronologically ");
bw.append("" + BEFORE + " means before, " + AFTER + " means after
");
long startDate = -1;
bw.append("").append(suite.getName()).append("
");
bw.append("(Hover the method name to see the test class name)
\n");
Collection invokedMethods = suite.getAllInvokedMethods();
if (alphabetical) {
@SuppressWarnings({"unchecked"})
Comparator alphabeticalComparator = new Comparator(){
@Override
public int compare(Object o1, Object o2) {
IInvokedMethod m1 = (IInvokedMethod) o1;
IInvokedMethod m2 = (IInvokedMethod) o2;
return m1.getTestMethod().getMethodName().compareTo(m2.getTestMethod().getMethodName());
}
};
Collections.sort((List) invokedMethods, alphabeticalComparator);
}
SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss");
boolean addedHeader = false;
synchronized(invokedMethods) {
for (IInvokedMethod iim : invokedMethods) {
ITestNGMethod tm = iim.getTestMethod();
if (!addedHeader) {
bw.append("\n")
.append("")
.append("Time ")
.append("Delta (ms) ")
.append("Suite configuration ")
.append("Test configuration ")
.append("Class configuration ")
.append("Groups configuration ")
.append("Method configuration ")
.append("Test method ")
.append("Thread ")
.append("Instances ")
.append(" \n");
addedHeader = true;
}
String methodName = tm.toString();
boolean bc = tm.isBeforeClassConfiguration();
boolean ac = tm.isAfterClassConfiguration();
boolean bt = tm.isBeforeTestConfiguration();
boolean at = tm.isAfterTestConfiguration();
boolean bs = tm.isBeforeSuiteConfiguration();
boolean as = tm.isAfterSuiteConfiguration();
boolean bg = tm.isBeforeGroupsConfiguration();
boolean ag = tm.isAfterGroupsConfiguration();
boolean setUp = tm.isBeforeMethodConfiguration();
boolean tearDown = tm.isAfterMethodConfiguration();
boolean isClassConfiguration = bc || ac;
boolean isGroupsConfiguration = bg || ag;
boolean isTestConfiguration = bt || at;
boolean isSuiteConfiguration = bs || as;
boolean isSetupOrTearDown = setUp || tearDown;
String configurationClassMethod = isClassConfiguration ? (bc ? BEFORE : AFTER) + methodName : SP;
String configurationTestMethod = isTestConfiguration ? (bt ? BEFORE : AFTER) + methodName : SP;
String configurationGroupsMethod = isGroupsConfiguration ? (bg ? BEFORE : AFTER) + methodName : SP;
String configurationSuiteMethod = isSuiteConfiguration ? (bs ? BEFORE : AFTER) + methodName : SP;
String setUpOrTearDownMethod = isSetupOrTearDown ? (setUp ? BEFORE : AFTER) + methodName : SP;
String testMethod = tm.isTest() ? methodName : SP;
StringBuffer instances = new StringBuffer();
for (long o : tm.getInstanceHashCodes()) {
instances.append(o).append(" ");
}
if (startDate == -1) {
startDate = iim.getDate();
}
String date = format.format(iim.getDate());
bw.append("")
.append(" ").append(date).append(" ")
.append(" ").append(Long.toString(iim.getDate() - startDate)).append(" ")
.append(td(configurationSuiteMethod))
.append(td(configurationTestMethod))
.append(td(configurationClassMethod))
.append(td(configurationGroupsMethod))
.append(td(setUpOrTearDownMethod))
.append(td(testMethod))
.append(" ").append(tm.getId()).append(" ")
.append(" ").append(instances).append(" ")
.append(" \n")
;
}
}
bw.append("
\n");
} catch (IOException e) {
Utils.log("[SuiteHTMLReporter]", 1, "Error writing to " + outputFileName + ": " + e.getMessage());
}
}
/**
* Generate a HTML color based on the class of the method
*/
private String createColor(ITestNGMethod tm) {
// real class can be null if this client is remote (not serializable)
long color = tm.getRealClass() != null ? tm.getRealClass().hashCode() & 0xffffff: 0xffffff;
long[] rgb = {
((color & 0xff0000) >> 16) & 0xff,
((color & 0x00ff00) >> 8) & 0xff,
color & 0xff
};
// Not too dark
for (int i = 0; i < rgb.length; i++) {
if (rgb[i] < 0x60) {
rgb[i] += 0x60;
}
}
long adjustedColor = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
String result = Long.toHexString(adjustedColor);
return result;
}
private String td(String s) {
StringBuffer result = new StringBuffer();
String prefix = "";
if (s.startsWith(BEFORE)) {
prefix = BEFORE;
}
else if (s.startsWith(AFTER)) {
prefix = AFTER;
}
if (! s.equals(SP)) {
result.append("");
int open = s.lastIndexOf("(");
int start = s.substring(0, open).lastIndexOf(".");
// int end = s.lastIndexOf(")");
if (start >= 0) {
result.append(prefix + s.substring(start + 1, open));
}
else {
result.append(prefix + s);
}
result.append(" \n");
}
else {
result.append("").append(SP).append(" ");
}
return result.toString();
}
private void ppp(String s) {
System.out.println("[SuiteHTMLReporter] " + s);
}
/**
* Generate information about methods and groups
*/
private void generateMethodsAndGroups(XmlSuite xmlSuite, ISuite suite) {
StringBuffer sb = new StringBuffer();
Map> groups = suite.getMethodsByGroups();
sb.append("Groups used for this test run ");
if (groups.size() > 0) {
sb.append("\n")
.append(" Group name ")
.append("Methods ");
String[] groupNames = groups.keySet().toArray(new String[groups.size()]);
Arrays.sort(groupNames);
for (String group : groupNames) {
Collection methods = groups.get(group);
sb.append("").append(group).append(" ");
StringBuffer methodNames = new StringBuffer();
Map uniqueMethods = Maps.newHashMap();
for (ITestNGMethod tm : methods) {
uniqueMethods.put(tm, tm);
}
for (ITestNGMethod tm : uniqueMethods.values()) {
methodNames.append(tm.toString()).append(" ");
}
sb.append("" + methodNames.toString() + " \n");
}
sb.append("
\n");
}
Utils.writeFile(getOutputDirectory(xmlSuite), GROUPS, sb.toString());
}
private void generateIndex(XmlSuite xmlSuite, ISuite sr) {
StringBuffer index = new StringBuffer()
.append("Results for " + sr.getName() + " \n")
.append("\n")
.append(" \n")
.append(" \n")
.append(" \n")
.append("\n")
;
Utils.writeFile(getOutputDirectory(xmlSuite), "index.html", index.toString());
}
private String makeTitle(ISuite suite) {
return "Results for" + suite.getName() + " ";
}
private void generateMain(XmlSuite xmlSuite, ISuite sr) {
StringBuffer index = new StringBuffer()
.append("Results for " + sr.getName() + " \n")
.append("Select a result on the left-hand pane.")
.append("\n")
;
Utils.writeFile(getOutputDirectory(xmlSuite), "main.html", index.toString());
}
/**
*
*/
private void generateTableOfContents(XmlSuite xmlSuite, ISuite suite) {
StringBuffer tableOfContents = new StringBuffer();
//
// Generate methods and groups hyperlinks
//
Map suiteResults = suite.getResults();
int groupCount = suite.getMethodsByGroups().size();
int methodCount = 0;
synchronized(suiteResults) {
for (ISuiteResult sr : suiteResults.values()) {
ITestNGMethod[] methods = sr.getTestContext().getAllTestMethods();
methodCount += Utils.calculateInvokedMethodCount(methods);
// Collect testClasses
for (ITestNGMethod tm : methods) {
ITestClass tc = tm.getTestClass();
m_classes.put(tc.getRealClass().getName(), tc);
}
}
}
String name = "Results for " + suite.getName();
tableOfContents
.append("\n")
.append("\n")
.append("" + name + " \n")
.append(HtmlHelper.getCssString())
.append("\n")
;
tableOfContents
.append("\n")
.append("" + makeTitle(suite) + "
\n")
.append("");
//
// Generate results for individual tests
//
// Order the results so we can show the failures first, then the skip and
// finally the successes
Map redResults = Maps.newHashMap();
Map yellowResults = Maps.newHashMap();
Map greenResults = Maps.newHashMap();
synchronized(suiteResults) {
for (Map.Entry entry : suiteResults.entrySet()) {
String suiteName = entry.getKey();
ISuiteResult sr = entry.getValue();
ITestContext tc = sr.getTestContext();
int failed = tc.getFailedTests().size();
int skipped = tc.getSkippedTests().size();
int passed = tc.getPassedTests().size();
if (failed > 0) {
redResults.put(suiteName, sr);
}
else if (skipped > 0) {
yellowResults.put(suiteName, sr);
}
else if (passed > 0) {
greenResults.put(suiteName, sr);
}
else {
redResults.put(suiteName, sr);
}
}
}
ISuiteResult[][] results = new ISuiteResult[][] {
sortResults(redResults.values()), sortResults(yellowResults.values()), sortResults(greenResults.values())
};
String[] colors = {"failed", "skipped", "passed"};
for (int i = 0; i < colors.length; i++) {
ISuiteResult[] r = results[i];
for (ISuiteResult sr: r) {
String suiteName = sr.getTestContext().getName();
generateSuiteResult(suiteName, sr, colors[i], tableOfContents, m_outputDirectory);
}
}
tableOfContents.append("");
Utils.writeFile(getOutputDirectory(xmlSuite), "toc.html", tableOfContents.toString());
}
private String pluralize(int count, String singular) {
return count > 1 ? (singular.endsWith("s") ? singular + "es" : singular + "s") : singular;
}
private String getOutputDirectory(XmlSuite xmlSuite) {
File fileResult = new File(m_outputDirectory + File.separatorChar + xmlSuite.getName()).getAbsoluteFile();
if (! fileResult.exists()) {
fileResult.mkdirs();
if (! fileResult.exists()) {
Utils.log("Reports", 2, "Problem creating output directory " + fileResult.getAbsolutePath());
}
}
return fileResult.getAbsolutePath();
}
private ISuiteResult[] sortResults(Collection r) {
ISuiteResult[] result = r.toArray(new ISuiteResult[r.size()]);
Arrays.sort(result);
return result;
}
private void generateSuiteResult(String suiteName,
ISuiteResult sr,
String cssClass,
StringBuffer tableOfContents,
String outputDirectory)
{
ITestContext tc = sr.getTestContext();
int passed = tc.getPassedTests().size();
int failed = tc.getFailedTests().size();
int skipped = tc.getSkippedTests().size();
String baseFile = tc.getName();
tableOfContents
.append("\n\n")
.append("\n")
.append("")
.append("")
.append(suiteName).append(" (").append(passed).append("/").append(failed).append("/").append(skipped).append(")")
.append(" ")
.append("\n")
.append(" Results \n")
// .append(" Output \n")
// .append(" Property file \n")
.append(" ")
.append("
\n")
.append("
\n")
;
tableOfContents.append("
\n");
}
/**
* Writes a property file for each suite result.
*
* @param xmlSuite
* @param suite
*/
private void generateSuites(XmlSuite xmlSuite, ISuite suite) {
Map suiteResults = suite.getResults();
for (ISuiteResult sr : suiteResults.values()) {
ITestContext testContext = sr.getTestContext();
StringBuffer sb = new StringBuffer();
for (ISuiteResult suiteResult : suiteResults.values()) {
sb.append(suiteResult.toString());
}
Utils.writeFile(getOutputDirectory(xmlSuite), testContext.getName() + ".properties", sb.toString());
}
}
}