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

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

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

import org.testng.IInvokedMethod;
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.ITestResult;
import org.testng.Reporter;
import org.testng.collections.Lists;
import org.testng.internal.Utils;
import org.testng.log4testng.Logger;
import org.testng.xml.XmlSuite;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.Files.newBufferedWriter;

/**
 * Reported designed to render self-contained HTML top down view of a testing
 * suite.
 *
 * @since 5.2
 */
public class EmailableReporter implements IReporter {
  private static final Logger L = Logger.getLogger(EmailableReporter.class);

  // ~ Instance fields ------------------------------------------------------

  private PrintWriter m_out;

  private int m_row;

  private Integer m_testIndex;

  private int m_methodIndex;

  private String fileName = "emailable-report.html";

  private static final String JVM_ARG = "emailable.report.name";

  public String getFileName() {
    return fileName;
  }

  public void setFileName(String fileName) {
    this.fileName = fileName;
  }

  // ~ Methods --------------------------------------------------------------

  /** Creates summary of the run */
  @Override
  public void generateReport(List xml, List suites, String outdir) {
    try {
      m_out = createWriter(outdir);
    }
    catch (IOException e) {
      L.error("output file", e);
      return;
    }
    startHtml(m_out);
    generateSuiteSummaryReport(suites);
    generateMethodSummaryReport(suites);
    generateMethodDetailReport(suites);
    endHtml(m_out);
    m_out.flush();
    m_out.close();
  }

  protected PrintWriter createWriter(String outdir) throws IOException {
    new File(outdir).mkdirs();
    String jvmArg = System.getProperty(JVM_ARG);
    if (jvmArg != null && !jvmArg.trim().isEmpty()) {
      fileName = jvmArg;
    }
    return new PrintWriter(newBufferedWriter(new File(outdir, fileName).toPath(), UTF_8));
  }

  /** Creates a table showing the highlights of each test method with links to the method details */
  protected void generateMethodSummaryReport(List suites) {
    m_methodIndex = 0;
    startResultSummaryTable();
    int testIndex = 1;
    for (ISuite suite : suites) {
      if(suites.size()>1) {
        titleRow(suite.getName(), 5);
      }
      Map r = suite.getResults();
      for (ISuiteResult r2 : r.values()) {
        ITestContext testContext = r2.getTestContext();
        String testName = testContext.getName();
        m_testIndex = testIndex;
        resultSummary(suite, testContext.getFailedConfigurations(), testName,
            "failed", " (configuration methods)");
        resultSummary(suite, testContext.getFailedTests(), testName, "failed",
            "");
        resultSummary(suite, testContext.getSkippedConfigurations(), testName,
            "skipped", " (configuration methods)");
        resultSummary(suite, testContext.getSkippedTests(), testName,
            "skipped", "");
        resultSummary(suite, testContext.getPassedTests(), testName, "passed",
            "");
        testIndex++;
      }
    }
    m_out.println("");
  }

  /** Creates a section showing known results for each method */
  protected void generateMethodDetailReport(List suites) {
    m_methodIndex = 0;
    for (ISuite suite : suites) {
      Map r = suite.getResults();
      for (ISuiteResult r2 : r.values()) {
        ITestContext testContext = r2.getTestContext();
        if (r.values().size() > 0) {
          m_out.println("

" + testContext.getName() + "

"); } resultDetail(testContext.getFailedConfigurations()); resultDetail(testContext.getFailedTests()); resultDetail(testContext.getSkippedConfigurations()); resultDetail(testContext.getSkippedTests()); resultDetail(testContext.getPassedTests()); } } } /** * @param tests */ private void resultSummary(ISuite suite, IResultMap tests, String testname, String style, String details) { if (!tests.getAllResults().isEmpty()) { StringBuilder buff = new StringBuilder(); String lastClassName = ""; int mq = 0; int cq = 0; for (ITestNGMethod method : getMethodSet(tests, suite)) { m_row += 1; m_methodIndex += 1; ITestClass testClass = method.getTestClass(); String className = testClass.getName(); if (mq == 0) { String id = (m_testIndex == null ? null : "t" + Integer.toString(m_testIndex)); titleRow(testname + " — " + style + details, 5, id); m_testIndex = null; } if (!className.equalsIgnoreCase(lastClassName)) { if (mq > 0) { cq += 1; m_out.print("" + " 1) { m_out.print(" rowspan=\"" + mq + "\""); } m_out.println(">" + lastClassName + "" + buff); } mq = 0; buff.setLength(0); lastClassName = className; } Set resultSet = tests.getResults(method); long end = Long.MIN_VALUE; long start = Long.MAX_VALUE; for (ITestResult testResult : tests.getResults(method)) { if (testResult.getEndMillis() > end) { end = testResult.getEndMillis(); } if (testResult.getStartMillis() < start) { start = testResult.getStartMillis(); } } mq += 1; if (mq > 1) { buff.append(""); } String description = method.getDescription(); String testInstanceName = resultSet.toArray(new ITestResult[]{})[0].getTestName(); buff.append("") .append(qualifiedName(method)) .append(" "); if (description != null && !description.isEmpty()) { buff.append("(\"").append(description).append("\")"); } buff.append(""); if (testInstanceName != null) { buff.append("
(").append(testInstanceName).append(")"); } buff.append("") .append("").append(resultSet.size()).append("") .append("").append(start).append("") .append("").append(end - start).append("") .append(""); } if (mq > 0) { cq++; m_out.print("" + " 1) { m_out.print(" rowspan=\"" + mq + "\""); } m_out.println(">" + lastClassName + "" + buff); } } } /** Starts and defines columns result summary table */ private void startResultSummaryTable() { tableStart("methodOverview", "summary"); m_out.println("Class" + "Method# of
ScenariosStartTime
(ms)"); m_row = 0; } private String qualifiedName(ITestNGMethod method) { StringBuilder addon = new StringBuilder(); String[] groups = method.getGroups(); int length = groups.length; if (length > 0 && !"basic".equalsIgnoreCase(groups[0])) { addon.append("("); for (int i = 0; i < length; i++) { if (i > 0) { addon.append(", "); } addon.append(groups[i]); } addon.append(")"); } return "" + method.getMethodName() + " " + addon; } private void resultDetail(IResultMap tests) { for (ITestResult result : tests.getAllResults()) { ITestNGMethod method = result.getMethod(); m_methodIndex++; String cname = method.getTestClass().getName(); m_out.println("

" + cname + ":" + method.getMethodName() + "

"); generateForResult(result, method); m_out.println("

back to summary

"); } } private void generateForResult(ITestResult ans, ITestNGMethod method) { Object[] parameters = ans.getParameters(); boolean hasParameters = parameters != null && parameters.length > 0; if (hasParameters) { tableStart("result", null); m_out.print(""); for (int x = 1; x <= parameters.length; x++) { m_out.print("Parameter #" + x + ""); } m_out.println(""); m_out.print(""); for (Object p : parameters) { m_out.println("" + Utils.escapeHtml(Utils.toString(p)) + ""); } m_out.println(""); } List msgs = Reporter.getOutput(ans); boolean hasReporterOutput = !msgs.isEmpty(); Throwable exception=ans.getThrowable(); boolean hasThrowable = exception!=null; if (hasReporterOutput||hasThrowable) { if (hasParameters) { m_out.print(" 1) { m_out.print(" colspan=\"" + parameters.length + "\""); } m_out.println(">"); } else { m_out.println("
"); } if (hasReporterOutput) { if(hasThrowable) { m_out.println("

Test Messages

"); } for (String line : msgs) { m_out.println(line + "
"); } } if(hasThrowable) { boolean wantsMinimalOutput = ans.getStatus()==ITestResult.SUCCESS; if(hasReporterOutput) { m_out.println("

" +(wantsMinimalOutput?"Expected Exception":"Failure") +"

"); } generateExceptionReport(exception,method); } if (hasParameters) { m_out.println(""); } else { m_out.println("
"); } } if (hasParameters) { m_out.println(""); } } protected void generateExceptionReport(Throwable exception, ITestNGMethod method) { m_out.print("
"); m_out.print(Utils.shortStackTrace(exception, true)); m_out.println("
"); } /** * Since the methods will be sorted chronologically, we want to return * the ITestNGMethod from the invoked methods. */ private Collection getMethodSet(IResultMap tests, ISuite suite) { List r = Lists.newArrayList(); List invokedMethods = suite.getAllInvokedMethods(); for (IInvokedMethod im : invokedMethods) { if (tests.getAllMethods().contains(im.getTestMethod())) { r.add(im); } } Arrays.sort(r.toArray(new IInvokedMethod[r.size()]), new TestSorter()); List result = Lists.newArrayList(); // Add all the invoked methods for (IInvokedMethod m : r) { result.add(m.getTestMethod()); } // Add all the methods that weren't invoked (e.g. skipped) that we // haven't added yet for (ITestNGMethod m : tests.getAllMethods()) { if (!result.contains(m)) { result.add(m); } } return result; } public void generateSuiteSummaryReport(List suites) { tableStart("testOverview", null); m_out.print(""); tableColumnStart("Test"); tableColumnStart("Methods
Passed"); tableColumnStart("Scenarios
Passed"); tableColumnStart("# skipped"); tableColumnStart("# failed"); tableColumnStart("Total
Time"); tableColumnStart("Included
Groups"); tableColumnStart("Excluded
Groups"); m_out.println(""); NumberFormat formatter = new DecimalFormat("#,##0.0"); int qty_tests = 0; int qty_pass_m = 0; int qty_pass_s = 0; int qty_skip = 0; int qty_fail = 0; long time_start = Long.MAX_VALUE; long time_end = Long.MIN_VALUE; m_testIndex = 1; for (ISuite suite : suites) { if (suites.size() > 1) { titleRow(suite.getName(), 8); } Map tests = suite.getResults(); for (ISuiteResult r : tests.values()) { qty_tests += 1; ITestContext overview = r.getTestContext(); startSummaryRow(overview.getName()); int q = getMethodSet(overview.getPassedTests(), suite).size(); qty_pass_m += q; summaryCell(q,Integer.MAX_VALUE); q = overview.getPassedTests().size(); qty_pass_s += q; summaryCell(q,Integer.MAX_VALUE); q = getMethodSet(overview.getSkippedTests(), suite).size(); qty_skip += q; summaryCell(q,0); q = getMethodSet(overview.getFailedTests(), suite).size(); qty_fail += q; summaryCell(q,0); time_start = Math.min(overview.getStartDate().getTime(), time_start); time_end = Math.max(overview.getEndDate().getTime(), time_end); summaryCell(formatter.format( (overview.getEndDate().getTime() - overview.getStartDate().getTime()) / 1000.) + " seconds", true); summaryCell(overview.getIncludedGroups()); summaryCell(overview.getExcludedGroups()); m_out.println(""); m_testIndex++; } } if (qty_tests > 1) { m_out.println("Total"); summaryCell(qty_pass_m,Integer.MAX_VALUE); summaryCell(qty_pass_s,Integer.MAX_VALUE); summaryCell(qty_skip,0); summaryCell(qty_fail,0); summaryCell(formatter.format((time_end - time_start) / 1000.) + " seconds", true); m_out.println(" "); } m_out.println(""); } private void summaryCell(String[] val) { StringBuilder b = new StringBuilder(); for (String v : val) { b.append(v).append(" "); } summaryCell(b.toString(),true); } private void summaryCell(String v, boolean isGood) { m_out.print("" + v + ""); } private void startSummaryRow(String label) { m_row++; m_out.print("" + label + "" + ""); } private void summaryCell(int v, int maxexpected) { summaryCell(String.valueOf(v), v<=maxexpected); } private void tableStart(String cssclass, String id) { m_out.println(""); m_row = 0; } private void tableColumnStart(String label) { m_out.print(""); } private void titleRow(String label, int cq) { titleRow(label, cq, null); } private void titleRow(String label, int cq, String id) { m_out.print(""); m_row = 0; } /** Starts HTML stream */ protected void startHtml(PrintWriter out) { out.println(""); out.println(""); out.println(""); out.println(""); out.println("TestNG Report"); out.println(""); out.println(""); out.println(""); } /** Finishes HTML stream */ protected void endHtml(PrintWriter out) { out.println(""); } // ~ Inner Classes -------------------------------------------------------- /** Arranges methods by classname and method name */ private static final class TestSorter implements Comparator { // ~ Methods ------------------------------------------------------------- /** Arranges methods by classname and method name */ @Override public int compare(IInvokedMethod o1, IInvokedMethod o2) { return (int) (o1.getDate() - o2.getDate()); } } }









" + label + "" + label + "