NIHVIVO-222 Capture the output of the test suite sub-process, to detect whether the suite has failed.
This commit is contained in:
parent
68887fef02
commit
67bb01a24c
7 changed files with 260 additions and 113 deletions
|
@ -17,9 +17,19 @@ import java.util.regex.Pattern;
|
||||||
* is logged with a warning, not an error.
|
* is logged with a warning, not an error.
|
||||||
*/
|
*/
|
||||||
public class IgnoredTests {
|
public class IgnoredTests {
|
||||||
private final File file;
|
public static final IgnoredTests EMPTY_LIST = new IgnoredTests();
|
||||||
|
|
||||||
|
private final String filePath;
|
||||||
private final List<IgnoredTestInfo> tests;
|
private final List<IgnoredTestInfo> tests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an empty instance.
|
||||||
|
*/
|
||||||
|
private IgnoredTests() {
|
||||||
|
this.filePath = "NO FILE";
|
||||||
|
this.tests = Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Parse the file of ignored tests.
|
* Parse the file of ignored tests.
|
||||||
|
@ -38,7 +48,8 @@ public class IgnoredTests {
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public IgnoredTests(File file) {
|
public IgnoredTests(File file) {
|
||||||
this.file = file;
|
this.filePath = file.getAbsolutePath();
|
||||||
|
|
||||||
List<IgnoredTestInfo> tests = new ArrayList<IgnoredTestInfo>();
|
List<IgnoredTestInfo> tests = new ArrayList<IgnoredTestInfo>();
|
||||||
|
|
||||||
BufferedReader reader = null;
|
BufferedReader reader = null;
|
||||||
|
@ -81,9 +92,9 @@ public class IgnoredTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package access -- only used in unit tests.
|
* Get a copy of the whole list.
|
||||||
*/
|
*/
|
||||||
List<IgnoredTestInfo> getList() {
|
public List<IgnoredTestInfo> getList() {
|
||||||
return new ArrayList<IgnoredTestInfo>(tests);
|
return new ArrayList<IgnoredTestInfo>(tests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +149,7 @@ public class IgnoredTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String s = " ignored tests from " + file.getPath() + "\n";
|
String s = " ignored tests from " + this.filePath + "\n";
|
||||||
for (IgnoredTestInfo test : tests) {
|
for (IgnoredTestInfo test : tests) {
|
||||||
s += " " + test.suiteName + ", " + test.testName + "\n";
|
s += " " + test.suiteName + ", " + test.testName + "\n";
|
||||||
}
|
}
|
||||||
|
@ -146,12 +157,13 @@ public class IgnoredTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Package access so it can be used in unit tests.
|
* Encapsulates a line from the file with suite name, test name, and
|
||||||
|
* comment.
|
||||||
*/
|
*/
|
||||||
static class IgnoredTestInfo {
|
public static class IgnoredTestInfo {
|
||||||
final String suiteName;
|
public final String suiteName;
|
||||||
final String testName;
|
public final String testName;
|
||||||
final String comment;
|
public final String comment;
|
||||||
|
|
||||||
public IgnoredTestInfo(String suiteName, String testName, String comment) {
|
public IgnoredTestInfo(String suiteName, String testName, String comment) {
|
||||||
this.suiteName = suiteName.trim();
|
this.suiteName = suiteName.trim();
|
||||||
|
|
|
@ -36,8 +36,9 @@ public class SeleniumRunner {
|
||||||
this.modelCleaner = new ModelCleaner(parms, this.tomcatController);
|
this.modelCleaner = new ModelCleaner(parms, this.tomcatController);
|
||||||
this.suiteRunner = new SuiteRunner(parms);
|
this.suiteRunner = new SuiteRunner(parms);
|
||||||
this.outputManager = new OutputManager(parms);
|
this.outputManager = new OutputManager(parms);
|
||||||
this.dataModel = new DataModel();
|
|
||||||
|
|
||||||
|
this.dataModel = new DataModel();
|
||||||
|
this.dataModel.setIgnoredTestList(parms.getIgnoredTests());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,10 +9,15 @@ import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests;
|
||||||
|
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
|
||||||
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
|
import edu.cornell.mannlib.vitro.utilities.testrunner.LogStats;
|
||||||
import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
|
import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
|
||||||
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener;
|
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener;
|
||||||
|
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput;
|
||||||
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults;
|
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults;
|
||||||
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults.TestResults;
|
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults.TestResults;
|
||||||
|
|
||||||
|
@ -26,12 +31,13 @@ public class DataModel {
|
||||||
private Collection<File> selectedSuites = Collections.emptyList();
|
private Collection<File> selectedSuites = Collections.emptyList();
|
||||||
private Collection<SuiteResults> suiteResults = Collections.emptyList();
|
private Collection<SuiteResults> suiteResults = Collections.emptyList();
|
||||||
private OutputDataListener.Info dataListenerInfo = OutputDataListener.Info.EMPTY_INFO;
|
private OutputDataListener.Info dataListenerInfo = OutputDataListener.Info.EMPTY_INFO;
|
||||||
|
private IgnoredTests ignoredTestList = IgnoredTests.EMPTY_LIST;
|
||||||
private LogStats logStats = LogStats.EMPTY_LOG_STATS; // TODO
|
private LogStats logStats = LogStats.EMPTY_LOG_STATS; // TODO
|
||||||
|
|
||||||
/* derived data */
|
/* derived data */
|
||||||
private Status runStatus = Status.PENDING;
|
private Status runStatus = Status.PENDING;
|
||||||
|
|
||||||
private final List<SuiteData> allSuiteData = new ArrayList<SuiteData>();
|
private final SortedMap<String, SuiteData> suiteDataMap = new TreeMap<String, SuiteData>();
|
||||||
private final List<SuiteData> pendingSuites = new ArrayList<SuiteData>();
|
private final List<SuiteData> pendingSuites = new ArrayList<SuiteData>();
|
||||||
private final List<SuiteData> passingSuites = new ArrayList<SuiteData>();
|
private final List<SuiteData> passingSuites = new ArrayList<SuiteData>();
|
||||||
private final List<SuiteData> failingSuites = new ArrayList<SuiteData>();
|
private final List<SuiteData> failingSuites = new ArrayList<SuiteData>();
|
||||||
|
@ -79,6 +85,11 @@ public class DataModel {
|
||||||
calculate();
|
calculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIgnoredTestList(IgnoredTests ignoredTestList) {
|
||||||
|
this.ignoredTestList = ignoredTestList;
|
||||||
|
calculate();
|
||||||
|
}
|
||||||
|
|
||||||
public void setLogStats(LogStats logStats) { // TODO
|
public void setLogStats(LogStats logStats) { // TODO
|
||||||
this.logStats = logStats;
|
this.logStats = logStats;
|
||||||
calculate();
|
calculate();
|
||||||
|
@ -95,7 +106,8 @@ public class DataModel {
|
||||||
// Clear all derived data.
|
// Clear all derived data.
|
||||||
runStatus = Status.OK;
|
runStatus = Status.OK;
|
||||||
|
|
||||||
allSuiteData.clear();
|
suiteDataMap.clear();
|
||||||
|
|
||||||
ignoredSuites.clear();
|
ignoredSuites.clear();
|
||||||
pendingSuites.clear();
|
pendingSuites.clear();
|
||||||
failingSuites.clear();
|
failingSuites.clear();
|
||||||
|
@ -119,34 +131,58 @@ public class DataModel {
|
||||||
contentsMap.put(contents.getName(), contents);
|
contentsMap.put(contents.getName(), contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String name : dataListenerInfo.getSuiteNames()) {
|
for (SuiteContents contents : suiteContents) {
|
||||||
SuiteContents contents = contentsMap.get(name);
|
String name = contents.getName();
|
||||||
SuiteResults result = resultsMap.get(name);
|
SuiteResults result = resultsMap.get(name);
|
||||||
boolean ignored = dataListenerInfo.getIgnoredSuiteNames().contains(
|
boolean ignored = ignoredTestList.isIgnored(name);
|
||||||
name);
|
ProcessOutput failureMessages = dataListenerInfo
|
||||||
allSuiteData.add(new SuiteData(name, ignored, contents, result));
|
.getFailureMessages().get(name);
|
||||||
|
suiteDataMap.put(name, new SuiteData(name, ignored, contents,
|
||||||
|
result, failureMessages));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tallys of suites and tests.
|
* Tallys of suites and tests.
|
||||||
*/
|
*/
|
||||||
for (SuiteData sd : allSuiteData) {
|
for (SuiteData sd : suiteDataMap.values()) {
|
||||||
SuiteContents contents = sd.getContents();
|
switch (sd.getSuiteStatus()) {
|
||||||
SuiteResults result = sd.getResults();
|
case ERROR:
|
||||||
if (result != null) {
|
failingSuites.add(sd);
|
||||||
tallyTestResults(result);
|
break;
|
||||||
} else if (contents != null) {
|
case PENDING:
|
||||||
|
pendingSuites.add(sd);
|
||||||
|
break;
|
||||||
|
case WARN:
|
||||||
|
ignoredSuites.add(sd);
|
||||||
|
break;
|
||||||
|
default: // Status.OK
|
||||||
|
passingSuites.add(sd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SuiteData sd : suiteDataMap.values()) {
|
||||||
|
SuiteResults sResult = sd.getResults();
|
||||||
|
if (sResult != null) {
|
||||||
|
tallyTestResults(sResult);
|
||||||
|
} else if (sd.getContents() != null) {
|
||||||
tallyTestContents(sd);
|
tallyTestContents(sd);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (sd.isIgnored()) {
|
for (TestResults tResult : allTests) {
|
||||||
ignoredSuites.add(sd);
|
switch (tResult.getStatus()) {
|
||||||
} else if (result == null) {
|
case OK:
|
||||||
pendingSuites.add(sd);
|
passingTests.add(tResult);
|
||||||
} else if (result.getStatus() == Status.ERROR) {
|
break;
|
||||||
failingSuites.add(sd);
|
case PENDING:
|
||||||
} else {
|
pendingTests.add(tResult);
|
||||||
passingSuites.add(sd);
|
break;
|
||||||
|
case WARN:
|
||||||
|
ignoredTests.add(tResult);
|
||||||
|
break;
|
||||||
|
default: // Status.ERROR
|
||||||
|
failingTests.add(tResult);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,41 +211,19 @@ public class DataModel {
|
||||||
private void tallyTestResults(SuiteResults sResult) {
|
private void tallyTestResults(SuiteResults sResult) {
|
||||||
for (TestResults tResult : sResult.getTests()) {
|
for (TestResults tResult : sResult.getTests()) {
|
||||||
allTests.add(tResult);
|
allTests.add(tResult);
|
||||||
switch (tResult.getStatus()) {
|
|
||||||
case OK:
|
|
||||||
passingTests.add(tResult);
|
|
||||||
break;
|
|
||||||
case PENDING:
|
|
||||||
pendingTests.add(tResult);
|
|
||||||
break;
|
|
||||||
case WARN:
|
|
||||||
ignoredTests.add(tResult);
|
|
||||||
break;
|
|
||||||
default: // Status.ERROR
|
|
||||||
failingTests.add(tResult);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Categorize all tests for which we have no results.
|
* Populate {@link #allTests} with the tests for which we have no results.
|
||||||
*/
|
*/
|
||||||
private void tallyTestContents(SuiteData suiteData) {
|
private void tallyTestContents(SuiteData suiteData) {
|
||||||
SuiteContents contents = suiteData.getContents();
|
Status suiteStatus = suiteData.getSuiteStatus();
|
||||||
|
|
||||||
for (String testName : contents.getTestNames()) {
|
for (String testName : suiteData.getContents().getTestNames()) {
|
||||||
if (suiteData.isIgnored()) {
|
TestResults t = new TestResults(testName, suiteData.getName(), "",
|
||||||
TestResults t = new TestResults(testName, suiteData.getName(),
|
suiteStatus, "");
|
||||||
"", Status.WARN, "");
|
allTests.add(t);
|
||||||
allTests.add(t);
|
|
||||||
ignoredTests.add(t);
|
|
||||||
} else {
|
|
||||||
TestResults t = new TestResults(testName, suiteData.getName(),
|
|
||||||
"", Status.PENDING, "");
|
|
||||||
allTests.add(t);
|
|
||||||
pendingTests.add(t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +264,7 @@ public class DataModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTotalSuiteCount() {
|
public int getTotalSuiteCount() {
|
||||||
return allSuiteData.size();
|
return suiteDataMap.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPassingSuiteCount() {
|
public int getPassingSuiteCount() {
|
||||||
|
@ -305,4 +319,30 @@ public class DataModel {
|
||||||
return Collections.unmodifiableCollection(ignoredTests);
|
return Collections.unmodifiableCollection(ignoredTests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<IgnoredTestInfo> getIgnoredTestInfo() {
|
||||||
|
return ignoredTestList.getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutputLink(String suiteName, String testName) {
|
||||||
|
SuiteData sd = suiteDataMap.get(suiteName);
|
||||||
|
if (sd != null) {
|
||||||
|
SuiteResults s = sd.getResults();
|
||||||
|
if (s != null) {
|
||||||
|
if (testName.equals("*")) {
|
||||||
|
return s.getOutputLink();
|
||||||
|
} else {
|
||||||
|
TestResults t = s.getTest(testName);
|
||||||
|
if (t != null) {
|
||||||
|
return t.getOutputLink();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReasonForIgnoring(String suiteName, String testName) {
|
||||||
|
return ignoredTestList.getReasonForIgnoring(suiteName, testName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,22 +2,28 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.utilities.testrunner.datamodel;
|
package edu.cornell.mannlib.vitro.utilities.testrunner.datamodel;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.utilities.testrunner.Status;
|
||||||
|
import edu.cornell.mannlib.vitro.utilities.testrunner.output.OutputDataListener.ProcessOutput;
|
||||||
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults;
|
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults;
|
||||||
|
import edu.cornell.mannlib.vitro.utilities.testrunner.output.SuiteResults.TestResults;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO
|
* What do we know about this suite, both before it runs and after it has run?
|
||||||
*/
|
*/
|
||||||
public class SuiteData {
|
public class SuiteData {
|
||||||
private final String name;
|
private final String name;
|
||||||
private final boolean ignored;
|
private final boolean ignored;
|
||||||
private final SuiteContents contents;
|
private final SuiteContents contents;
|
||||||
private final SuiteResults results;
|
private final SuiteResults results;
|
||||||
|
private final ProcessOutput failureMessages;
|
||||||
|
|
||||||
public SuiteData(String name, boolean ignored, SuiteContents contents, SuiteResults results) {
|
public SuiteData(String name, boolean ignored, SuiteContents contents,
|
||||||
|
SuiteResults results, ProcessOutput failureMessages) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.ignored = ignored;
|
this.ignored = ignored;
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
this.results = results;
|
this.results = results;
|
||||||
|
this.failureMessages = failureMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
@ -36,4 +42,25 @@ public class SuiteData {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Status getSuiteStatus() {
|
||||||
|
if (ignored) {
|
||||||
|
return Status.WARN;
|
||||||
|
}
|
||||||
|
if (failureMessages != null) {
|
||||||
|
return Status.ERROR;
|
||||||
|
}
|
||||||
|
if (results == null) {
|
||||||
|
return Status.PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have results and no failure messages, scan the results for the
|
||||||
|
* worst status.
|
||||||
|
*/
|
||||||
|
Status status = Status.OK;
|
||||||
|
for (TestResults t : results.getTests()) {
|
||||||
|
status = Status.combine(status, t.getStatus());
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,11 @@ 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.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
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.listener.Listener;
|
import edu.cornell.mannlib.vitro.utilities.testrunner.listener.Listener;
|
||||||
|
@ -16,8 +17,9 @@ public class OutputDataListener 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>();
|
private ProcessOutput currentSuiteOutput = new ProcessOutput("");
|
||||||
|
private Map<String, ProcessOutput> failureMessages = new HashMap<String, ProcessOutput>();
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// Listener methods that affect the data model
|
// Listener methods that affect the data model
|
||||||
|
@ -40,14 +42,27 @@ public class OutputDataListener implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suiteIgnored(File suite) {
|
public void suiteStarted(File suiteDir) {
|
||||||
suiteNames.add(FileHelper.baseName(suite));
|
currentSuiteOutput = new ProcessOutput(FileHelper.baseName(suiteDir));
|
||||||
ignoredSuiteNames.add(FileHelper.baseName(suite));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suiteAdded(File suite) {
|
public void suiteStopped(File suiteDir) {
|
||||||
suiteNames.add(FileHelper.baseName(suite));
|
if (currentSuiteOutput.isSuiteFailure()) {
|
||||||
|
failureMessages.put(currentSuiteOutput.suiteName,
|
||||||
|
currentSuiteOutput);
|
||||||
|
}
|
||||||
|
currentSuiteOutput = new ProcessOutput("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void subProcessStdout(String string) {
|
||||||
|
currentSuiteOutput.addStdout(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void subProcessErrout(String string) {
|
||||||
|
currentSuiteOutput.addErrout(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
@ -63,26 +78,22 @@ public class OutputDataListener implements Listener {
|
||||||
private final boolean runCompleted;
|
private final boolean runCompleted;
|
||||||
private final long startTime;
|
private final long startTime;
|
||||||
private final long endTime;
|
private final long endTime;
|
||||||
private final List<String> suiteNames;
|
private final Map<String, ProcessOutput> failureMessages;
|
||||||
private final List<String> ignoredSuiteNames;
|
|
||||||
|
|
||||||
Info() {
|
Info() {
|
||||||
this.runCompleted = false;
|
this.runCompleted = false;
|
||||||
this.startTime = 0;
|
this.startTime = 0;
|
||||||
this.endTime = 0;
|
this.endTime = 0;
|
||||||
this.suiteNames = Collections.emptyList();
|
this.failureMessages = Collections.emptyMap();
|
||||||
this.ignoredSuiteNames = Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Info(OutputDataListener parent) {
|
Info(OutputDataListener parent) {
|
||||||
this.runCompleted = parent.runCompleted;
|
this.runCompleted = parent.runCompleted;
|
||||||
this.startTime = parent.startTime;
|
this.startTime = parent.startTime;
|
||||||
this.endTime = parent.endTime;
|
this.endTime = parent.endTime;
|
||||||
this.suiteNames = Collections
|
this.failureMessages = Collections
|
||||||
.unmodifiableList(new ArrayList<String>(parent.suiteNames));
|
.unmodifiableMap(new HashMap<String, ProcessOutput>(
|
||||||
this.ignoredSuiteNames = Collections
|
parent.failureMessages));
|
||||||
.unmodifiableList(new ArrayList<String>(
|
|
||||||
parent.ignoredSuiteNames));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunCompleted() {
|
public boolean isRunCompleted() {
|
||||||
|
@ -105,13 +116,10 @@ public class OutputDataListener implements Listener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getSuiteNames() {
|
public Map<String, ProcessOutput> getFailureMessages() {
|
||||||
return suiteNames;
|
return failureMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getIgnoredSuiteNames() {
|
|
||||||
return ignoredSuiteNames;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,10 +129,61 @@ public class OutputDataListener implements Listener {
|
||||||
return new Info(this);
|
return new Info(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// A class that summarized the sub-process output from a test suite.
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output from a subprocess that runs a test suite. It's only
|
||||||
|
* interesting if it indicates a suite failure.
|
||||||
|
*/
|
||||||
|
public static class ProcessOutput {
|
||||||
|
private final String suiteName;
|
||||||
|
private final StringBuilder stdout = new StringBuilder();
|
||||||
|
private final StringBuilder errout = new StringBuilder();
|
||||||
|
|
||||||
|
public ProcessOutput(String suiteName) {
|
||||||
|
this.suiteName = suiteName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addStdout(String string) {
|
||||||
|
stdout.append(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addErrout(String string) {
|
||||||
|
errout.append(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSuiteName() {
|
||||||
|
return suiteName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStdout() {
|
||||||
|
return stdout.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrout() {
|
||||||
|
return errout.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuiteFailure() {
|
||||||
|
return errout.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
// Listener methods that don't affect the data model
|
// Listener methods that don't affect the data model
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void suiteAdded(File suite) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void suiteIgnored(File suite) {
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runFailed(Exception e) {
|
public void runFailed(Exception e) {
|
||||||
}
|
}
|
||||||
|
@ -205,22 +264,10 @@ public class OutputDataListener implements Listener {
|
||||||
public void subProcessStartInBackground(List<String> command) {
|
public void subProcessStartInBackground(List<String> command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void subProcessStdout(String string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void subProcessErrout(String string) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void subProcessStop(List<String> command) {
|
public void subProcessStop(List<String> command) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void suiteStarted(File suiteDir) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void suiteTestingStarted(File suiteDir) {
|
public void suiteTestingStarted(File suiteDir) {
|
||||||
}
|
}
|
||||||
|
@ -237,10 +284,6 @@ public class OutputDataListener implements Listener {
|
||||||
public void suiteTestingStopped(File suiteDir) {
|
public void suiteTestingStopped(File suiteDir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void suiteStopped(File suiteDir) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cleanUploadStart(File uploadDirectory) {
|
public void cleanUploadStart(File uploadDirectory) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
|
import edu.cornell.mannlib.vitro.utilities.testrunner.FileHelper;
|
||||||
|
import edu.cornell.mannlib.vitro.utilities.testrunner.IgnoredTests.IgnoredTestInfo;
|
||||||
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;
|
||||||
|
@ -93,6 +94,8 @@ public class OutputSummaryFormatter {
|
||||||
|
|
||||||
private void writeHeader(PrintWriter writer) {
|
private void writeHeader(PrintWriter writer) {
|
||||||
Status runStatus = dataModel.getRunStatus();
|
Status runStatus = dataModel.getRunStatus();
|
||||||
|
String statusString = (runStatus == Status.PENDING) ? "IN PROGRESS"
|
||||||
|
: runStatus.toString();
|
||||||
String startString = formatDateTime(dataModel.getStartTime());
|
String startString = formatDateTime(dataModel.getStartTime());
|
||||||
|
|
||||||
writer.println("<html>");
|
writer.println("<html>");
|
||||||
|
@ -107,7 +110,7 @@ public class OutputSummaryFormatter {
|
||||||
writer.println(" <div class=\"heading\">");
|
writer.println(" <div class=\"heading\">");
|
||||||
writer.println(" Acceptance test results: " + startString);
|
writer.println(" Acceptance test results: " + startString);
|
||||||
writer.println(" <div class=\"" + runStatus.getHtmlClass()
|
writer.println(" <div class=\"" + runStatus.getHtmlClass()
|
||||||
+ " one-word\">" + runStatus + "</div>");
|
+ " one-word\">" + statusString + "</div>");
|
||||||
writer.println(" </div>");
|
writer.println(" </div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +217,8 @@ public class OutputSummaryFormatter {
|
||||||
|
|
||||||
private void writeIgnoreSection(PrintWriter writer) {
|
private void writeIgnoreSection(PrintWriter writer) {
|
||||||
String warnClass = Status.WARN.getHtmlClass();
|
String warnClass = Status.WARN.getHtmlClass();
|
||||||
Collection<TestResults> ignoredTests = dataModel.getIgnoredTests();
|
Collection<IgnoredTestInfo> ignoredTests = dataModel
|
||||||
|
.getIgnoredTestInfo();
|
||||||
|
|
||||||
writer.println(" <div class=section>Ignored tests</div>");
|
writer.println(" <div class=section>Ignored tests</div>");
|
||||||
writer.println();
|
writer.println();
|
||||||
|
@ -225,13 +229,22 @@ 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 (TestResults t : ignoredTests) {
|
for (IgnoredTestInfo info : ignoredTests) {
|
||||||
|
String suiteName = info.suiteName;
|
||||||
|
String testName = info.testName;
|
||||||
|
String link = dataModel.getOutputLink(suiteName, testName);
|
||||||
|
String reason = dataModel.getReasonForIgnoring(suiteName,
|
||||||
|
testName);
|
||||||
|
|
||||||
writer.println(" <tr class=\"" + warnClass + "\">");
|
writer.println(" <tr class=\"" + warnClass + "\">");
|
||||||
writer.println(" <td>" + t.getSuiteName() + "</td>");
|
writer.println(" <td>" + suiteName + "</td>");
|
||||||
writer.println(" <td><a href=\"" + t.getOutputLink()
|
if (link.isEmpty()) {
|
||||||
+ "\">" + t.getTestName() + "</a></td>");
|
writer.println(" <td>" + testName + "</td>");
|
||||||
writer.println(" <td>" + t.getReasonForIgnoring()
|
} else {
|
||||||
+ "</td>");
|
writer.println(" <td><a href=\"" + link + "\">"
|
||||||
|
+ testName + "</a></td>");
|
||||||
|
}
|
||||||
|
writer.println(" <td>" + reason + "</td>");
|
||||||
writer.println(" </tr>");
|
writer.println(" </tr>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -120,15 +122,20 @@ public class SuiteResults {
|
||||||
|
|
||||||
private final String suiteName;
|
private final String suiteName;
|
||||||
private final String outputLink;
|
private final String outputLink;
|
||||||
private final List<TestResults> tests;
|
private final Map<String, TestResults> testMap;
|
||||||
private final Status status;
|
private final Status status;
|
||||||
|
|
||||||
public SuiteResults(String suiteName, String outputLink,
|
public SuiteResults(String suiteName, String outputLink,
|
||||||
List<TestResults> tests, Status status) {
|
List<TestResults> tests, Status status) {
|
||||||
this.suiteName = suiteName;
|
this.suiteName = suiteName;
|
||||||
this.outputLink = outputLink;
|
this.outputLink = outputLink;
|
||||||
this.tests = tests;
|
|
||||||
this.status = status;
|
this.status = status;
|
||||||
|
|
||||||
|
Map<String, TestResults> map = new HashMap<String, TestResults>();
|
||||||
|
for (TestResults t : tests) {
|
||||||
|
map.put(t.getTestName(), t);
|
||||||
|
}
|
||||||
|
testMap = Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
@ -144,7 +151,11 @@ public class SuiteResults {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<TestResults> getTests() {
|
public Collection<TestResults> getTests() {
|
||||||
return Collections.unmodifiableCollection(tests);
|
return Collections.unmodifiableCollection(testMap.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestResults getTest(String testName) {
|
||||||
|
return testMap.get(testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TestResults {
|
public static class TestResults {
|
||||||
|
|
Loading…
Add table
Reference in a new issue