Browse Source

Some additional enhancements to junit related classes.

Submitted by:	Stephane Bailliez <sbailliez@imediation.com>


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@268557 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 24 years ago
parent
commit
c30a74289e
5 changed files with 242 additions and 171 deletions
  1. +109
    -44
      src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java
  2. +93
    -93
      src/main/org/apache/tools/ant/taskdefs/optional/junit/Enumerations.java
  3. +9
    -17
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
  4. +14
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
  5. +17
    -16
      src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java

+ 109
- 44
src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java View File

@@ -69,75 +69,140 @@ import java.io.File;
* @author <a href="mailto:jeff.martin@synamic.co.uk">Jeff Martin</a>
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a>
*
* @see JUnitTest
*/
public final class BatchTest extends BaseTest {

/** the reference to the project */
private Project project;

/** the list of filesets containing the testcase filename rules */
private Vector filesets = new Vector();

/**
* create a new batchtest instance
* @param project the project it depends on.
*/
public BatchTest(Project project){
this.project = project;
}

/**
* Add a new fileset instance to this batchtest. Whatever the fileset is,
* only filename that are <tt>.java</tt> or <tt>.class</tt> will be
* considered as 'candidates'.
* @param fs the new fileset containing the rules to get the testcases.
*/
public void addFileSet(FileSet fs) {
filesets.addElement(fs);
}

/**
* return all <tt>JUnitTest</tt> instances obtain by applying the fileset rules.
* @return an enumeration of all elements of this batchtest that are
* a <tt>JUnitTest</tt> instance.
* @see addTestsTo(Vector)
*/
public final Enumeration elements(){
return new FileList();
JUnitTest[] tests = createAllJUnitTest();
return Enumerations.fromArray(tests);
}

public class FileList implements Enumeration{
private String files[]=null;

private int i=0;

private FileList(){
Vector v = new Vector();
for (int j=0; j<filesets.size(); j++) {
FileSet fs = (FileSet) filesets.elementAt(j);
DirectoryScanner ds = fs.getDirectoryScanner(project);
ds.scan();
String[] f = ds.getIncludedFiles();
for (int k=0; k<f.length; k++) {
if (f[k].endsWith(".java")) {
v.addElement(f[k].substring(0, f[k].length()-5));
} else if (f[k].endsWith(".class")) {
v.addElement(f[k].substring(0, f[k].length()-6));
}
}
}

files = new String[v.size()];
v.copyInto(files);
/**
* Convenient method to merge the <tt>JUnitTest</tt>s of this batchtest
* to a <tt>Vector</tt>.
* @param v the vector to which should be added all individual tests of this
* batch test.
*/
final void addTestsTo(Vector v){
JUnitTest[] tests = createAllJUnitTest();
v.ensureCapacity( v.size() + tests.length);
for (int i = 0; i < tests.length; i++) {
v.addElement(tests[i]);
}
}

public final boolean hasMoreElements(){
if(i<files.length)return true;
return false;
/**
* Create all <tt>JUnitTest</tt>s based on the filesets. Each instance
* is configured to match this instance properties.
* @return the array of all <tt>JUnitTest</tt>s that belongs to this batch.
*/
private JUnitTest[] createAllJUnitTest(){
String[] filenames = getFilenames();
JUnitTest[] tests = new JUnitTest[filenames.length];
for (int i = 0; i < tests.length; i++) {
String classname = javaToClass(filenames[i]);
tests[i] = createJUnitTest(classname);
}
return tests;
}

public final Object nextElement() throws NoSuchElementException{
if(hasMoreElements()){
JUnitTest test = new JUnitTest(javaToClass(files[i]));
test.setHaltonerror(haltOnError);
test.setHaltonfailure(haltOnFail);
test.setFork(fork);
test.setIf(ifProperty);
test.setUnless(unlessProperty);
test.setTodir(destDir);
Enumeration list = formatters.elements();
while (list.hasMoreElements()) {
test.addFormatter((FormatterElement)list.nextElement());
/**
* Iterate over all filesets and return the filename of all files
* that end with <tt>.java</tt> or <tt>.class</tt>. This is to avoid
* wrapping a <tt>JUnitTest</tt> over an xml file for example. A Testcase
* is obviouslly a java file (compiled or not).
* @return an array of filenames without their extension. As they should
* normally be taken from their root, filenames should match their fully
* qualified class name (If it is not the case it will fail when running the test).
* For the class <tt>org/apache/Whatever.class</tt> it will return <tt>org/apache/Whatever</tt>.
*/
private String[] getFilenames(){
Vector v = new Vector();
final int size = this.filesets.size();
for (int j=0; j<size; j++) {
FileSet fs = (FileSet) filesets.elementAt(j);
DirectoryScanner ds = fs.getDirectoryScanner(project);
ds.scan();
String[] f = ds.getIncludedFiles();
for (int k = 0; k < f.length; k++) {
String pathname = f[k];
if (pathname.endsWith(".java")) {
v.addElement(pathname.substring(0, pathname.length()-".java".length()));
} else if (pathname.endsWith(".class")) {
v.addElement(pathname.substring(0, pathname.length()-".class".length()));
}
i++;
return test;
}
throw new NoSuchElementException();
}

public final String javaToClass(String fileName){
return fileName.replace(java.io.File.separatorChar, '.');
String[] files = new String[v.size()];
v.copyInto(files);
return files;
}

/**
* convenient method to convert a pathname without extension to a
* fully qualified classname. For example <tt>org/apache/Whatever</tt> will
* be converted to <tt>org.apache.Whatever</tt>
* @param filename the filename to "convert" to a classname.
* @return the classname matching the filename.
*/
public final static String javaToClass(String filename){
return filename.replace(File.separatorChar, '.');
}

/**
* Create a <tt>JUnitTest</tt> that has the same property as this
* <tt>BatchTest</tt> instance.
* @param classname the name of the class that should be run as a
* <tt>JUnitTest</tt>. It must be a fully qualified name.
* @return the <tt>JUnitTest</tt> over the given classname.
*/
private JUnitTest createJUnitTest(String classname){
JUnitTest test = new JUnitTest();
test.setName(classname);
test.setHaltonerror(this.haltOnError);
test.setHaltonfailure(this.haltOnFail);
test.setFork(this.fork);
test.setIf(this.ifProperty);
test.setUnless(this.unlessProperty);
test.setTodir(this.destDir);
Enumeration list = this.formatters.elements();
while (list.hasMoreElements()) {
test.addFormatter((FormatterElement)list.nextElement());
}
return test;
}

}

+ 93
- 93
src/main/org/apache/tools/ant/taskdefs/optional/junit/Enumerations.java View File

@@ -64,29 +64,29 @@ import java.util.NoSuchElementException;
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a>
*/
public final class Enumerations {
private Enumerations(){
}
private Enumerations(){
}

/**
* creates an enumeration from an array of objects.
* @param array the array of object to enumerate.
* @return the enumeration over the array of objects.
*/
public static Enumeration fromArray(Object[] array){
return new ArrayEnumeration(array);
}
/**
* creates an enumeration from an array of objects.
* @param array the array of object to enumerate.
* @return the enumeration over the array of objects.
*/
public static Enumeration fromArray(Object[] array){
return new ArrayEnumeration(array);
}

/**
* creates an enumeration from an array of enumeration. The created enumeration
* will sequentially enumerate over all elements of each enumeration and skip
* <tt>null</tt> enumeration elements in the array.
* @param enums the array of enumerations.
* @return the enumeration over the array of enumerations.
*/
public static Enumeration fromCompound(Enumeration[] enums){
return new CompoundEnumeration(enums);
}
/**
* creates an enumeration from an array of enumeration. The created enumeration
* will sequentially enumerate over all elements of each enumeration and skip
* <tt>null</tt> enumeration elements in the array.
* @param enums the array of enumerations.
* @return the enumeration over the array of enumerations.
*/
public static Enumeration fromCompound(Enumeration[] enums){
return new CompoundEnumeration(enums);
}

}

@@ -96,47 +96,47 @@ public final class Enumerations {
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a>
*/
class ArrayEnumeration implements Enumeration {
/** object array */
private Object[] array;
/** current index */
private int pos;
/**
* Initialize a new enumeration that wraps an array.
* @param array the array of object to enumerate.
*/
public ArrayEnumeration(Object[] array){
this.array = array;
this.pos = 0;
}
/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if and only if this enumeration object
* contains at least one more element to provide;
* <code>false</code> otherwise.
*/
public boolean hasMoreElements() {
return (pos < array.length);
}
/** object array */
private Object[] array;
/** current index */
private int pos;
/**
* Initialize a new enumeration that wraps an array.
* @param array the array of object to enumerate.
*/
public ArrayEnumeration(Object[] array){
this.array = array;
this.pos = 0;
}
/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if and only if this enumeration object
* contains at least one more element to provide;
* <code>false</code> otherwise.
*/
public boolean hasMoreElements() {
return (pos < array.length);
}

/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @throws NoSuchElementException if no more elements exist.
*/
public Object nextElement() throws NoSuchElementException {
if (hasMoreElements()) {
Object o = array[pos];
pos++;
return o;
}
throw new NoSuchElementException();
}
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @throws NoSuchElementException if no more elements exist.
*/
public Object nextElement() throws NoSuchElementException {
if (hasMoreElements()) {
Object o = array[pos];
pos++;
return o;
}
throw new NoSuchElementException();
}
}
/**
* Convenient enumeration over an array of enumeration. For example:
@@ -170,46 +170,46 @@ class ArrayEnumeration implements Enumeration {
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a>
*/
class CompoundEnumeration implements Enumeration {
/** enumeration array */
private Enumeration[] enumArray;
/** index in the enums array */
private int index = 0;
/** enumeration array */
private Enumeration[] enumArray;
/** index in the enums array */
private int index = 0;

public CompoundEnumeration(Enumeration[] enumarray) {
this.enumArray = enumarray;
this.enumArray = enumarray;
}

/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if and only if this enumeration object
* contains at least one more element to provide;
* <code>false</code> otherwise.
*/
/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if and only if this enumeration object
* contains at least one more element to provide;
* <code>false</code> otherwise.
*/
public boolean hasMoreElements() {
while (index < enumArray.length) {
if (enumArray[index] != null && enumArray[index].hasMoreElements()) {
return true;
}
index++;
}
return false;
while (index < enumArray.length) {
if (enumArray[index] != null && enumArray[index].hasMoreElements()) {
return true;
}
index++;
}
return false;
}

/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @throws NoSuchElementException if no more elements exist.
*/
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @throws NoSuchElementException if no more elements exist.
*/
public Object nextElement() throws NoSuchElementException {
if ( hasMoreElements() ) {
return enumArray[index].nextElement();
}
throw new NoSuchElementException();
if ( hasMoreElements() ) {
return enumArray[index].nextElement();
}
throw new NoSuchElementException();
}
}



+ 9
- 17
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java View File

@@ -213,10 +213,7 @@ public class JUnitTask extends Task {
public void addSysproperty(Environment.Variable sysp) {
commandline.addSysproperty(sysp);
}

/**
* create a classpath to use for forked jvm
*/
public Path createClasspath() {
return commandline.createClasspath(project).createPath();
}
@@ -260,21 +257,17 @@ public class JUnitTask extends Task {
*/
public void execute() throws BuildException {
Enumeration list = getIndividualTests();
try {
while (list.hasMoreElements()) {
JUnitTest test = (JUnitTest)list.nextElement();
if ( test.shouldRun(project)) {
execute(test);
}
while (list.hasMoreElements()) {
JUnitTest test = (JUnitTest)list.nextElement();
if ( test.shouldRun(project)) {
execute(test);
}
} finally {
//@todo here we should run test aggregation (SBa)
}
}

protected void execute(JUnitTest test) throws BuildException {
// set the default values if not specified
//@todo should be moved to the test class (?) (SBa)
//@todo should be moved to the test class instead.
if (test.getTodir() == null) {
test.setTodir(project.resolveFile("."));
}
@@ -288,7 +281,7 @@ public class JUnitTask extends Task {
boolean wasKilled = false;
if (!test.getFork()) {
exitValue = executeInVM(test);
} else {
} else {
ExecuteWatchdog watchdog = createWatchdog();
exitValue = executeAsForked(test, watchdog);
// null watchdog means no timeout, you'd better not check with null
@@ -459,10 +452,9 @@ public class JUnitTask extends Task {

private FormatterElement[] mergeFormatters(JUnitTest test){
Vector feVector = (Vector)formatters.clone();
FormatterElement[] fes = test.getFormatters();
FormatterElement[] feArray = new FormatterElement[feVector.size() + fes.length];
test.addFormattersTo(feVector);
FormatterElement[] feArray = new FormatterElement[feVector.size()];
feVector.copyInto(feArray);
System.arraycopy(fes, 0, feArray, feVector.size(), fes.length);
return feArray;
}



+ 14
- 1
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java View File

@@ -73,7 +73,10 @@ public class JUnitTest extends BaseTest {
/** the name of the result file */
private String outfile = null;

// @todo this is duplicating TestResult information. Only the time is not
// part of the result. So we'd better derive a new class from TestResult
// and deal with it. (SB)
private long runs, failures, errors;
private long runTime;

@@ -139,4 +142,14 @@ public class JUnitTest extends BaseTest {
formatters.copyInto(fes);
return fes;
}

/**
* Convenient method to add formatters to a vector
*/
void addFormattersTo(Vector v){
final int count = formatters.size();
for (int i = 0; i < count; i++){
v.addElement( formatters.elementAt(i) );
}
}
}

+ 17
- 16
src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java View File

@@ -74,7 +74,7 @@ import junit.framework.TestCase;
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
*/

public class XMLJUnitResultFormatter implements JUnitResultFormatter {
public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants {

private static DocumentBuilder getDocumentBuilder() {
try {
@@ -88,7 +88,8 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter {
/**
* Formatter for timings.
*/
private NumberFormat nf = NumberFormat.getInstance();
private NumberFormat nf = NumberFormat.getInstance(Locale.US);

/**
* The XML document.
*/
@@ -121,19 +122,19 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter {
*/
public void startTestSuite(JUnitTest suite) {
doc = getDocumentBuilder().newDocument();
rootElement = doc.createElement("testsuite");
rootElement.setAttribute("name", suite.getName());
rootElement = doc.createElement(TESTSUITE);
rootElement.setAttribute(ATTR_NAME, suite.getName());
}

/**
* The whole testsuite ended.
*/
public void endTestSuite(JUnitTest suite) throws BuildException {
rootElement.setAttribute("tests", ""+suite.runCount());
rootElement.setAttribute("failures", ""+suite.failureCount());
rootElement.setAttribute("errors", ""+suite.errorCount());
rootElement.setAttribute("time",
nf.format(suite.getRunTime()/1000.0)+" sec");
rootElement.setAttribute(ATTR_TESTS, ""+suite.runCount());
rootElement.setAttribute(ATTR_FAILURES, ""+suite.failureCount());
rootElement.setAttribute(ATTR_ERRORS, ""+suite.errorCount());
rootElement.setAttribute(ATTR_TIME,
nf.format(suite.getRunTime()/1000.0));
if (out != null) {
Writer wri = null;
try {
@@ -162,8 +163,8 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter {
*/
public void startTest(Test t) {
lastTestStart = System.currentTimeMillis();
currentTest = doc.createElement("testcase");
currentTest.setAttribute("name", ((TestCase) t).name());
currentTest = doc.createElement(TESTCASE);
currentTest.setAttribute(ATTR_NAME, ((TestCase) t).name());
rootElement.appendChild(currentTest);
}

@@ -173,7 +174,7 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter {
* <p>A Test is finished.
*/
public void endTest(Test test) {
currentTest.setAttribute("time",
currentTest.setAttribute(ATTR_TIME,
nf.format((System.currentTimeMillis()-lastTestStart)
/ 1000.0));
}
@@ -184,7 +185,7 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter {
* <p>A Test failed.
*/
public void addFailure(Test test, Throwable t) {
formatError("failure", test, t);
formatError(FAILURE, test, t);
}

/**
@@ -202,7 +203,7 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter {
* <p>An error occured while running the test.
*/
public void addError(Test test, Throwable t) {
formatError("error", test, t);
formatError(ERROR, test, t);
}

private void formatError(String type, Test test, Throwable t) {
@@ -219,9 +220,9 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter {

String message = t.getMessage();
if (message != null && message.length() > 0) {
nested.setAttribute("message", t.getMessage());
nested.setAttribute(ATTR_MESSAGE, t.getMessage());
}
nested.setAttribute("type", t.getClass().getName());
nested.setAttribute(ATTR_TYPE, t.getClass().getName());

StringWriter swr = new StringWriter();
t.printStackTrace(new PrintWriter(swr, true));


Loading…
Cancel
Save