NIHVIVO-222 Continue to convert the output data collection from scanning the log to using a Listener.

This commit is contained in:
jeb228 2010-08-18 20:43:31 +00:00
parent 718548b7a8
commit 4bb1727a60
4 changed files with 105 additions and 56 deletions

View file

@ -1,16 +1,22 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner.output; package edu.cornell.mannlib.vitro.utilities.testrunner.output;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener; import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
public class OutputDataModel implements Listener { public class OutputDataModel implements Listener {
private boolean runCompleted; private boolean runCompleted;
private long startTime; private long startTime;
private long endTime; private long endTime;
private final List<String> suiteNames = new ArrayList<String>();
private final List<String> ignoredSuiteNames = new ArrayList<String>();
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Listener methods that affect the data model // Listener methods that affect the data model
@ -31,6 +37,17 @@ public class OutputDataModel implements Listener {
runCompleted = true; runCompleted = true;
} }
@Override
public void suiteIgnored(File suite) {
suiteNames.add(FileHelper.baseName(suite));
ignoredSuiteNames.add(FileHelper.baseName(suite));
}
@Override
public void suiteAdded(File suite) {
suiteNames.add(FileHelper.baseName(suite));
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Accessor methods // Accessor methods
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -55,18 +72,18 @@ public class OutputDataModel implements Listener {
} }
} }
public List<String> getSuiteNames() {
return suiteNames;
}
public List<String> getIgnoredSuiteNames() {
return ignoredSuiteNames;
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Listener methods that don't affect the data model // Listener methods that don't affect the data model
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@Override
public void suiteIgnored(File suite) {
}
@Override
public void suiteAdded(File suite) {
}
@Override @Override
public void runFailed(Exception e) { public void runFailed(Exception e) {
} }

View file

@ -5,14 +5,13 @@ package edu.cornell.mannlib.vitro.utilities.testrunner.output;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.HashMap;
import java.util.List; import java.util.Map;
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper; import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats; import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters; import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters;
import edu.cornell.mannlib.vitro.utilities.testrunner.Status; import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
import edu.cornell.mannlib.vitro.utilities.testrunner.SuiteStats;
/** /**
* Manages the contents of the output area. Removes old files prior to a run. * Manages the contents of the output area. Removes old files prior to a run.
@ -67,12 +66,12 @@ public class OutputManager {
public Status summarizeOutput() { public Status summarizeOutput() {
LogStats log = LogStats.parse(parms.getLogFile()); LogStats log = LogStats.parse(parms.getLogFile());
List<SuiteStats> suites = new ArrayList<SuiteStats>(); Map<String, SuiteResults> suites = new HashMap<String, SuiteResults>();
for (File outputFile : parms.getOutputDirectory().listFiles( for (File outputFile : parms.getOutputDirectory().listFiles(
new HtmlFileFilter())) { new HtmlFileFilter())) {
SuiteStats suite = SuiteStats.parse(parms, outputFile); SuiteResults suite = SuiteResults.parse(parms, outputFile);
if (suite != null) { if (suite != null) {
suites.add(suite); suites.put(suite.getName(), suite);
} }
} }

View file

@ -12,13 +12,13 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map;
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper; import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats; import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters; import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters;
import edu.cornell.mannlib.vitro.utilities.testrunner.Status; import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
import edu.cornell.mannlib.vitro.utilities.testrunner.SuiteStats; import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults.TestResults;
import edu.cornell.mannlib.vitro.utilities.testrunner.SuiteStats.TestInfo;
/** /**
* Creates the summary HTML file. * Creates the summary HTML file.
@ -31,13 +31,17 @@ public class OutputSummaryFormatter {
private final SeleniumRunnerParameters parms; private final SeleniumRunnerParameters parms;
private LogStats log; private LogStats log;
private List<SuiteStats> suites; private Map<String, SuiteResults> suites;
private OutputDataModel dataModel; private OutputDataModel dataModel;
private Status runStatus; private Status runStatus;
private List<TestInfo> allTests = new ArrayList<TestInfo>(); private List<TestResults> allTests = new ArrayList<TestResults>();
private int passingTestCount; private int passingTestCount;
private List<TestInfo> failingTests = new ArrayList<TestInfo>(); private List<TestResults> failingTests = new ArrayList<TestResults>();
private List<TestInfo> ignoredTests = new ArrayList<TestInfo>(); private List<TestResults> ignoredTests = new ArrayList<TestResults>();
private List<String> passingSuites = new ArrayList<String>();
private List<String> failingSuites = new ArrayList<String>();
private List<String> ignoredSuites = new ArrayList<String>();
private List<String> remainingSuites = new ArrayList<String>();
public OutputSummaryFormatter(SeleniumRunnerParameters parms) { public OutputSummaryFormatter(SeleniumRunnerParameters parms) {
this.parms = parms; this.parms = parms;
@ -47,13 +51,14 @@ public class OutputSummaryFormatter {
* Create a summary HTML file from the info contained in this log file and * Create a summary HTML file from the info contained in this log file and
* these suite outputs. * these suite outputs.
*/ */
public void format(LogStats log, List<SuiteStats> suites, public void format(LogStats log, Map<String, SuiteResults> suites,
OutputDataModel dataModel) { OutputDataModel dataModel) {
this.log = log; this.log = log;
this.suites = suites; this.suites = suites;
this.dataModel = dataModel; this.dataModel = dataModel;
this.runStatus = figureOverallStatus(log, suites); this.runStatus = figureOverallStatus(log, suites);
tallyTests(); tallyTests();
tallySuites();
PrintWriter writer = null; PrintWriter writer = null;
try { try {
@ -105,13 +110,14 @@ public class OutputSummaryFormatter {
/** /**
* The overall status for the run is the worst status of any component. * The overall status for the run is the worst status of any component.
*/ */
public Status figureOverallStatus(LogStats log, List<SuiteStats> suites) { public Status figureOverallStatus(LogStats log,
Map<String, SuiteResults> suites) {
if (log.hasErrors()) { if (log.hasErrors()) {
return Status.ERROR; return Status.ERROR;
} }
boolean hasWarnings = log.hasWarnings(); boolean hasWarnings = log.hasWarnings();
for (SuiteStats s : suites) { for (SuiteResults s : suites.values()) {
if (s.getStatus() == Status.ERROR) { if (s.getStatus() == Status.ERROR) {
return Status.ERROR; return Status.ERROR;
} else if (s.getStatus() == Status.WARN) { } else if (s.getStatus() == Status.WARN) {
@ -127,8 +133,8 @@ public class OutputSummaryFormatter {
} }
private void tallyTests() { private void tallyTests() {
for (SuiteStats s : suites) { for (SuiteResults s : suites.values()) {
for (TestInfo t : s.getTests()) { for (TestResults t : s.getTests()) {
this.allTests.add(t); this.allTests.add(t);
if (t.getStatus() == Status.OK) { if (t.getStatus() == Status.OK) {
this.passingTestCount++; this.passingTestCount++;
@ -141,6 +147,25 @@ public class OutputSummaryFormatter {
} }
} }
private void tallySuites() {
List<String> ignoredSuiteNames = dataModel.getIgnoredSuiteNames();
for (String name : dataModel.getSuiteNames()) {
if (ignoredSuiteNames.contains(name)) {
this.ignoredSuites.add(name);
} else if (!suites.containsKey(name)) {
this.remainingSuites.add(name);
} else {
SuiteResults s = suites.get(name);
if (s.getStatus() == Status.ERROR) {
this.failingSuites.add(name);
} else {
this.passingSuites.add(name);
}
}
}
}
private void writeHeader(PrintWriter writer) { private void writeHeader(PrintWriter writer) {
String startString = formatDateTime(dataModel.getStartTime()); String startString = formatDateTime(dataModel.getStartTime());
@ -187,19 +212,22 @@ public class OutputSummaryFormatter {
writer.println(" </td>"); writer.println(" </td>");
writer.println(" <td>"); writer.println(" <td>");
writer.println(" <table cellspacing=\"0\">"); writer.println(" <table cellspacing=\"0\">");
writer.println(" <tr><td>Suites</td><td>" + this.suites.size() writer.println(" <tr><th>&nbsp;</th><th>Suites</th><th>Tests</th>");
+ "</td></tr>"); writer.println(" <tr><th>Total</th><td>" + "</td><td>"
writer.println(" <tr><td>Total tests</td><td>" + "</td>");
+ this.allTests.size() + "</td></tr>"); writer.println(" <tr class=\"" + passClass
writer.println(" <tr class=\"" + passClass + "\"><th>Passed</th><td>" + this.passingSuites.size()
+ "\"><td>Passing tests</td><td>" + this.passingTestCount + "</td><td>" + this.passingTestCount + "</td>");
+ "</td></tr>"); writer.println(" <tr class=\"" + failClass
writer.println(" <tr class=\"" + failClass + "\"><th>Failed</th><td>" + this.failingSuites.size()
+ "\"><td>Failing tests</td><td>" + this.failingTests.size() + "</td><td>" + this.failingTests.size() + "</td>");
+ "</td></tr>"); writer.println(" <tr class=\"" + ignoreClass
writer.println(" <tr class=\"" + ignoreClass + "\"><th>Ignored</th><td>" + this.ignoredSuites.size()
+ "\"><td>Ignored tests</td><td>" + this.ignoredTests.size() + "</td><td>" + this.ignoredTests.size() + "</td>");
+ "</td></tr>"); if (!this.remainingSuites.isEmpty()) {
writer.println(" <tr><th>Remaining</th><td>"
+ this.remainingSuites.size() + "</td><td>?</td>");
}
writer.println(" </table>"); writer.println(" </table>");
writer.println(" </td>"); writer.println(" </td>");
writer.println(" </tr>"); writer.println(" </tr>");
@ -242,7 +270,7 @@ public class OutputSummaryFormatter {
writer.println(" <tr><td colspan=\"2\">No tests failed.</td>" writer.println(" <tr><td colspan=\"2\">No tests failed.</td>"
+ "</tr>"); + "</tr>");
} else { } else {
for (TestInfo t : failingTests) { for (TestResults t : failingTests) {
writer.println(" <tr class=\"" + errorClass + "\">"); writer.println(" <tr class=\"" + errorClass + "\">");
writer.println(" <td>" + t.getSuiteName() + "</td>"); writer.println(" <td>" + t.getSuiteName() + "</td>");
writer.println(" <td><a href=\"" + t.getOutputLink() writer.println(" <td><a href=\"" + t.getOutputLink()
@ -266,7 +294,7 @@ public class OutputSummaryFormatter {
writer.println(" <tr><td colspan=\"3\">No tests ignored.</td>" writer.println(" <tr><td colspan=\"3\">No tests ignored.</td>"
+ "</tr>"); + "</tr>");
} else { } else {
for (TestInfo t : ignoredTests) { for (TestResults t : ignoredTests) {
writer.println(" <tr class=\"" + warnClass + "\">"); writer.println(" <tr class=\"" + warnClass + "\">");
writer.println(" <td>" + t.getSuiteName() + "</td>"); writer.println(" <td>" + t.getSuiteName() + "</td>");
writer.println(" <td><a href=\"" + t.getOutputLink() writer.println(" <td><a href=\"" + t.getOutputLink()
@ -285,7 +313,7 @@ public class OutputSummaryFormatter {
writer.println(); writer.println();
writer.println(" <table cellspacing=\"0\">"); writer.println(" <table cellspacing=\"0\">");
for (SuiteStats s : suites) { for (SuiteResults s : suites.values()) {
writer.println(" <tr class=\"" + s.getStatus().getHtmlClass() writer.println(" <tr class=\"" + s.getStatus().getHtmlClass()
+ "\">"); + "\">");
writer.println(" <td><a href=\"" + s.getOutputLink() + "\">" writer.println(" <td><a href=\"" + s.getOutputLink() + "\">"
@ -303,7 +331,7 @@ public class OutputSummaryFormatter {
writer.println(" <table cellspacing=\"0\">"); writer.println(" <table cellspacing=\"0\">");
writer.println(" <tr><th>Suite name</th><th>Test name</th></tr>\n"); writer.println(" <tr><th>Suite name</th><th>Test name</th></tr>\n");
for (TestInfo t : allTests) { for (TestResults t : allTests) {
writer.println(" <tr class=\"" + t.getStatus().getHtmlClass() writer.println(" <tr class=\"" + t.getStatus().getHtmlClass()
+ "\">"); + "\">");
writer.println(" <td>" + t.getSuiteName() + "</td>"); writer.println(" <td>" + t.getSuiteName() + "</td>");

View file

@ -1,6 +1,6 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */ /* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.utilities.testrunner; package edu.cornell.mannlib.vitro.utilities.testrunner.output;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
@ -13,11 +13,16 @@ import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests;
import edu.cornell.mannlib.vitro.utilities.testrunner.SeleniumRunnerParameters;
import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
/** /**
* Extract any summary information from an HTML output file, produced by a test * Extract any summary information from an HTML output file, produced by a test
* suite. * suite.
*/ */
public class SuiteStats { public class SuiteResults{
/** /**
* If the file doesn't contain a line that includes this pattern, it is not * If the file doesn't contain a line that includes this pattern, it is not
* a suite output file. * a suite output file.
@ -39,17 +44,17 @@ public class SuiteStats {
/** /**
* Parse the fields from this file and attempt to produce a * Parse the fields from this file and attempt to produce a
* {@link SuiteStats} object. If this is not an appropriate file, just * {@link SuiteResults} object. If this is not an appropriate file, just
* return null. * return null.
*/ */
public static SuiteStats parse(SeleniumRunnerParameters parms, public static SuiteResults parse(SeleniumRunnerParameters parms,
File outputFile) { File outputFile) {
IgnoredTests ignoredTests = parms.getIgnoredTests(); IgnoredTests ignoredTests = parms.getIgnoredTests();
boolean isSuiteOutputFile = false; boolean isSuiteOutputFile = false;
Status status = Status.ERROR; Status status = Status.ERROR;
List<TestInfo> tests = new ArrayList<TestInfo>(); List<TestResults> tests = new ArrayList<TestResults>();
String suiteName = FileHelper.baseName(outputFile); String suiteName = FileHelper.baseName(outputFile);
String outputLink = outputFile.getName(); String outputLink = outputFile.getName();
@ -82,13 +87,13 @@ public class SuiteStats {
reasonForIgnoring = ""; reasonForIgnoring = "";
} }
tests.add(new TestInfo(testName, suiteName, testLink, tests.add(new TestResults(testName, suiteName, testLink,
testStatus, reasonForIgnoring)); testStatus, reasonForIgnoring));
} }
} }
status = Status.OK; status = Status.OK;
for (TestInfo t : tests) { for (TestResults t : tests) {
if (t.status == Status.ERROR) { if (t.status == Status.ERROR) {
status = Status.ERROR; status = Status.ERROR;
} else if ((t.status == Status.WARN) && (status == Status.OK)) { } else if ((t.status == Status.WARN) && (status == Status.OK)) {
@ -97,7 +102,7 @@ public class SuiteStats {
} }
if (isSuiteOutputFile) { if (isSuiteOutputFile) {
return new SuiteStats(suiteName, outputLink, tests, status); return new SuiteResults(suiteName, outputLink, tests, status);
} else { } else {
return null; return null;
} }
@ -119,11 +124,11 @@ public class SuiteStats {
private final String suiteName; private final String suiteName;
private final String outputLink; private final String outputLink;
private final List<TestInfo> tests; private final List<TestResults> tests;
private final Status status; private final Status status;
public SuiteStats(String suiteName, String outputLink, public SuiteResults(String suiteName, String outputLink,
List<TestInfo> tests, Status status) { List<TestResults> tests, Status status) {
this.suiteName = suiteName; this.suiteName = suiteName;
this.outputLink = outputLink; this.outputLink = outputLink;
this.tests = tests; this.tests = tests;
@ -142,18 +147,18 @@ public class SuiteStats {
return outputLink; return outputLink;
} }
public Collection<TestInfo> getTests() { public Collection<TestResults> getTests() {
return Collections.unmodifiableCollection(tests); return Collections.unmodifiableCollection(tests);
} }
public static class TestInfo { public static class TestResults {
private final String name; private final String name;
private final String suite; private final String suite;
private final String outputLink; private final String outputLink;
private final Status status; private final Status status;
private final String reasonForIgnoring; private final String reasonForIgnoring;
public TestInfo(String name, String suite, String outputLink, public TestResults(String name, String suite, String outputLink,
Status status, String reasonForIgnoring) { Status status, String reasonForIgnoring) {
this.name = name; this.name = name;
this.suite = suite; this.suite = suite;