SuiteHTMLReporter.java revision 31f6566ce35497e9324201e8a3f6f79265df2e79
1336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustpackage org.testng.reporters;
2336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
30f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.IReporter;
40f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.ISuite;
50f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.ISuiteResult;
60f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.ITestClass;
70f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.ITestContext;
80f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.ITestNGMethod;
90f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.Reporter;
10ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beustimport org.testng.collections.Lists;
110f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.collections.Maps;
120f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.internal.Utils;
130f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.xml.XmlSuite;
140f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust
15336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.io.File;
16336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.io.IOException;
17336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.lang.reflect.Method;
18336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.text.SimpleDateFormat;
19336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.util.Arrays;
20336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.util.Collection;
21336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.util.Collections;
22336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.util.Comparator;
23336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.util.List;
24336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustimport java.util.Map;
25336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
26336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust/**
27336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust * This class implements an HTML reporter for suites.
28336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust *
29336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust * @author cbeust
309a1482542f224166248c1821ddeb70c7dbc5415athe.mindstorm * @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
31336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust */
32336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beustpublic class SuiteHTMLReporter implements IReporter {
33336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String METHODS_CHRONOLOGICAL = "methods.html";
34336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String METHODS_ALPHABETICAL = "methods-alphabetical.html";
35336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String GROUPS = "groups.html";
36336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String CLASSES = "classes.html";
37336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String REPORTER_OUTPUT = "reporter-output.html";
38336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String METHODS_NOT_RUN = "methods-not-run.html";
39336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String TESTNG_XML = "testng.xml.html";
40336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
410f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust  private Map<String, ITestClass> m_classes = Maps.newHashMap();
42336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String m_outputDirectory;
43336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
44336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) {
45336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    m_outputDirectory = outputDirectory;
46336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
47336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    try {
48336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      HtmlHelper.generateStylesheet(outputDirectory);
49336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    } catch (IOException e) {
50336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //  TODO Propagate the exception properly.
51336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      e.printStackTrace();
52336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
53336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
5431f6566ce35497e9324201e8a3f6f79265df2e79Cédric Beust    for (int i = 0; i < suites.size(); i++) {
55336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
56336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //
57336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // Generate the various reports
58336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //
59336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      ISuite suite = suites.get(i);
6031f6566ce35497e9324201e8a3f6f79265df2e79Cédric Beust      XmlSuite xmlSuite = suite.getXmlSuite();
6131f6566ce35497e9324201e8a3f6f79265df2e79Cédric Beust      if (xmlSuite.getTests().size() == 0) continue;
62336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateTableOfContents(xmlSuite, suite);
63336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateSuites(xmlSuite, suite);
64336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateIndex(xmlSuite, suite);
65336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateMain(xmlSuite, suite);
66336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateMethodsAndGroups(xmlSuite, suite);
67336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateMethodsChronologically(xmlSuite, suite, METHODS_CHRONOLOGICAL, false);
68336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateMethodsChronologically(xmlSuite, suite, METHODS_ALPHABETICAL, true);
69336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateClasses(xmlSuite, suite);
70336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateReporterOutput(xmlSuite, suite);
71336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateExcludedMethodsReport(xmlSuite, suite);
72336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      generateXmlFile(xmlSuite, suite);
73336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
74336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
75336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    generateIndex(suites);
76336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
77336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
78336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateXmlFile(XmlSuite xmlSuite, ISuite suite) {
79336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String content =
80336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      new String(xmlSuite.toXml().replaceAll("<", "&lt;").replaceAll(">", "&gt;"))
81336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .replaceAll(" ", "&nbsp;").replaceAll("\n", "<br/>");
82336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
83336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer sb = new StringBuffer("<html>");
84336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
857ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    sb.append("<head><title>").append("testng.xml for ")
867ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append(xmlSuite.getName()).append("</title></head><body><tt>")
87336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append(content)
88336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("</tt></body></html>");
89336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
90975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm    Utils.writeFile(getOutputDirectory(xmlSuite), TESTNG_XML, sb.toString());
91336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
92336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
93336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  /**
94336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * Generate the main index.html file that lists all the suites
95336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * and their result
96336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   */
97336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateIndex(List<ISuite> suites) {
98336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer sb = new StringBuffer();
99336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String title = "Test results";
100336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    sb.append("<html>\n<head><title>" + title + "</title>")
101336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append(HtmlHelper.getCssString("."))
102336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("</head><body>\n")
103336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("<h2><p align='center'>").append(title).append("</p></h2>\n")
1047ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append("<table border='1' width='100%' class='main-page'>")
105336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("<tr><th>Suite</th><th>Passed</th><th>Failed</th><th>Skipped</th><th>testng.xml</th></tr>\n");
106336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
107124444cdff2e318bce603521a44633524543619athe.mindstorm    int totalFailedTests = 0;
108124444cdff2e318bce603521a44633524543619athe.mindstorm    int totalPassedTests = 0;
109124444cdff2e318bce603521a44633524543619athe.mindstorm    int totalSkippedTests = 0;
110336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
111124444cdff2e318bce603521a44633524543619athe.mindstorm    StringBuffer suiteBuf= new StringBuffer();
112336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (ISuite suite : suites) {
113c8d9bd6d086f47260464a65a9fb9ed6af0d9b15cCédric Beust      if (suite.getResults().size() == 0) continue;
114c8d9bd6d086f47260464a65a9fb9ed6af0d9b15cCédric Beust
115336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String name = suite.getName();
116336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
117124444cdff2e318bce603521a44633524543619athe.mindstorm      int failedTests= 0;
118124444cdff2e318bce603521a44633524543619athe.mindstorm      int passedTests= 0;
119124444cdff2e318bce603521a44633524543619athe.mindstorm      int skippedTests= 0;
120124444cdff2e318bce603521a44633524543619athe.mindstorm
121336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      Map<String, ISuiteResult> results = suite.getResults();
122336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (String suiteName : results.keySet()) {
123336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ISuiteResult result = results.get(suiteName);
124336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ITestContext context = result.getTestContext();
125336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        failedTests += context.getFailedTests().size();
126124444cdff2e318bce603521a44633524543619athe.mindstorm        totalFailedTests += context.getFailedTests().size();
127336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        passedTests += context.getPassedTests().size();
128124444cdff2e318bce603521a44633524543619athe.mindstorm        totalPassedTests += context.getPassedTests().size();
129336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        skippedTests += context.getSkippedTests().size();
130124444cdff2e318bce603521a44633524543619athe.mindstorm        totalSkippedTests += context.getSkippedTests().size();
131336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
132336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
1337ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      String cls = failedTests > 0 ? "invocation-failed"
1347ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust          : (passedTests > 0  ? "invocation-passed" : "invocation-failed");
135124444cdff2e318bce603521a44633524543619athe.mindstorm      suiteBuf.append("<tr align='center' class='").append(cls).append("'>")
136336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<td><a href='").append(name).append("/index.html'>")
137336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append(name).append("</a></td>\n");
138124444cdff2e318bce603521a44633524543619athe.mindstorm      suiteBuf.append("<td>" + passedTests + "</td>")
139336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<td>" + failedTests + "</td>")
140336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<td>" + skippedTests + "</td>")
141336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<td><a href='").append(name).append("/").append(TESTNG_XML).append("'>Link").append("</a></td>")
142336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("</tr>");
143336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
144336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
145336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
1467ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    String cls= totalFailedTests > 0 ? "invocation-failed"
1477ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        : (totalPassedTests > 0 ? "invocation-passed" : "invocation-failed");
148124444cdff2e318bce603521a44633524543619athe.mindstorm    sb.append("<tr align='center' class='").append(cls).append("'>")
149e9d9e161c61fe97ca84146830000aae3b694ed56the.mindstorm      .append("<td><em>Total</em></td>")
150e9d9e161c61fe97ca84146830000aae3b694ed56the.mindstorm      .append("<td><em>").append(totalPassedTests).append("</em></td>")
151e9d9e161c61fe97ca84146830000aae3b694ed56the.mindstorm      .append("<td><em>").append(totalFailedTests).append("</em></td>")
152e9d9e161c61fe97ca84146830000aae3b694ed56the.mindstorm      .append("<td><em>").append(totalSkippedTests).append("</em></td>")
153124444cdff2e318bce603521a44633524543619athe.mindstorm      .append("<td>&nbsp;</td>")
154124444cdff2e318bce603521a44633524543619athe.mindstorm      .append("</tr>\n");
155124444cdff2e318bce603521a44633524543619athe.mindstorm    sb.append(suiteBuf);
156124444cdff2e318bce603521a44633524543619athe.mindstorm    sb.append("</table>").append("</body></html>\n");
157336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
1588199621f3dd6adcbc12e93c4ea5508cf9f4f9055the.mindstorm    Utils.writeFile(m_outputDirectory, "index.html", sb.toString());
159336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
160336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
161336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateExcludedMethodsReport(XmlSuite xmlSuite, ISuite suite) {
162336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      Collection<ITestNGMethod> excluded = suite.getExcludedMethods();
16301864456a039f32dd36028e4b26c63c10d03a5aaCédric Beust      StringBuffer sb2 = new StringBuffer("<h2>Methods that were not run</h2><table>\n");
164336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (ITestNGMethod method : excluded) {
165336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        Method m = method.getMethod();
166336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        if (m != null) {
167336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          sb2.append("<tr><td>")
1685a7f440cd13a7b3bc12ef68e7237a519bb4e1a37the.mindstorm          .append(m.getDeclaringClass().getName() + "." + m.getName());
1695a7f440cd13a7b3bc12ef68e7237a519bb4e1a37the.mindstorm          if(null != method.getDescription() && !"".equals(method.getDescription())) {
1705a7f440cd13a7b3bc12ef68e7237a519bb4e1a37the.mindstorm            sb2.append("<br/>").append(SP2).append("<i>").append(method.getDescription()).append("</i>");
1715a7f440cd13a7b3bc12ef68e7237a519bb4e1a37the.mindstorm          }
1725a7f440cd13a7b3bc12ef68e7237a519bb4e1a37the.mindstorm          sb2.append("</td></tr>\n");
173336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        }
174336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
175336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      sb2.append("</table>");
176336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
177975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm      Utils.writeFile(getOutputDirectory(xmlSuite), METHODS_NOT_RUN, sb2.toString());
178336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
179336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
180336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateReporterOutput(XmlSuite xmlSuite, ISuite suite) {
181336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer sb = new StringBuffer();
182ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> methodsNotRun = Lists.newArrayList();
183336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
184336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    //
185336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    // Reporter output
186336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    //
187336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    sb.append("<h2>Reporter output</h2>")
188336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("<table>");
189336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    List<String> output = Reporter.getOutput();
190336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (String line : output) {
191336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      sb.append("<tr><td>").append(line).append("</td></tr>\n");
192336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
193336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
194336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    sb.append("</table>");
195336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
196975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm    Utils.writeFile(getOutputDirectory(xmlSuite), REPORTER_OUTPUT, sb.toString());
197336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
198336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
199336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateClasses(XmlSuite xmlSuite, ISuite suite) {
200336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer sb = new StringBuffer();
2017ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    sb.append("<table border='1'>\n")
2027ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    .append("<tr>\n")
2037ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    .append("<th>Class name</th>\n")
2047ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    .append("<th>Method name</th>\n")
2057ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    .append("<th>Groups</th>\n")
2067ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    .append("</tr>")
2077ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    ;
208336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (ITestClass tc : m_classes.values()) {
209336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      sb.append(generateClass(tc));
210336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
211336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
2127ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    sb.append("</table>\n");
2137ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust
214975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm    Utils.writeFile(getOutputDirectory(xmlSuite), CLASSES, sb.toString());
215336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
216336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
217336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private final static String SP = "&nbsp;";
218336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private final static String SP2 = SP + SP + SP + SP;
219336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private final static String SP3 = SP2 + SP2;
220336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private final static String SP4 = SP3 + SP3;
221336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
222336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String generateClass(ITestClass cls) {
223336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer sb = new StringBuffer();
2247ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust
2257ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    sb.append("<tr>\n")
2267ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append("<td>").append(cls.getRealClass().getName()).append("</td>\n")
2277ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append("<td>&nbsp;</td>")
2287ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append("<td>&nbsp;</td>")
2297ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append("</tr>\n")
2307ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      ;
2317ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust
2327ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    String[] tags = new String[] {
2337ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        "@Test",
2347ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        "@BeforeClass",
2357ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        "@BeforeMethod",
2367ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        "@AfterMethod",
2377ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        "@AfterClass"
2387ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    };
2397ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    ITestNGMethod[][] methods = new ITestNGMethod[][] {
2407ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      cls.getTestMethods(),
2417ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      cls.getBeforeClassMethods(),
2427ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      cls.getBeforeTestMethods(),
2437ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      cls.getAfterTestMethods(),
2447ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      cls.getAfterClassMethods()
2457ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    };
2467ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust
2477ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    for (int i = 0; i < tags.length; i++) {
2487ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      sb.append("<tr>\n")
2497ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append("<td align='center' colspan='3'>").append(tags[i]).append("</td>\n")
2507ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append("</tr>\n")
2517ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      .append(dumpMethods(methods[i]))
2527ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      ;
2537ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    }
2547ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//    sb.append("<hr width='100%'/>")
2557ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//    .append("<h3>").append(cls.getRealClass().getName()).append("</h3>\n");
2567ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//
2577ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//    sb.append("<div>").append(SP3).append("Test methods\n")
2587ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append(dumpMethods(cls.getTestMethods())).append("</div>\n")
2597ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append("<div>").append(SP3).append("@BeforeClass\n")
2607ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append(dumpMethods(cls.getBeforeClassMethods())).append("</div>\n")
2617ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append("<div>").append(SP3).append("@BeforeMethod\n")
2627ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append(dumpMethods(cls.getBeforeTestMethods())).append("</div>\n")
2637ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append("<div>").append(SP3).append("@AfterMethod\n")
2647ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append(dumpMethods(cls.getAfterTestMethods())).append("</div>\n")
2657ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append("<div>").append(SP3).append("@AfterClass\n")
2667ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append(dumpMethods(cls.getAfterClassMethods())).append("</div>\n")
2677ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//     ;
268336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
269336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String result = sb.toString();
270336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result;
271336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
272336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
273336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String dumpMethods(ITestNGMethod[] testMethods) {
2748c794e046efae93dc1053eac4c978a3f2dfa2510gkorland    StringBuffer sb = new StringBuffer();
275336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if(null == testMethods || testMethods.length == 0) {
276336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      return "";
277336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
278336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
2797ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    for (ITestNGMethod m : testMethods) {
2807ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      sb.append("<tr>\n");
2817ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      sb.append("<td>&nbsp;</td>\n")
2827ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        .append("<td>").append(m.getMethodName()).append("</td>\n")
2837ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        ;
2847ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      String[] groups = m.getGroups();
2857ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      if (groups != null && groups.length > 0) {
2867ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        sb.append("<td>");
2877ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        for (String g : groups) {
2887ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust          sb.append(g).append(" ");
2897ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        }
2907ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        sb.append("</td>\n");
2917ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      }
2927ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      else {
2937ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust        sb.append("<td>&nbsp;</td>");
2947ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      }
2957ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust      sb.append("</tr>\n");
2967ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust    }
2977ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust
2987ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//    StringBuffer sb = new StringBuffer("<br/>");  //"<table bgcolor=\"#c0c0c0\"/>");
2997ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//    for (ITestNGMethod tm : testMethods) {
3007ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      sb
3017ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append(SP4).append(tm.getMethodName()).append("()\n")
3027ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append(dumpGroups(tm.getGroups()))
3037ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      .append("<br/>");
3047ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//      ;
3057ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust//    }
3067ae4d3305466d7663609eba37fd5d4bb23ca047fCédric Beust
307336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
308336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String result = sb.toString();
309336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result;
310336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
311336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
312336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String dumpGroups(String[] groups) {
313336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer sb = new StringBuffer();
314336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
315336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (null != groups && groups.length > 0) {
316336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      sb.append(SP4).append("<em>[");
317336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
318336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (String g : groups) {
319336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        sb.append(g).append(" ");
320336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
321336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
322336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      sb.append("]</em><br/>\n");
323336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
324336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
325336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String result = sb.toString();
326336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result;
327336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
328336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
329336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  /**
330336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * Generate information about the methods that were run
331336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   */
332336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String AFTER= "&lt;&lt;";
333336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  public static final String BEFORE = "&gt;&gt;";
334336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateMethodsChronologically(XmlSuite xmlSuite, ISuite suite,
335336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String outputFileName, boolean alphabetical)
336336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  {
337336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer sb = new StringBuffer();
338336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
339336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    sb.append("<h2>Methods run, sorted chronologically</h2>");
340336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    sb.append("<h3>" + BEFORE + " means before, " + AFTER + " means after</h3><p/>");
341336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
342336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    long startDate = -1;
3430f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<Long, StringBuffer> tables = Maps.newHashMap();
344336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    sb.append("<br/><em>").append(suite.getName()).append("</em><p/>");
34501864456a039f32dd36028e4b26c63c10d03a5aaCédric Beust    sb.append("<small><i>(Hover the method name to see the test class name)</i></small><p/>\n");
346336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    Collection<ITestNGMethod> invokedMethods = suite.getInvokedMethods();
347336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
348336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (alphabetical) {
3496227fbd5182d211f7c1333ca253eee54fbf7c3b2the.mindstorm      @SuppressWarnings({"unchecked"})
350336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      Comparator<? super ITestNGMethod>  alphabeticalComparator = new Comparator(){
351336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        public int compare(Object o1, Object o2) {
352336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          ITestNGMethod m1 = (ITestNGMethod) o1;
353336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          ITestNGMethod m2 = (ITestNGMethod) o2;
354336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          return m1.getMethodName().compareTo(m2.getMethodName());
355336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        }
356336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      };
357336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      Collections.sort((List) invokedMethods, alphabeticalComparator);
358336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
359336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
360336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (ITestNGMethod tm : invokedMethods) {
361336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      Long id = new Long(0);
362336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      StringBuffer table = tables.get(id);
363336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      if (null == table) {
364336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        table = new StringBuffer();
365336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        tables.put(id, table);
366336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        table.append("<table border=\"1\">\n")
367336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<tr>")
368336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Time</th>")
369336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Delta (ms)</th>")
370336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Suite<br>configuration</th>")
371336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Test<br>configuration</th>")
372336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Class<br>configuration</th>")
373336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Groups<br>configuration</th>")
374336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Method<br>configuration</th>")
375336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Test<br>method</th>")
376336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Thread</th>")
377336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<th>Instances</th>")
378336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("</tr>\n");
379336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
380336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String methodName = tm.toString();
381336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean bc = tm.isBeforeClassConfiguration();
382336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean ac = tm.isAfterClassConfiguration();
383336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean bt = tm.isBeforeTestConfiguration();
384336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean at = tm.isAfterTestConfiguration();
385336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean bs = tm.isBeforeSuiteConfiguration();
386336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean as = tm.isAfterSuiteConfiguration();
387336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean bg = tm.isBeforeGroupsConfiguration();
388336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean ag = tm.isAfterGroupsConfiguration();
389336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean setUp = tm.isBeforeMethodConfiguration();
390336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean tearDown = tm.isAfterMethodConfiguration();
391336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean isClassConfiguration = bc || ac;
392336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean isGroupsConfiguration = bg || ag;
393336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean isTestConfiguration = bt || at;
394336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean isSuiteConfiguration = bs || as;
395336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      boolean isSetupOrTearDown = setUp || tearDown;
396336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String configurationClassMethod = isClassConfiguration ? (bc ? BEFORE : AFTER) + methodName : SP;
397336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String configurationTestMethod = isTestConfiguration ? (bt ? BEFORE : AFTER) + methodName : SP;
398336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String configurationGroupsMethod = isGroupsConfiguration ? (bg ? BEFORE : AFTER) + methodName : SP;
399336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String configurationSuiteMethod = isSuiteConfiguration ? (bs ? BEFORE : AFTER) + methodName : SP;
400336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String setUpOrTearDownMethod = isSetupOrTearDown ? (setUp ? BEFORE : AFTER) + methodName : SP;
401336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String testMethod = tm.isTest() ? methodName : SP;
402336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
403336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      StringBuffer instances = new StringBuffer();
404336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (long o : tm.getInstanceHashCodes()) {
405336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        instances.append(o).append(" ");
406336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
407336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
408336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      if (startDate == -1) startDate = tm.getDate();
409336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss");
410336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String date = format.format(tm.getDate());
411336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      table.append("<tr bgcolor=\"" + createColor(tm) + "\">")
412336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("  <td>").append(date).append("</td> ")
413336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("  <td>").append(tm.getDate() - startDate).append("</td> ")
414336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append(td(configurationSuiteMethod))
415336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append(td(configurationTestMethod))
416336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append(td(configurationClassMethod))
417336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append(td(configurationGroupsMethod))
418336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append(td(setUpOrTearDownMethod))
419336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append(td(testMethod))
420336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("  <td>").append(tm.getId()).append("</td> ")
421336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("  <td>").append(instances).append("</td> ")
422336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("</tr>\n")
423336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ;
424336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
425336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
426336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    /// Close all the tables
427336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (StringBuffer table : tables.values()) {
428336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      table.append("</table>\n");
429336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      sb.append(table.toString());
430336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
431975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm    Utils.writeFile(getOutputDirectory(xmlSuite), outputFileName, sb.toString());
432336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
433336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
434336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
435336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private static String toHex(int n) {
436336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return Integer.toHexString(0x10 | n).substring(1).toUpperCase();
437336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
438336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
439336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  /**
440336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * Generate a HTML color based on the class of the method
441336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   */
442336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String createColor(ITestNGMethod tm) {
443336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    // real class can be null if this client is remote (not serializable)
444336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    long color = tm.getRealClass() != null ? tm.getRealClass().hashCode() & 0xffffff: 0xffffff;
445336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    long[] rgb = {
446336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ((color & 0xff0000) >> 16) & 0xff,
447336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ((color & 0x00ff00) >> 8) & 0xff,
448336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        color & 0xff
449336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    };
450336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    // Not too dark
451336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (int i = 0; i < rgb.length; i++) {
452336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      if (rgb[i] < 0x60) rgb[i] += 0x60;
453336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
454336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    long adjustedColor = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
455336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String result = Long.toHexString(adjustedColor);
456336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
457336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result;
458336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
459336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
460336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String td(String s) {
461336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer result = new StringBuffer();
462336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String prefix = "";
463336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
464336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (s.startsWith(BEFORE)) {
465336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      prefix = BEFORE;
466336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
467336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    else if (s.startsWith(AFTER)) {
468336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      prefix = AFTER;
469336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
470336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
471336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (! s.equals(SP)) {
472336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.append("<td title=\"").append(s).append("\">");
473336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      int open = s.lastIndexOf("(");
474336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      int start = s.substring(0, open).lastIndexOf(".");
475975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm//      int end = s.lastIndexOf(")");
476336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      if (start >= 0) {
477336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        result.append(prefix + s.substring(start + 1, open));
478336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
479336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      else {
480336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        result.append(prefix + s);
481336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
482336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.append("</td> \n");
483336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
484336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    else {
485336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      result.append("<td>").append(SP).append("</td>");
486336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
487336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
488336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result.toString();
489336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
490336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
491336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void ppp(String s) {
492336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    System.out.println("[SuiteHTMLReporter] " + s);
493336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
494336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
495336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  /**
496336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   * Generate information about methods and groups
497336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   */
498336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateMethodsAndGroups(XmlSuite xmlSuite, ISuite suite) {
499336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer sb = new StringBuffer();
500336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
501336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    Map<String, Collection<ITestNGMethod>> groups = suite.getMethodsByGroups();
502336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
503336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    sb.append("<h2>Groups used for this test run</h2>");
504336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    if (groups.size() > 0) {
505336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      sb.append("<table border=\"1\">\n")
506336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<tr> <td align=\"center\"><b>Group name</b></td>")
507336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<td align=\"center\"><b>Methods</b></td></tr>");
508336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
509336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      String[] groupNames = groups.keySet().toArray(new String[groups.size()]);
510336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      Arrays.sort(groupNames);
511336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (String group : groupNames) {
512336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        Collection<ITestNGMethod> methods = groups.get(group);
513336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        sb.append("<tr><td>").append(group).append("</td>");
514336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        StringBuffer methodNames = new StringBuffer();
5150f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust        Map<ITestNGMethod, ITestNGMethod> uniqueMethods = Maps.newHashMap();
516336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        for (ITestNGMethod tm : methods) {
517336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          uniqueMethods.put(tm, tm);
518336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        }
519336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        for (ITestNGMethod tm : uniqueMethods.values()) {
520336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          methodNames.append(tm.toString()).append("<br/>");
521336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        }
522336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        sb.append("<td>" + methodNames.toString() + "</td></tr>\n");
523336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
524336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
525336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      sb.append("</table>\n");
526336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
527975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm    Utils.writeFile(getOutputDirectory(xmlSuite), GROUPS, sb.toString());
528336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
529336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
530336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateIndex(XmlSuite xmlSuite, ISuite sr) {
531336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer index = new StringBuffer()
532336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("<html><head><title>Results for " + sr.getName() + "</title></head>\n")
533336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("<frameset cols=\"26%,74%\">\n")
534336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("<frame src=\"toc.html\" name=\"navFrame\">\n")
535336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("<frame src=\"main.html\" name=\"mainFrame\">\n")
536336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("</frameset>\n")
537336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("</html>\n")
538336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    ;
539336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
540975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm    Utils.writeFile(getOutputDirectory(xmlSuite), "index.html", index.toString());
541336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
542336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
543336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String makeTitle(ISuite suite) {
544336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return "Results for<br/><em>" + suite.getName() + "</em>";
545336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
546336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
547336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateMain(XmlSuite xmlSuite, ISuite sr) {
548336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer index = new StringBuffer()
549336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("<html><head><title>Results for " + sr.getName() + "</title></head>\n")
550336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("<body>Select a result on the left-hand pane.</body>")
551336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    .append("</html>\n")
552336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    ;
553336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
554975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm    Utils.writeFile(getOutputDirectory(xmlSuite), "main.html", index.toString());
555336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
556336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
557336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  /**
558336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   *
559336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust   */
560336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateTableOfContents(XmlSuite xmlSuite, ISuite suite) {
561336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    StringBuffer tableOfContents = new StringBuffer();
562336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
563336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    //
564336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    // Generate methods and groups hyperlinks
565336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    //
566336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    Map<String, ISuiteResult> suiteResults = suite.getResults();
567336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    int groupCount = suite.getMethodsByGroups().size();
568336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    int methodCount = 0;
569336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (ISuiteResult sr : suiteResults.values()) {
570336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      ITestNGMethod[] methods = sr.getTestContext().getAllTestMethods();
571336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      methodCount += Utils.calculateInvokedMethodCount(methods);
572336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
573336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // Collect testClasses
574336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (ITestNGMethod tm : methods) {
575336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ITestClass tc = tm.getTestClass();
576336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        m_classes.put(tc.getRealClass().getName(), tc);
577336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
578336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
579336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
580336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String name = "Results for " + suite.getName();
581336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    tableOfContents
582336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<html>\n")
583336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<head>\n")
584336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<title>" + name + "</title>\n")
585336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append(HtmlHelper.getCssString())
586336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("</head>\n")
587336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ;
588336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    tableOfContents
589336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<body>\n")
590336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<h3><p align=\"center\">" + makeTitle(suite) + "</p></h3>\n")
591336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<table border='1' width='100%'>\n")
592336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<tr valign='top'>\n")
593336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<td>")
594336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust            .append(suiteResults.size()).append(" ").append(pluralize(suiteResults.size(), "test"))
595336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("</td>\n")
596336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<td>")
597336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              .append("<a target='mainFrame' href='").append(CLASSES).append("'>")
598336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              .append(m_classes.size() + " " + pluralize(m_classes.size(), "class"))
599336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust              .append("</a>")
600336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("</td>\n")
601336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("<td>" + methodCount + " " + pluralize(methodCount, "method") + ":<br/>\n")
602336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust            .append("&nbsp;&nbsp;<a target='mainFrame' href='").append(METHODS_CHRONOLOGICAL).append("'>").append("chronological</a><br/>\n")
603336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust            .append("&nbsp;&nbsp;<a target='mainFrame' href='").append(METHODS_ALPHABETICAL).append("\'>").append("alphabetical</a><br/>\n")
6045a7f440cd13a7b3bc12ef68e7237a519bb4e1a37the.mindstorm            .append("&nbsp;&nbsp;<a target='mainFrame' href='").append(METHODS_NOT_RUN).append("'>not run (" + suite.getExcludedMethods().size() + ")</a>")
605336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          .append("</td>\n")
606336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("</tr>\n")
607336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
608336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<tr>\n")
609336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<td><a target='mainFrame' href='").append(GROUPS).append("'>").append(groupCount + pluralize(groupCount, " group") + "</a></td>\n")
610336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<td><a target='mainFrame' href='").append(REPORTER_OUTPUT).append("'>reporter output</a></td>\n")
611336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("<td><a target='mainFrame' href='").append(TESTNG_XML).append("'>testng.xml</a></td>\n")
612336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("</tr>")
613336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        .append("</table>");
614336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
615336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //
616336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // Generate results for individual tests
617336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      //
618336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
619336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // Order the results so we can show the failures first, then the skip and
620336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      // finally the successes
6210f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<String, ISuiteResult> redResults = Maps.newHashMap();
6220f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<String, ISuiteResult> yellowResults = Maps.newHashMap();
6230f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<String, ISuiteResult> greenResults = Maps.newHashMap();
624336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
625336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (String suiteName : suiteResults.keySet()) {
626336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ISuiteResult sr = suiteResults.get(suiteName);
627336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ITestContext tc = sr.getTestContext();
628336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        int failed = tc.getFailedTests().size();
629336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        int skipped = tc.getSkippedTests().size();
63008ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        int passed = tc.getPassedTests().size();
631336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
63208ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        if (failed > 0) {
63308ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm          redResults.put(suiteName, sr);
63408ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        }
63508ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        else if (skipped > 0) {
63608ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm          yellowResults.put(suiteName, sr);
63708ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        }
63808ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        else if (passed > 0) {
63908ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm          greenResults.put(suiteName, sr);
64008ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        }
64108ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        else {
64208ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm          redResults.put(suiteName, sr);
64308ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm        }
644336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
645336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
64608ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm
647336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      ISuiteResult[][] results = new ISuiteResult[][] {
648336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        sortResults(redResults.values()), sortResults(yellowResults.values()), sortResults(greenResults.values())
649336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      };
65008ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm
65108ebf81679fb5175f8090732f52ade4f9a099f1ethe.mindstorm      String[] colors = {"failed", "skipped", "passed"};
652336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (int i = 0; i < colors.length; i++) {
653336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ISuiteResult[] r = results[i];
654336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        for (ISuiteResult sr: r) {
655336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          String suiteName = sr.getTestContext().getName();
656336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust          generateSuiteResult(suiteName, sr, colors[i], tableOfContents, m_outputDirectory);
657336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        }
658336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
659336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
660336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    tableOfContents.append("</body></html>");
661975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm    Utils.writeFile(getOutputDirectory(xmlSuite), "toc.html", tableOfContents.toString());
662336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
663336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
664336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String pluralize(int count, String singular) {
665336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return count > 1 ? (singular.endsWith("s") ? singular + "es" : singular + "s") : singular;
666336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
667336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
668336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private String getOutputDirectory(XmlSuite xmlSuite) {
669336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return m_outputDirectory + File.separatorChar + xmlSuite.getName();
670336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
671336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
672336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private ISuiteResult[] sortResults(Collection<ISuiteResult> r) {
673336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    ISuiteResult[] result = r.toArray(new ISuiteResult[r.size()]);
674336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    Arrays.sort(result);
675336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    return result;
676336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
677336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
678336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateSuiteResult(String suiteName,
679336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust                                   ISuiteResult sr,
680336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust                                   String cssClass,
681336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust                                   StringBuffer tableOfContents,
682336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust                                   String outputDirectory)
683336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  {
684336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    ITestContext tc = sr.getTestContext();
685336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    int passed = tc.getPassedTests().size();
686336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    int failed = tc.getFailedTests().size();
687336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    int skipped = tc.getSkippedTests().size();
688336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    String baseFile = tc.getName();
689336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    tableOfContents
690336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("\n<table width='100%' class='test-").append(cssClass).append("'>\n")
691336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("<tr><td>\n")
692336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("<table style='width: 100%'><tr>")
693336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("<td valign='top'>")
694336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append(suiteName).append(" (").append(passed).append("/").append(failed).append("/").append(skipped).append(")")
695336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("</td>")
696336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("<td valign='top' align='right'>\n")
697336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("  <a href='" + baseFile + ".html' target='mainFrame'>Results</a>\n")
698336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust//      .append("  <a href=\"" + baseFile + ".out\" target=\"mainFrame\"\">Output</a>\n")
699336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust//      .append("&nbsp;&nbsp;<a href=\"file://" + baseFile + ".properties\" target=\"mainFrame\"\">Property file</a><br>\n")
700336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("</td>")
701336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("</tr></table>\n")
702336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      .append("</td></tr><p/>\n")
703336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      ;
704336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
705336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    tableOfContents.append("</table>\n");
706336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
707336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
708f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel  /**
709f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel   * Writes a property file for each suite result.
710f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel   *
711f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel   * @param xmlSuite
712f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel   * @param suite
713f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel   */
714336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  private void generateSuites(XmlSuite xmlSuite, ISuite suite) {
715336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    Map<String, ISuiteResult> suiteResults = suite.getResults();
716336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
717f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel    // TODO CQ why not iterate over entry set if were going to use the key to get the value?
718336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    for (String propertyFileName : suiteResults.keySet()) {
719f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel
720fad421d6d4ca1a438daf74a25dff620db815541cthe.mindstorm      ISuiteResult sr = suiteResults.get(propertyFileName);
721336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      ITestContext testContext = sr.getTestContext();
722336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust
723336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      StringBuffer sb = new StringBuffer();
724f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel
725f0a15dd5b96f3d02be7cc50ad01bb2d0005f0c69cquezel      // TODO CQ why not iterate over entry set if were going to use the key to get the value?
726336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      for (String name : suiteResults.keySet()) {
727336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        ISuiteResult suiteResult = suiteResults.get(name);
728336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust        sb.append(suiteResult.toString());
729336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust      }
730975d9acab06f8de7ef2791ebe784c6d1c6b4e6d9the.mindstorm      Utils.writeFile(getOutputDirectory(xmlSuite), testContext.getName() + ".properties", sb.toString());
731336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust    }
732336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust  }
733336f0ef401e9f564b8dc99d601ac80e8891ac2c1Cédric Beust}
734