Browse Source

Patch from Scott Stirling <scottstirling@rcn.com> that allows

stack trace filtering for formatters. It will filter out
those unneeded frame from Ant and JUnit so the stack will
be much more readable.

nb: Looks like the JUnit task need serious refactoring since we have
been adding feature incrementally. It starts to be a real mess,
I can barely read my own code :-(


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270099 13f79535-47bb-0310-9956-ffa450edef68
master
Stephane Bailliez 23 years ago
parent
commit
c58f8e6e7a
7 changed files with 122 additions and 20 deletions
  1. +15
    -6
      src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java
  2. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/BatchTest.java
  3. +19
    -3
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
  4. +3
    -2
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
  5. +80
    -5
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
  6. +2
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java
  7. +2
    -3
      src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java

+ 15
- 6
src/main/org/apache/tools/ant/taskdefs/optional/junit/BaseTest.java View File

@@ -60,12 +60,13 @@ import java.util.Vector;
/**
* Baseclass for BatchTest and JUnitTest.
*
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
* @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a>
*/
public abstract class BaseTest {
protected boolean haltOnError = false;
protected boolean haltOnFail = false;
protected boolean filtertrace = true;
protected boolean fork = false;
protected String ifProperty = null;
protected String unlessProperty = null;
@@ -76,6 +77,14 @@ public abstract class BaseTest {
protected String failureProperty;
protected String errorProperty;

public void setFiltertrace(boolean value) {
filtertrace = value;
}

public boolean getFiltertrace() {
return filtertrace;
}
public void setFork(boolean value) {
fork = value;
}
@@ -116,12 +125,12 @@ public abstract class BaseTest {
* Sets the destination directory.
*/
public void setTodir(File destDir) {
this.destDir = destDir;
this.destDir = destDir;
}

/**
* @return the destination directory as an absolute path if it exists
* otherwise return <tt>null</tt>
* otherwise return <tt>null</tt>
*/
public String getTodir(){
if (destDir != null){
@@ -133,15 +142,15 @@ public abstract class BaseTest {
public java.lang.String getFailureProperty() {
return failureProperty;
}
public void setFailureProperty(String failureProperty) {
this.failureProperty = failureProperty;
}
public java.lang.String getErrorProperty() {
return errorProperty;
}
public void setErrorProperty(String errorProperty) {
this.errorProperty = errorProperty;
}


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

@@ -199,6 +199,7 @@ public final class BatchTest extends BaseTest {
test.setName(classname);
test.setHaltonerror(this.haltOnError);
test.setHaltonfailure(this.haltOnFail);
test.setFiltertrace(this.filtertrace);
test.setFork(this.fork);
test.setIf(this.ifProperty);
test.setUnless(this.unlessProperty);


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

@@ -155,7 +155,23 @@ public class JUnitTask extends Task {
private Integer timeout = null;
private boolean summary = false;
private String summaryValue = "";
private boolean filtertrace = true;
private JUnitTestRunner runner = null;
/**
* Tells this task whether to smartly filter the stack frames of JUnit testcase
* errors and failures before reporting them. This property is applied on all
* BatchTest (batchtest) and JUnitTest (test) however it can possibly be
* overridden by their own properties.
* @param value <tt>false</tt> if it should not filter, otherwise <tt>true<tt>
*/
public void setFiltertrace(boolean value) {
Enumeration enum = allTests();
while (enum.hasMoreElements()) {
BaseTest test = (BaseTest) enum.nextElement();
test.setFiltertrace(value);
}
}
/**
* Tells this task to halt when there is an error in a test.
@@ -361,7 +377,7 @@ public class JUnitTask extends Task {
/**
* Adds the jars or directories containing Ant, this task and
* JUnit to the classpath - this should make the forked JVM work
* without having to specify the directly.
* without having to specify them directly.
*/
public void init() {
addClasspathEntry("/junit/framework/TestCase.class");
@@ -447,6 +463,7 @@ public class JUnitTask extends Task {

cmd.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
cmd.createArgument().setValue(test.getName());
cmd.createArgument().setValue("filtertrace=" + test.getFiltertrace());
cmd.createArgument().setValue("haltOnError=" + test.getHaltonerror());
cmd.createArgument().setValue("haltOnFailure=" + test.getHaltonfailure());
if (summary) {
@@ -555,8 +572,7 @@ public class JUnitTask extends Task {
// will cause trouble in JDK 1.1 if omitted
cl.addSystemPackageRoot("org.apache.tools.ant");
}
runner = new JUnitTestRunner(test, test.getHaltonerror(), test.getHaltonfailure(), cl);

runner = new JUnitTestRunner(test, test.getHaltonerror(), test.getFiltertrace(), test.getHaltonfailure(), cl);
if (summary) {
log("Running " + test.getName(), Project.MSG_INFO);



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

@@ -100,10 +100,11 @@ public class JUnitTest extends BaseTest {
this.name = name;
}

public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure) {
public JUnitTest(String name, boolean haltOnError, boolean haltOnFailure, boolean filtertrace) {
this.name = name;
this.haltOnError = haltOnError;
this.haltOnFail = haltOnFail;
this.haltOnFail = haltOnFailure;
this.filtertrace = filtertrace;
}

/**


+ 80
- 5
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java View File

@@ -64,7 +64,11 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import junit.framework.AssertionFailedError;
import java.lang.reflect.Method;
import java.io.BufferedReader;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.FileInputStream;
@@ -121,6 +125,24 @@ public class JUnitTestRunner implements TestListener {
*/
private TestResult res;

/**
* Do we filter junit.*.* stack frames out of failure and error exceptions.
*/
private static boolean filtertrace = true;
private final static String[] DEFAULT_TRACE_FILTERS = new String[] {
"junit.framework.TestCase",
"junit.framework.TestResult",
"junit.framework.TestSuite",
"junit.framework.Assert.", // don't filter AssertionFailure
"junit.swingui.TestRunner",
"junit.awtui.TestRunner",
"junit.textui.TestRunner",
"java.lang.reflect.Method.invoke(",
"org.apache.tools.ant."
};

/**
* Do we stop on errors.
*/
@@ -161,16 +183,18 @@ public class JUnitTestRunner implements TestListener {
* Constructor for fork=true or when the user hasn't specified a
* classpath.
*/
public JUnitTestRunner(JUnitTest test, boolean haltOnError,
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace,
boolean haltOnFailure) {
this(test, haltOnError, haltOnFailure, null);
this(test, haltOnError, filtertrace, haltOnFailure, null);
}

/**
* Constructor to use when the user has specified a classpath.
*/
public JUnitTestRunner(JUnitTest test, boolean haltOnError,
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace,
boolean haltOnFailure, ClassLoader loader) {
//JUnitTestRunner.filtertrace = filtertrace;
this.filtertrace = filtertrace;
this.junitTest = test;
this.haltOnError = haltOnError;
this.haltOnFailure = haltOnFailure;
@@ -378,6 +402,7 @@ public class JUnitTestRunner implements TestListener {
boolean exitAtEnd = true;
boolean haltError = false;
boolean haltFail = false;
boolean stackfilter = true;
Properties props = new Properties();

if (args.length == 0) {
@@ -390,6 +415,8 @@ public class JUnitTestRunner implements TestListener {
haltError = Project.toBoolean(args[i].substring(12));
} else if (args[i].startsWith("haltOnFailure=")) {
haltFail = Project.toBoolean(args[i].substring(14));
} else if (args[i].startsWith("filtertrace=")) {
stackfilter = Project.toBoolean(args[i].substring(12));
} else if (args[i].startsWith("formatter=")) {
try {
createAndStoreFormatter(args[i].substring(10));
@@ -405,7 +432,7 @@ public class JUnitTestRunner implements TestListener {
}
JUnitTest t = new JUnitTest(args[0]);
// Add/overlay system properties on the properties from the Ant project
Hashtable p = System.getProperties();
for (Enumeration enum = p.keys(); enum.hasMoreElements(); ) {
@@ -414,7 +441,7 @@ public class JUnitTestRunner implements TestListener {
}
t.setProperties(props);

JUnitTestRunner runner = new JUnitTestRunner(t, haltError, haltFail);
JUnitTestRunner runner = new JUnitTestRunner(t, haltError, stackfilter, haltFail);
transferFormatters(runner);
runner.run();
System.exit(runner.getRetCode());
@@ -443,5 +470,53 @@ public class JUnitTestRunner implements TestListener {
}
fromCmdLine.addElement(fe.createFormatter());
}
/**
* Returns a filtered stack trace.
* This is ripped out of junit.runner.BaseTestRunner.
* Scott M. Stirling.
*/
public static String getFilteredTrace(Throwable t) {
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
t.printStackTrace(writer);
StringBuffer buffer = stringWriter.getBuffer();
String trace = buffer.toString();
return JUnitTestRunner.filterStack(trace);
}

/**
* Filters stack frames from internal JUnit and Ant classes
*/
public static String filterStack(String stack) {
if (!filtertrace) {
return stack;
}
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
StringReader sr = new StringReader(stack);
BufferedReader br = new BufferedReader(sr);

String line;
try {
while ((line = br.readLine()) != null) {
if (!filterLine(line)) {
pw.println(line);
}
}
} catch (Exception IOException) {
return stack; // return the stack unfiltered
}
return sw.toString();
}

private static boolean filterLine(String line) {
for (int i = 0; i < DEFAULT_TRACE_FILTERS.length; i++) {
if (line.indexOf(DEFAULT_TRACE_FILTERS[i]) > 0) {
return true;
}
}
return false;
}
} // JUnitTestRunner

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

@@ -248,7 +248,8 @@ public class PlainJUnitResultFormatter implements JUnitResultFormatter {

wri.println(type);
wri.println(t.getMessage());
t.printStackTrace(wri);
String strace = JUnitTestRunner.getFilteredTrace(t);
wri.print(strace);
wri.println("");
}
}


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

@@ -261,9 +261,8 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan
}
nested.setAttribute(ATTR_TYPE, t.getClass().getName());

StringWriter swr = new StringWriter();
t.printStackTrace(new PrintWriter(swr, true));
Text trace = doc.createTextNode(swr.toString());
String strace = JUnitTestRunner.getFilteredTrace(t);
Text trace = doc.createTextNode(strace);
nested.appendChild(trace);
}



Loading…
Cancel
Save