All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.testng.reporters.SuiteHTMLReporter Maven / Gradle / Ivy

There is a newer version: 7.10.2
Show newest version
package org.testng.reporters;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.testng.IReporter;
import org.testng.IResultMap;
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.SuiteResult;
import org.testng.internal.Utils;
import org.testng.xml.XmlSuite;

/**
 * This class implements an HTML reporter for suites.
 * 
 * @author cbeust
 */
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 = new HashMap();
  private String m_outputDirectory;
  
  public void generateReport(List xmlSuites, List suites, String outputDirectory) {
    m_outputDirectory = outputDirectory;
    
    try {
      HtmlHelper.generateStylesheet(outputDirectory);
    } catch (IOException e) {
      //  TODO Propagate the exception properly.
      e.printStackTrace();
    }
    
    for (int i = 0; i < xmlSuites.size(); i++) {
      
      //
      // Generate the various reports
      //
      XmlSuite xmlSuite = xmlSuites.get(i);
      ISuite suite = suites.get(i);
      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);
  }
  
  private void generateXmlFile(XmlSuite xmlSuite, ISuite suite) {
    String content = 
      new String(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); } /** * 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("\n"); int failedTests = 0; int passedTests = 0; int skippedTests = 0; for (ISuite suite : suites) { String name = suite.getName(); Map results = suite.getResults(); for (String suiteName : results.keySet()) { ISuiteResult result = results.get(suiteName); ITestContext context = result.getTestContext(); failedTests += context.getFailedTests().size(); passedTests += context.getPassedTests().size(); skippedTests += context.getSkippedTests().size(); } String cls = failedTests > 0 ? "invocation-failed" : "invocation-passed"; sb.append("") .append("\n"); sb.append("") .append("") .append(""); } sb.append("
SuitePassedFailedSkippedtestng.xml
") .append(name).append("" + passedTests + "" + failedTests + "" + skippedTests + "Link").append("
") .append("\n"); File outputFile = new File(m_outputDirectory + File.separatorChar + "index.html"); Utils.writeFile(outputFile, sb.toString()); } private void generateExcludedMethodsReport(XmlSuite xmlSuite, ISuite suite) { Collection excluded = suite.getExcludedMethods(); StringBuffer sb2 = new StringBuffer("

Disabled methods

\n"); for (ITestNGMethod method : excluded) { Method m = method.getMethod(); if (m != null) { sb2.append("\n"); } } sb2.append("
") .append(m.getDeclaringClass().getName() + "." + m.getName()) .append("
"); Utils.writeFile(getOutputDirectory(xmlSuite), METHODS_NOT_RUN, sb2); } private void generateReporterOutput(XmlSuite xmlSuite, ISuite suite) { StringBuffer sb = new StringBuffer(); List methodsNotRun = new ArrayList(); // // Reporter output // sb.append("

Reporter output

") .append(""); List output = Reporter.getOutput(); for (String line : output) { sb.append("\n"); } sb.append("
").append(line).append("
"); Utils.writeFile(getOutputDirectory(xmlSuite), REPORTER_OUTPUT, sb); } // Map results = suite.getResults(); // for (String testName : results.keySet()) { // ISuiteResult sr = results.get(testName); // ITestContext testContext = sr.getTestContext(); // Map[] all = new Map[] { // testContext.getPassedTests(), // testContext.getFailedTests(), // testContext.getSkippedTests(), // testContext.getFailedButWithinSuccessPercentageTests() // }; // // // // // Iterate through all the methods // for (Map resultSet : all) { // for (ITestNGMethod m : resultSet.keySet()) { // // NOTE(cbeust) // // Should use a map instead of a list for contains() // if (invokedMethods.contains(m)) { // sb.append("\n"); // ITestResult tr = resultSet.get(m); // List output = tr.getExtraOutput().getOutput(); // for (String line : output) { // sb.append("[").append(m.getMethodName()).append("]\n") // .append("").append(line).append("\n"); // } // } // else { // methodsNotRun.add(m); // } // } // } // } // for testName: result // } private void generateClasses(XmlSuite xmlSuite, ISuite suite) { StringBuffer sb = new StringBuffer(); sb.append("

Test classes

"); for (ITestClass tc : m_classes.values()) { sb.append(generateClass(tc)); } Utils.writeFile(getOutputDirectory(xmlSuite), CLASSES, sb); } 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("
") .append("

").append(cls.getRealClass().getName()).append("

"); sb.append(SP3).append("Test methods

\n") .append(dumpMethods(cls.getTestMethods())) .append(SP3).append("beforeClass methods

\n") .append(dumpMethods(cls.getBeforeClassMethods())) .append(SP3).append("beforeTest methods

\n") .append(dumpMethods(cls.getBeforeTestMethods())) .append(SP3).append("afterTest methods

\n") .append(dumpMethods(cls.getAfterTestMethods())) .append(SP3).append("afterClass methods

\n") .append(dumpMethods(cls.getAfterClassMethods())) ; String result = sb.toString(); return result; } private String dumpMethods(ITestNGMethod[] testMethods) { StringBuffer sb = new StringBuffer(); //"

"); for (ITestNGMethod tm : testMethods) { sb // .append("") ; } sb.append("
") .append(dumpGroups(tm.getGroups())) .append(SP4).append(tm.getMethodName()).append("()

\n") // .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) { StringBuffer sb = new StringBuffer(); sb.append("

Methods run, sorted chronologically

"); sb.append("

" + BEFORE + " means before, " + AFTER + " means after

"); long startDate = -1; Map tables = new HashMap(); sb.append("
").append(suite.getName()).append("

"); Collection invokedMethods = suite.getInvokedMethods(); if (alphabetical) { Comparator alphabeticalComparator = new Comparator(){ public int compare(Object o1, Object o2) { ITestNGMethod m1 = (ITestNGMethod) o1; ITestNGMethod m2 = (ITestNGMethod) o2; return m1.getMethodName().compareTo(m2.getMethodName()); } }; Collections.sort((List) invokedMethods, alphabeticalComparator); } for (ITestNGMethod tm : invokedMethods) { Long id = new Long(0); StringBuffer table = tables.get(id); if (null == table) { table = new StringBuffer(); tables.put(id, table); table.append("

\n") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("\n"); } 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 = tm.getDate(); SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); String date = format.format(tm.getDate()); table.append("") .append(" ") .append(" ") .append(td(configurationSuiteMethod)) .append(td(configurationTestMethod)) .append(td(configurationClassMethod)) .append(td(configurationGroupsMethod)) .append(td(setUpOrTearDownMethod)) .append(td(testMethod)) .append(" ") .append(" ") .append("\n") ; } /// Close all the tables for (StringBuffer table : tables.values()) { table.append("
TimeDelta (ms)Suite
configuration
Test
configuration
Class
configuration
Groups
configuration
Method
configuration
Test
method
ThreadInstances
").append(date).append("").append(tm.getDate() - startDate).append("").append(tm.getId()).append("").append(instances).append("
\n"); sb.append(table.toString()); } Utils.writeFile(getOutputDirectory(xmlSuite), outputFileName, sb); } private static String toHex(int n) { return Integer.toHexString(0x10 | n).substring(1).toUpperCase(); } /** * 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("") .append(""); String[] groupNames = groups.keySet().toArray(new String[groups.size()]); Arrays.sort(groupNames); for (String group : groupNames) { Collection methods = groups.get(group); sb.append(""); StringBuffer methodNames = new StringBuffer(); Map uniqueMethods = new HashMap(); for (ITestNGMethod tm : methods) { uniqueMethods.put(tm, tm); } for (ITestNGMethod tm : uniqueMethods.values()) { methodNames.append(tm.toString()).append("
"); } sb.append("
\n"); } sb.append("
Group nameMethods
").append(group).append("" + methodNames.toString() + "
\n"); } Utils.writeFile(getOutputDirectory(xmlSuite), GROUPS, sb); } private void generateIndex(XmlSuite xmlSuite, ISuite sr) { StringBuffer titles = new StringBuffer(); titles.append(makeTitle(sr)); StringBuffer index = new StringBuffer() .append("" + titles + "\n") .append("\n") .append("\n") .append("\n") .append("\n") .append("\n") ; Utils.writeFile(getOutputDirectory(xmlSuite), "index.html", index); } private String makeTitle(ISuite suite) { return "Results for
" + suite.getName() + ""; } private void generateMain(XmlSuite xmlSuite, ISuite sr) { StringBuffer titles = new StringBuffer(); titles.append(makeTitle(sr)); StringBuffer index = new StringBuffer() .append("" + titles + "\n") .append("Select a result on the left-hand pane.") .append("\n") ; Utils.writeFile(getOutputDirectory(xmlSuite), "main.html", index); } /** * */ 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; 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 = makeTitle(suite); tableOfContents .append("\n") .append("\n") .append("" + name + "\n") .append(HtmlHelper.getCssString()) .append("\n") .append("\n") .append("

" + name + "

\n") .append("\n") .append("\n") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append("") .append(" redResults = new HashMap(); Map yellowResults = new HashMap(); Map greenResults = new HashMap(); for (String suiteName : suiteResults.keySet()) { ISuiteResult sr = suiteResults.get(suiteName); ITestContext tc = sr.getTestContext(); int failed = tc.getFailedTests().size(); int skipped = tc.getSkippedTests().size(); if (failed > 0) redResults.put(suiteName, sr); else if (skipped > 0) yellowResults.put(suiteName, sr); else greenResults.put(suiteName, sr); } String[] colors = { "failed", "skipped", "passed" }; ISuiteResult[][] results = new ISuiteResult[][] { sortResults(redResults.values()), sortResults(yellowResults.values()), sortResults(greenResults.values()) }; 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); } private String pluralize(int count, String singular) { return count > 1 ? singular + "s" : singular; } private String getOutputDirectory(XmlSuite xmlSuite) { return m_outputDirectory + File.separatorChar + xmlSuite.getName(); } 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("
").append(suiteResults.size() + " " + pluralize(suiteResults.size(), "test")) .append("\n") .append("" + m_classes.size() + " " + pluralize(m_classes.size(), "class") + "" + methodCount + " " + pluralize(methodCount, "method") + ":
") .append("  chronological
") .append("  alphabetical
") .append("  not run
" + groupCount + pluralize(groupCount, " group") + "reporter outputtestng.xml
\n") .append("

") ; tableOfContents.append("

") .append("") .append("") .append("") .append("
") .append(suiteName).append(" (").append(passed).append("/").append(failed).append("/").append(skipped).append(")") .append("\n") .append(" Results\n") // .append(" Output\n") // .append("  Property file
\n") .append("
") .append("
\n"); } private void generateSuites(XmlSuite xmlSuite, ISuite suite) { Map suiteResults = suite.getResults(); for (String propertyFileName : suiteResults.keySet()) { SuiteResult sr = (SuiteResult) suiteResults.get(propertyFileName); ITestContext testContext = sr.getTestContext(); StringBuffer sb = new StringBuffer(); for (String name : suiteResults.keySet()) { ISuiteResult suiteResult = suiteResults.get(name); sb.append(suiteResult.toString()); } Utils.writeFile(getOutputDirectory(xmlSuite), testContext.getName() + ".properties", sb); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy