NIHVIVO-2811 Restructure the build utilities into a single directory, and compile them all at the beginning.
This commit is contained in:
parent
60e92e9bf0
commit
0e4441935e
14 changed files with 113 additions and 147 deletions
107
webapp/build.xml
107
webapp/build.xml
|
@ -15,21 +15,24 @@
|
|||
- - - - - - - - - - - - - - - - - -->
|
||||
<dirname property="corebase.dir" file="${ant.file.vitroCore}" />
|
||||
|
||||
<!--
|
||||
If calling from a Product build script, these properties already point to
|
||||
the product-related locations, so setting them here has no effect.
|
||||
-->
|
||||
<!-- A product script will override appbase.dir, but not corebase.dir -->
|
||||
<property name="appbase.dir" location="${corebase.dir}" />
|
||||
|
||||
<property name="build.dir" location=".build" />
|
||||
<property name="deploy.properties.file" location="config/deploy.properties" />
|
||||
|
||||
<property name="war.dir" location="${build.dir}/war" />
|
||||
<property name="war-webinf.dir" location="${war.dir}/WEB-INF" />
|
||||
<property name="war-classes.dir" location="${war-webinf.dir}/classes" />
|
||||
<property name="war-resources.dir" location="${war-webinf.dir}/resources" />
|
||||
<property name="revisionInfo.build.file" location="${war-resources.dir}/revisionInfo.txt" />
|
||||
<property name="utilities.base.dir" location="${corebase.dir}/../utilities/buildutils" />
|
||||
<property name="utilities.source.dir" location="${utilities.base.dir}/src" />
|
||||
<property name="utilities.lib.dir" location="${utilities.base.dir}/lib" />
|
||||
|
||||
<property name="test-classes.dir" location="${build.dir}/testclasses" />
|
||||
<property name="war.dir" location="${build.dir}/war" />
|
||||
<property name="war.webinf.dir" location="${war.dir}/WEB-INF" />
|
||||
<property name="war.classes.dir" location="${war.webinf.dir}/classes" />
|
||||
<property name="war.resources.dir" location="${war.webinf.dir}/resources" />
|
||||
<property name="revisionInfo.build.file" location="${war.resources.dir}/revisionInfo.txt" />
|
||||
|
||||
<property name="test.classes.dir" location="${build.dir}/testClasses" />
|
||||
<property name="utility.classes.dir" location="${build.dir}/utilityClasses" />
|
||||
|
||||
<property name="javac.deprecation" value="true" />
|
||||
|
||||
|
@ -37,23 +40,30 @@
|
|||
paths: for compiling and running
|
||||
- - - - - - - - - - - - - - - - - -->
|
||||
<path id="compile.classpath">
|
||||
<fileset dir="${appbase.dir}/lib">
|
||||
<include name="**/*.jar" />
|
||||
</fileset>
|
||||
<fileset dir="${appbase.dir}/lib" includes="*.jar" />
|
||||
</path>
|
||||
|
||||
<path id="utility.compile.classpath">
|
||||
<fileset dir="${utilities.lib.dir}" includes="*.jar" />
|
||||
</path>
|
||||
|
||||
<path id="utility.run.classpath">
|
||||
<pathelement location="${utility.classes.dir}" />
|
||||
<path refid="utility.compile.classpath" />
|
||||
</path>
|
||||
|
||||
<path id="test.compile.classpath">
|
||||
<pathelement location="${war-classes.dir}" />
|
||||
<pathelement location="${war.classes.dir}" />
|
||||
<path refid="compile.classpath" />
|
||||
</path>
|
||||
|
||||
<path id="test.run.classpath">
|
||||
<pathelement location="${appbase.dir}/test" />
|
||||
<pathelement location="${test-classes.dir}" />
|
||||
<pathelement location="${test.classes.dir}" />
|
||||
<path refid="test.compile.classpath" />
|
||||
<path refid="utility.run.classpath" />
|
||||
</path>
|
||||
|
||||
|
||||
<!-- =================================
|
||||
target: describe
|
||||
================================= -->
|
||||
|
@ -123,25 +133,43 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
<delete dir="${solr.home.dir}" excludes="data/**/*" includeemptydirs="true" />
|
||||
</target>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - -
|
||||
target: compileUtilities
|
||||
- - - - - - - - - - - - - - - - - -->
|
||||
<target name="compileUtilities">
|
||||
<mkdir dir="${utility.classes.dir}" />
|
||||
<javac srcdir="${utilities.source.dir}"
|
||||
destdir="${utility.classes.dir}"
|
||||
debug="true"
|
||||
deprecation="${javac.deprecation}"
|
||||
encoding="UTF8"
|
||||
includeantruntime="false"
|
||||
optimize="false"
|
||||
source="1.6">
|
||||
<classpath refid="utility.compile.classpath" />
|
||||
</javac>
|
||||
|
||||
<typedef name="dirDifference"
|
||||
classname="edu.cornell.mannlib.vitro.utilities.anttasks.DirDifferenceFileSet"
|
||||
classpathref="utility.run.classpath" />
|
||||
</target>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - -
|
||||
target: prepare
|
||||
- - - - - - - - - - - - - - - - - -->
|
||||
<target name="prepare" depends="properties">
|
||||
<target name="prepare" depends="properties, compileUtilities">
|
||||
<mkdir dir="${build.dir}" />
|
||||
<mkdir dir="${war-classes.dir}" />
|
||||
<mkdir dir="${war-resources.dir}" />
|
||||
<mkdir dir="${test-classes.dir}" />
|
||||
<mkdir dir="${war.classes.dir}" />
|
||||
<mkdir dir="${war.resources.dir}" />
|
||||
<mkdir dir="${test.classes.dir}" />
|
||||
|
||||
<!-- copy all sorts of web stuff into the war directory. -->
|
||||
<copy todir="${war.dir}">
|
||||
<fileset dir="${appbase.dir}/web">
|
||||
</fileset>
|
||||
<fileset dir="${appbase.dir}">
|
||||
<include name="themes/**/*" />
|
||||
</fileset>
|
||||
<fileset dir="${appbase.dir}/web" />
|
||||
<fileset dir="${appbase.dir}" includes="themes/**/*" />
|
||||
</copy>
|
||||
|
||||
<copy todir="${war-webinf.dir}">
|
||||
<copy todir="${war.webinf.dir}">
|
||||
<fileset dir="${appbase.dir}">
|
||||
<!-- copy the JARs into the war directory -->
|
||||
<include name="lib/*" />
|
||||
|
@ -154,7 +182,7 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
<!-- use the production Log4J properties, unless a debug version exists. -->
|
||||
<available file="${appbase.dir}/config/debug.log4j.properties"
|
||||
property="debug.log4j.exists" />
|
||||
<copy tofile="${war-classes.dir}/log4j.properties" filtering="true" overwrite="true">
|
||||
<copy tofile="${war.classes.dir}/log4j.properties" filtering="true" overwrite="true">
|
||||
<fileset dir="${appbase.dir}/config">
|
||||
<include name="default.log4j.properties" unless="debug.log4j.exists" />
|
||||
<include name="debug.log4j.properties" if="debug.log4j.exists" />
|
||||
|
@ -164,7 +192,7 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
</filterchain>
|
||||
</copy>
|
||||
|
||||
<copy todir="${war-classes.dir}">
|
||||
<copy todir="${war.classes.dir}">
|
||||
<!-- copy the deploy.properties into the war directory -->
|
||||
<fileset file="${deploy.properties.file}" />
|
||||
|
||||
|
@ -183,14 +211,14 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
<target name="compile" depends="prepare" description="--> Compile Java sources">
|
||||
<!-- deletes all files that depend on changed .java files -->
|
||||
<depend srcdir="${appbase.dir}/src"
|
||||
destdir="${war-classes.dir}"
|
||||
destdir="${war.classes.dir}"
|
||||
closure="false"
|
||||
cache="${build.dir}/.depcache">
|
||||
<classpath refid="compile.classpath" />
|
||||
</depend>
|
||||
|
||||
<javac srcdir="${appbase.dir}/src"
|
||||
destdir="${war-classes.dir}"
|
||||
destdir="${war.classes.dir}"
|
||||
debug="true"
|
||||
deprecation="${javac.deprecation}"
|
||||
encoding="UTF8"
|
||||
|
@ -206,7 +234,7 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
================================= -->
|
||||
<target name="test" depends="compile" unless="skiptests" description="--> Run JUnit tests">
|
||||
<javac srcdir="${appbase.dir}/test"
|
||||
destdir="${test-classes.dir}"
|
||||
destdir="${test.classes.dir}"
|
||||
debug="true"
|
||||
deprecation="${javac.deprecation}"
|
||||
encoding="UTF8"
|
||||
|
@ -216,7 +244,7 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
<classpath refid="test.compile.classpath" />
|
||||
</javac>
|
||||
|
||||
<java classname="edu.cornell.mannlib.vitro.testing.VitroTestRunner"
|
||||
<java classname="edu.cornell.mannlib.vitro.utilities.testing.VitroTestRunner"
|
||||
fork="yes"
|
||||
failonerror="true">
|
||||
<classpath refid="test.run.classpath" />
|
||||
|
@ -229,8 +257,7 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
target: jar
|
||||
================================= -->
|
||||
<target name="jar" depends="test" description="--> Compile the Java, and build a JAR file">
|
||||
<jar basedir="${war-classes.dir}"
|
||||
destfile="${build.dir}/${ant.project.name}.jar" />
|
||||
<jar basedir="${war.classes.dir}" destfile="${build.dir}/${ant.project.name}.jar" />
|
||||
</target>
|
||||
|
||||
<!-- =================================
|
||||
|
@ -364,20 +391,10 @@ deploy - Deploy the application directly into the Tomcat webapps directory.
|
|||
<attribute name="productName" />
|
||||
<attribute name="productCheckoutDir" />
|
||||
<sequential>
|
||||
<javac srcdir="${corebase.dir}/../utilities/buildutils/revisioninfo"
|
||||
destdir="${test-classes.dir}"
|
||||
debug="true"
|
||||
deprecation="${javac.deprecation}"
|
||||
encoding="UTF8"
|
||||
includeantruntime="false"
|
||||
optimize="false"
|
||||
source="1.6">
|
||||
</javac>
|
||||
|
||||
<java classname="edu.cornell.mannlib.vitro.utilities.revisioninfo.RevisionInfoBuilder"
|
||||
fork="no"
|
||||
failonerror="true">
|
||||
<classpath refid="test.run.classpath" />
|
||||
<classpath refid="utility.run.classpath" />
|
||||
<arg value="@{productName}" />
|
||||
<arg file="@{productCheckoutDir}" />
|
||||
<arg file="${revisionInfo.build.file}" />
|
||||
|
|
|
@ -33,17 +33,10 @@
|
|||
<pathelement location="${vivoProduct.basedir}/../utilities/anttasks/classes" />
|
||||
</path>
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - -
|
||||
custom Ant types
|
||||
- - - - - - - - - - - - - - - - - -->
|
||||
<typedef name="dirDifference"
|
||||
classname="edu.cornell.mannlib.vitro.utilities.anttasks.DirDifferenceFileSet"
|
||||
classpathref="anttasks.classpath" />
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - -
|
||||
target: prepare
|
||||
- - - - - - - - - - - - - - - - - -->
|
||||
<target name="prepare" depends="product-prepare,vitroCore.prepare" />
|
||||
<target name="prepare" depends="compileUtilities,product-prepare,vitroCore.prepare" />
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - -
|
||||
target: product-prepare
|
||||
|
@ -61,25 +54,26 @@
|
|||
<fileset dir="${product.modifications.dir}" />
|
||||
</copy>
|
||||
|
||||
<patternset id="appbase.patterns">
|
||||
<include name="src/**/*" />
|
||||
<include name="lib/**/*" />
|
||||
<include name="test/**/*" />
|
||||
<include name="themes/**/*" />
|
||||
<include name="config/*.properties" />
|
||||
<include name="config/solr/*" />
|
||||
<include name="context.xml" />
|
||||
</patternset>
|
||||
|
||||
<copy todir="${appbase.dir}" includeemptydirs="true">
|
||||
<dirDifference dir="${corebase.dir}">
|
||||
<include name="src/**/*" />
|
||||
<include name="lib/**/*" />
|
||||
<include name="test/**/*" />
|
||||
<include name="themes/**/*" unless="skip.core.themes" />
|
||||
<include name="config/*.properties" />
|
||||
<include name="config/solr/*" />
|
||||
<include name="context.xml" />
|
||||
<patternset refid="appbase.patterns" />
|
||||
<exclude name="themes/**/*" if="skip.core.themes" />
|
||||
<blockingPath>
|
||||
<pathelement location="." />
|
||||
</blockingPath>
|
||||
</dirDifference>
|
||||
<fileset dir=".">
|
||||
<include name="src/**/*" />
|
||||
<include name="lib/**/*" />
|
||||
<include name="test/**/*" />
|
||||
<include name="themes/**/*" />
|
||||
<include name="context.xml" />
|
||||
<patternset refid="appbase.patterns" />
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
|
@ -100,16 +94,16 @@
|
|||
|
||||
In regular use, checks that all appropriate source files have license tags.
|
||||
At release time, applies license text to source files.
|
||||
|
||||
NOTE: don't override licenser.properties.file from the command line.
|
||||
Instead, override licenser.core.properties.file and licenser.product.properties.file
|
||||
The files are handled as properties so they can be overridden from the command line, if desired.
|
||||
================================= -->
|
||||
<target name="licenser" description="--> Check source files for licensing tags">
|
||||
<property name="licenser.product.properties.file"
|
||||
location="./config/licenser/licenser.properties" />
|
||||
<property name="licenser.core.properties.file"
|
||||
location="${corebase.dir}/config/licenser/licenser.properties" />
|
||||
<runLicenserScript productname="${ant.project.name}" propertiesfile="${licenser.product.properties.file}" />
|
||||
<runLicenserScript productname="Vitro core" propertiesfile="${licenser.core.properties.file}" />
|
||||
<runLicenserScript productname="${ant.project.name}"
|
||||
propertiesfile="${licenser.product.properties.file}" />
|
||||
<runLicenserScript productname="Vitro core"
|
||||
propertiesfile="${licenser.core.properties.file}" />
|
||||
</target>
|
||||
</project>
|
||||
|
|
|
@ -1,347 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.testing;
|
||||
|
||||
import static edu.cornell.mannlib.vitro.testing.VitroTestRunner.ReportLevel.BRIEF;
|
||||
import static edu.cornell.mannlib.vitro.testing.VitroTestRunner.ReportLevel.FULL;
|
||||
import static edu.cornell.mannlib.vitro.testing.VitroTestRunner.ReportLevel.MORE;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.Result;
|
||||
import org.junit.runner.notification.Failure;
|
||||
import org.junit.runner.notification.RunListener;
|
||||
|
||||
import com.ibm.icu.text.SimpleDateFormat;
|
||||
|
||||
import edu.cornell.mannlib.vitro.testing.VitroTestRunner.ReportLevel;
|
||||
|
||||
/**
|
||||
* Listen to events as they come from the JUnit test runner. The events from the
|
||||
* lifecycle methods are broken down into semantic chunks and executed. Three
|
||||
* levels of output are available.
|
||||
*
|
||||
* On the surface, JUnit treats "failures" (failed assertions) the same as
|
||||
* "errors" (unexpected exceptions). We're going to distinguish between them.
|
||||
*
|
||||
* @author jeb228
|
||||
*/
|
||||
public class VitroTestRunListener extends RunListener {
|
||||
private final ReportLevel reportLevel;
|
||||
|
||||
private int classCount;
|
||||
private int testsTotal;
|
||||
private int errorsTotal;
|
||||
private int failuresTotal;
|
||||
private int ignoresTotal;
|
||||
private long overallStartTime;
|
||||
|
||||
private Class<?> currentClass;
|
||||
private int testsCurrentClass;
|
||||
private int errorsCurrentClass;
|
||||
private int failuresCurrentClass;
|
||||
private int ignoresCurrentClass;
|
||||
private long classStartTime;
|
||||
|
||||
private String currentTest;
|
||||
private boolean testHadError;
|
||||
private boolean testFailed;
|
||||
private boolean testIgnored;
|
||||
private long testStartTime;
|
||||
|
||||
public VitroTestRunListener(ReportLevel reportLevel) {
|
||||
this.reportLevel = reportLevel;
|
||||
}
|
||||
|
||||
/** Did any of the tests fail or have errors? */
|
||||
public boolean didEverythingPass() {
|
||||
return (failuresTotal == 0) && (errorsTotal == 0);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Life-cycle methods that will be called by the test runner.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void testRunStarted(Description description) throws Exception {
|
||||
openTestRun();
|
||||
reportTestRunStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testStarted(Description description) throws Exception {
|
||||
if (currentClass != description.getTestClass()) {
|
||||
if (currentClass != null) {
|
||||
closeCurrentClass();
|
||||
reportCurrentClass();
|
||||
}
|
||||
|
||||
openCurrentClass(description);
|
||||
reportCurrentClassStart();
|
||||
}
|
||||
|
||||
openCurrentTest(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testAssumptionFailure(Failure failure) {
|
||||
if (isError(failure)) {
|
||||
testHadError = true;
|
||||
reportError(failure);
|
||||
} else {
|
||||
testFailed = true;
|
||||
reportFailure(failure);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testFailure(Failure failure) throws Exception {
|
||||
if (isError(failure)) {
|
||||
testHadError = true;
|
||||
reportError(failure);
|
||||
} else {
|
||||
testFailed = true;
|
||||
reportFailure(failure);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testFinished(Description description) throws Exception {
|
||||
closeCurrentTest();
|
||||
reportCurrentTest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testIgnored(Description description) throws Exception {
|
||||
testStarted(description);
|
||||
testIgnored = true;
|
||||
testFinished(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testRunFinished(Result result) throws Exception {
|
||||
if (currentClass != null) {
|
||||
closeCurrentClass();
|
||||
reportCurrentClass();
|
||||
}
|
||||
closeTestRun();
|
||||
reportTestRun();
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Handling the logical events.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private void openTestRun() {
|
||||
overallStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void closeTestRun() {
|
||||
// Nothing to close.
|
||||
}
|
||||
|
||||
private void reportTestRunStart() {
|
||||
if (reportLevel == FULL) {
|
||||
System.out
|
||||
.println("Starting test run at " + time(overallStartTime));
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
if (reportLevel == MORE) {
|
||||
System.out
|
||||
.println("Starting test run at " + time(overallStartTime));
|
||||
System.out.println();
|
||||
System.out.println("Tests Pass Error Fail Ignore Seconds");
|
||||
}
|
||||
}
|
||||
|
||||
private void reportTestRun() {
|
||||
int successes = testsTotal - errorsTotal - failuresTotal - ignoresTotal;
|
||||
|
||||
if (reportLevel != BRIEF) {
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.format(
|
||||
"Tests Pass Error Fail Ignore Seconds TOTAL (%d classes)\n",
|
||||
classCount);
|
||||
System.out.format(" %4d %4d %4d %4d %4d %6s\n", testsTotal,
|
||||
successes, errorsTotal, failuresTotal, ignoresTotal,
|
||||
elapsed(overallStartTime));
|
||||
|
||||
if (reportLevel != BRIEF) {
|
||||
System.out.println("Ending test run at "
|
||||
+ time(System.currentTimeMillis()));
|
||||
}
|
||||
}
|
||||
|
||||
private void openCurrentClass(Description description) {
|
||||
currentClass = description.getTestClass();
|
||||
classStartTime = System.currentTimeMillis();
|
||||
testsCurrentClass = 0;
|
||||
errorsCurrentClass = 0;
|
||||
failuresCurrentClass = 0;
|
||||
ignoresCurrentClass = 0;
|
||||
}
|
||||
|
||||
private void closeCurrentClass() {
|
||||
classCount++;
|
||||
testsTotal += testsCurrentClass;
|
||||
errorsTotal += errorsCurrentClass;
|
||||
failuresTotal += failuresCurrentClass;
|
||||
ignoresTotal += ignoresCurrentClass;
|
||||
}
|
||||
|
||||
private void reportCurrentClassStart() {
|
||||
if (reportLevel == FULL) {
|
||||
System.out.format("Tests Pass Error Fail Ignore Seconds %s\n",
|
||||
currentClass.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private void reportCurrentClass() {
|
||||
int successes = testsCurrentClass - errorsCurrentClass
|
||||
- failuresCurrentClass - ignoresCurrentClass;
|
||||
if (reportLevel == MORE) {
|
||||
System.out.format(" %4d %4d %4d %4d %4d %6s %s\n",
|
||||
testsCurrentClass, successes, errorsCurrentClass,
|
||||
failuresCurrentClass, ignoresCurrentClass,
|
||||
elapsed(classStartTime), currentClass.getSimpleName());
|
||||
}
|
||||
if (reportLevel == FULL) {
|
||||
System.out.println("-----------------------------------");
|
||||
System.out.format(" %4d %4d %4d %4d %4d %6s\n",
|
||||
testsCurrentClass, successes, errorsCurrentClass,
|
||||
failuresCurrentClass, ignoresCurrentClass,
|
||||
elapsed(classStartTime));
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
private void openCurrentTest(Description description) {
|
||||
currentTest = description.getMethodName();
|
||||
testHadError = false;
|
||||
testFailed = false;
|
||||
testIgnored = false;
|
||||
testStartTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void closeCurrentTest() {
|
||||
if (testHadError) {
|
||||
errorsCurrentClass++;
|
||||
}
|
||||
if (testFailed) {
|
||||
failuresCurrentClass++;
|
||||
}
|
||||
if (testIgnored) {
|
||||
ignoresCurrentClass++;
|
||||
}
|
||||
testsCurrentClass++;
|
||||
}
|
||||
|
||||
private boolean isError(Failure failure) {
|
||||
Throwable throwable = failure.getException();
|
||||
return (throwable != null) && !(throwable instanceof AssertionError);
|
||||
}
|
||||
|
||||
private void reportError(Failure error) {
|
||||
Description description = error.getDescription();
|
||||
String methodName = description.getMethodName();
|
||||
String className = description.getTestClass().getName();
|
||||
String message = error.getMessage();
|
||||
System.out.format("EXCEPTION: test %s() in %s: %s\n",
|
||||
methodName, className, message);
|
||||
System.out.println(formatStackTrace(error.getException()));
|
||||
}
|
||||
|
||||
private void reportFailure(Failure failure) {
|
||||
Description description = failure.getDescription();
|
||||
String methodName = description.getMethodName();
|
||||
String className = description.getTestClass().getName();
|
||||
String message = failure.getMessage();
|
||||
System.out.format("TEST FAILED: test %s() in %s: %s\n", methodName,
|
||||
className, message);
|
||||
}
|
||||
|
||||
private void reportCurrentTest() {
|
||||
if (reportLevel == FULL) {
|
||||
char passFlag = (testIgnored | testFailed | testHadError) ? ' '
|
||||
: '1';
|
||||
char errorFlag = testHadError ? '1' : ' ';
|
||||
char failFlag = testFailed ? '1' : ' ';
|
||||
char ignoreFlag = testIgnored ? '1' : ' ';
|
||||
System.out.format(
|
||||
" %c %c %c %c %6s %s()\n",
|
||||
passFlag, errorFlag, failFlag, ignoreFlag,
|
||||
elapsed(testStartTime), currentTest);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Formatting methods.
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private final SimpleDateFormat formatter = new SimpleDateFormat(
|
||||
"HH:mm:ss 'on' MMM dd, yyyy");
|
||||
|
||||
private String time(long time) {
|
||||
return formatter.format(new Date(time));
|
||||
}
|
||||
|
||||
/** Show elapsed time in 6 columns. */
|
||||
private String elapsed(long start) {
|
||||
long interval = System.currentTimeMillis() - start;
|
||||
return String.format("%6.2f", ((float) interval) / 1000.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim the stack trace: don't show the line saying "23 more", and don't
|
||||
* show the lines about org.junit or java.lang.reflect or sun.reflect.
|
||||
*
|
||||
* Once we hit some "client code", we won't trim any futher lines even if
|
||||
* they belong to org.junit, or the others.
|
||||
*
|
||||
* If we have nested exceptions, the process repeats for each "Caused by"
|
||||
* section.
|
||||
*/
|
||||
private String formatStackTrace(Throwable throwable) {
|
||||
StringWriter w = new StringWriter();
|
||||
throwable.printStackTrace(new PrintWriter(w));
|
||||
String[] lineArray = w.toString().split("\\n");
|
||||
List<String> lines = new ArrayList<String>(Arrays.asList(lineArray));
|
||||
|
||||
boolean removing = true;
|
||||
for (int i = lines.size() - 1; i > 0; i--) {
|
||||
String line = lines.get(i);
|
||||
if (removing) {
|
||||
if (line.matches("\\s*[\\.\\s\\d]+more\\s*")
|
||||
|| line.contains("at "
|
||||
+ VitroTestRunner.class.getName())
|
||||
|| line.contains("at org.junit.")
|
||||
|| line.contains("at java.lang.reflect.")
|
||||
|| line.contains("at sun.reflect.")) {
|
||||
lines.remove(line);
|
||||
} else {
|
||||
removing = false;
|
||||
}
|
||||
} else {
|
||||
if (line.contains("Caused by: ")) {
|
||||
removing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (String line : lines) {
|
||||
result.append(line).append('\n');
|
||||
}
|
||||
return result.toString().trim();
|
||||
}
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.testing;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.junit.runner.JUnitCore;
|
||||
|
||||
/**
|
||||
* A Java application that will run the Vitro unit tests. It searches for unit
|
||||
* tests in the supplied source directory (any file whose name is *Test.Java).
|
||||
* It runs the tests with a variety of reporting detail, depending on the level
|
||||
* selected. If the level selector is absent or unrecognized, the medium level
|
||||
* is used.
|
||||
*
|
||||
* @author jeb228
|
||||
*/
|
||||
public class VitroTestRunner {
|
||||
public enum ReportLevel {
|
||||
/** Report only the one-line summary. */
|
||||
BRIEF,
|
||||
/** Report times and statistics for each test class. */
|
||||
MORE,
|
||||
/** Report times and statistics for each test method. */
|
||||
FULL
|
||||
}
|
||||
|
||||
private final List<Class<?>> classes;
|
||||
private final VitroTestRunListener listener;
|
||||
|
||||
/**
|
||||
* Locate the test classes. Initialize the test listener.
|
||||
*/
|
||||
public VitroTestRunner(File sourceRootDir, ReportLevel reportLevel) {
|
||||
List<String> classNames = getListOfTestClassNames(sourceRootDir);
|
||||
this.classes = getTestClasses(classNames);
|
||||
this.listener = new VitroTestRunListener(reportLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a recursive search through the source directory.
|
||||
*/
|
||||
private List<String> getListOfTestClassNames(File sourceRootDir) {
|
||||
SortedSet<String> names = new TreeSet<String>();
|
||||
searchForTestClasses(names, "", sourceRootDir);
|
||||
return new ArrayList<String>(names);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively search the directory for files in the form "*Test.java".
|
||||
* Ignore any files or directories whose names start with a "."
|
||||
*/
|
||||
private void searchForTestClasses(SortedSet<String> names, String prefix,
|
||||
File directory) {
|
||||
for (File file : directory.listFiles()) {
|
||||
String filename = file.getName();
|
||||
if (filename.startsWith(".")) {
|
||||
// ignore .svn, etc.
|
||||
} else if (file.isDirectory()) {
|
||||
searchForTestClasses(names, prefix + filename + ".", file);
|
||||
} else if (filename.endsWith("Test.java")) {
|
||||
String classname = filename.substring(0, filename.length() - 5);
|
||||
names.add(prefix + classname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate a class for each test class name.
|
||||
*/
|
||||
private List<Class<?>> getTestClasses(List<String> classNames) {
|
||||
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
for (String classname : classNames) {
|
||||
try {
|
||||
classes.add(Class.forName(classname));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("Can't load test class: "
|
||||
+ classname, e);
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* We've located all of the test clases. Now run them.
|
||||
*/
|
||||
private void run() {
|
||||
JUnitCore junitCore = new JUnitCore();
|
||||
junitCore.addListener(this.listener);
|
||||
junitCore.run(this.classes.toArray(new Class<?>[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Did any of the tests fail?
|
||||
*/
|
||||
private boolean didEverythingPass() {
|
||||
return this.listener.didEverythingPass();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* You must provide a path to the source directory of the test classes.
|
||||
* </p>
|
||||
* <p>
|
||||
* You may also provide a reporting level of "BRIEF", "MORE", or "FULL". If
|
||||
* no level is provided, or if it is not recognized, "BRIEF" is used.
|
||||
* </p>
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if ((args.length < 1) || (args.length > 2)) {
|
||||
usage("Wrong number of arguments: expecting 1 or 2, but found "
|
||||
+ args.length + ".");
|
||||
}
|
||||
File sourceRootDir = new File(args[0]);
|
||||
|
||||
if (!sourceRootDir.exists()) {
|
||||
usage(sourceRootDir + " does not exist.");
|
||||
}
|
||||
if (!sourceRootDir.isDirectory()) {
|
||||
usage(sourceRootDir + " is not a directory.");
|
||||
}
|
||||
|
||||
ReportLevel reportLevel = ReportLevel.MORE;
|
||||
if (args.length == 2) {
|
||||
for (ReportLevel level : ReportLevel.values()) {
|
||||
if (level.toString().equalsIgnoreCase(args[1])) {
|
||||
reportLevel = level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VitroTestRunner runner = new VitroTestRunner(sourceRootDir, reportLevel);
|
||||
runner.run();
|
||||
|
||||
if (!runner.didEverythingPass()) {
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell them how it should have been done.
|
||||
*/
|
||||
private static void usage(String message) {
|
||||
System.out.println(message);
|
||||
System.out.println("usage: " + VitroTestRunner.class.getSimpleName()
|
||||
+ " sourceRootDirectory [ BRIEF | MORE | FULL ]");
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue