Browse Source

JUnit4 tests marked @Ignore do not appear in XML output. PR 43969

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@1452674 13f79535-47bb-0310-9956-ffa450edef68
master
Antoine Levy-Lambert 12 years ago
parent
commit
3930d3e938
25 changed files with 736 additions and 80 deletions
  1. +1
    -0
      CONTRIBUTORS
  2. +3
    -0
      WHATSNEW
  3. +4
    -0
      contributors.xml
  4. +1
    -1
      lib/libraries.properties
  5. BIN
      lib/optional/junit-4.11.jar
  6. BIN
      lib/optional/junit-4.8.1.jar
  7. +1
    -1
      release.sh
  8. +45
    -0
      src/etc/testcases/taskdefs/optional/junit.xml
  9. +43
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java
  10. +89
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/CustomJUnit4TestAdapterCache.java
  11. +53
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestListener.java
  12. +99
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestResult.java
  13. +4
    -45
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter.java
  14. +1
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
  15. +29
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
  16. +12
    -10
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
  17. +42
    -1
      src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java
  18. +2
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
  19. +35
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/TestIgnored.java
  20. +74
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/TestListenerWrapper.java
  21. +2
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLConstants.java
  22. +101
    -18
      src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java
  23. +1
    -0
      src/tests/antunit/taskdefs/optional/junit/junit-test.xml
  24. +38
    -1
      src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java
  25. +56
    -0
      src/tests/junit/org/example/junit/Junit4Skippable.java

+ 1
- 0
CONTRIBUTORS View File

@@ -234,6 +234,7 @@ Matthew Inger
Matthew Kuperus Heun
Matthew Watson
Michael Bayne
Michael Clarke
Michael Davey
Michael J. Sikorsky
Michael McCallum


+ 3
- 0
WHATSNEW View File

@@ -87,6 +87,9 @@ Fixed bugs:
set to ANSI_X3.4-1968.
Bugzilla Report 54606

* JUnit4 tests marked @Ignore do not appear in XML output
Bugzilla Report 43969

Other changes:
--------------



+ 4
- 0
contributors.xml View File

@@ -957,6 +957,10 @@
<first>Michael</first>
<last>Bayne</last>
</name>
<name>
<first>Michael</first>
<last>Clarke</last>
</name>
<name>
<first>Michael</first>
<last>Davey</last>


+ 1
- 1
lib/libraries.properties View File

@@ -45,7 +45,7 @@ jasper-compiler.version=4.1.36
jasper-runtime.version=${jasper-compiler.version}
jdepend.version=2.9.1
jruby.version=0.9.8
junit.version=4.8.1
junit.version=4.11
jsch.version=0.1.42
jython.version=2.1
#log4j 1.2.15 requires JMS and a few other Sun jars that are not in the m2 repo


BIN
lib/optional/junit-4.11.jar View File


BIN
lib/optional/junit-4.8.1.jar View File


+ 1
- 1
release.sh View File

@@ -17,7 +17,7 @@
# this is a first attempt to document the build of the distribution
# paths are hard-coded and obviously this is for a Cygwin/Windows combo
#######################################################################
rm -rf bootstrap build dist distribution
rm -rf bootstrap build dist distribution java-repository
unset ANT_HOME
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;


+ 45
- 0
src/etc/testcases/taskdefs/optional/junit.xml View File

@@ -276,4 +276,49 @@
</junit>
</target>

<!-- Junit4 Ignore and Assume for skipping tests -->
<target name="testSkippableTests">
<mkdir dir="out"/>
<junit fork="true">
<classpath refid="test"/>
<formatter type="xml"/>
<classpath refid="test"/>
<batchtest todir="out">
<fileset dir="../../../../tests/junit">
<include
name="org/example/junit/Junit4Skippable.java"/>
<!-- tests remove out-dir on tearDown -->
</fileset>
</batchtest>
</junit>
</target>

<target name="testTestMethods" >
<echo file="${tmp.dir}/T1.java">public class T1 extends
junit.framework.TestCase {
public void testOK() {}
public void testBad() {throw new RuntimeException("failed");}
}</echo>
<echo file="${tmp.dir}/T2.java">
import org.junit.Test;
public class T2 {
@Test
public void ok() {}
@Test
public void bad() {
throw new RuntimeException("failed");}
}</echo>
<javac srcdir="${tmp.dir}" destdir="${tmp.dir}" includes="T1.java,T2.java" source="5">

</javac>
<junit fork="false" printsummary="true" haltonerror="true">
<classpath>
<pathelement location="${tmp.dir}" />
<path refid="test" />
</classpath>
<test name="T1" methods="testOK" />
<test name="T2" methods="ok" />
</junit>
</target>

</project>

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

@@ -25,11 +25,13 @@ import java.io.StringWriter;
import java.text.NumberFormat;

import junit.framework.AssertionFailedError;
import junit.framework.JUnit4TestCaseFacade;
import junit.framework.Test;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.StringUtils;
import org.junit.Ignore;

/**
* Prints plain text output of the test to a specified Writer.
@@ -38,7 +40,7 @@ import org.apache.tools.ant.util.StringUtils;
* @see FormatterElement
* @see PlainJUnitResultFormatter
*/
public class BriefJUnitResultFormatter implements JUnitResultFormatter {
public class BriefJUnitResultFormatter implements JUnitResultFormatter, IgnoredTestListener {

private static final double ONE_SECOND = 1000.0;

@@ -141,6 +143,8 @@ public class BriefJUnitResultFormatter implements JUnitResultFormatter {
sb.append(suite.failureCount());
sb.append(", Errors: ");
sb.append(suite.errorCount());
sb.append(", Skipped: ");
sb.append(suite.skipCount());
sb.append(", Time elapsed: ");
sb.append(numberFormat.format(suite.getRunTime() / ONE_SECOND));
sb.append(" sec");
@@ -267,4 +271,42 @@ public class BriefJUnitResultFormatter implements JUnitResultFormatter {
throw new BuildException(ex);
}
}


@Override
public void testIgnored(Test test) {
String message = null;
if (test instanceof JUnit4TestCaseFacade) {
JUnit4TestCaseFacade facade = (JUnit4TestCaseFacade) test;
Ignore annotation = facade.getDescription().getAnnotation(Ignore.class);
if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) {
message = annotation.value();
}
}
formatSkip(test, message);
}


public void formatSkip(Test test, String message) {
if (test != null) {
endTest(test);
}

try {
resultWriter.write(formatTest(test) + "SKIPPED");
if (message != null) {
resultWriter.write(": ");
resultWriter.write(message);
}
resultWriter.newLine();
} catch (IOException ex) {
throw new BuildException(ex);
}

}

@Override
public void testAssumptionFailure(Test test, Throwable cause) {
formatSkip(test, cause.getMessage());
}
}

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

@@ -0,0 +1,89 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.junit;

import junit.framework.JUnit4TestAdapter;
import junit.framework.JUnit4TestAdapterCache;
import junit.framework.TestResult;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;

/**
* Provides a custom implementation of the notifier for a Junit4TestAdapter
* so that skipped and ignored tests can be reported to the existing
* <tt>TestListener</tt>s.
*
*/
public class CustomJUnit4TestAdapterCache extends JUnit4TestAdapterCache {

private static final CustomJUnit4TestAdapterCache INSTANCE = new CustomJUnit4TestAdapterCache();

public static CustomJUnit4TestAdapterCache getInstance() {
return INSTANCE;
}

private CustomJUnit4TestAdapterCache() {
super();
}

public RunNotifier getNotifier(final TestResult result, final JUnit4TestAdapter adapter) {
return getNotifier(result);
}

public RunNotifier getNotifier(final TestResult result) {

final IgnoredTestResult resultWrapper = (IgnoredTestResult) result;

RunNotifier notifier = new RunNotifier();
notifier.addListener(new RunListener() {
@Override
public void testFailure(Failure failure) throws Exception {
result.addError(asTest(failure.getDescription()), failure.getException());
}

@Override
public void testFinished(Description description) throws Exception {
result.endTest(asTest(description));
}

@Override
public void testStarted(Description description) throws Exception {
result.startTest(asTest(description));
}

@Override
public void testIgnored(Description description) throws Exception {
if (resultWrapper != null) {
resultWrapper.testIgnored(asTest(description));
}
}

@Override
public void testAssumptionFailure(Failure failure) {
if (resultWrapper != null) {
resultWrapper.testAssumptionFailure(asTest(failure.getDescription()), failure.getException());
}
}
});

return notifier;
}
}

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

@@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.junit;

import junit.framework.Test;
import junit.framework.TestListener;
import org.junit.runner.notification.Failure;

/**
* Provides the functionality for TestListeners to be able to be notified of
* the necessary Junit4 events for test being ignored (@Ignore annotation)
* or skipped (Assume failures). Tests written in Junit4 will report against
* the methods in this interface alongside the methods in the existing TestListener
*/
public interface IgnoredTestListener extends TestListener {

/**
* Reports when a test has been marked with the @Ignore annotation. The parameter
* should normally be typed to Junit's {@link junit.framework.JUnit4TestCaseFacade}
* so implementing classes should be able to get the details of the ignore by casting
* the argument and retrieving the descriptor from the test.
* @param test
*/
void testIgnored(Test test);

/**
* Receive a report that a test has failed an assumption. Within JUnit4
* this is normally treated as a test being skipped, although how any
* listener handles this is up to that specific listener.<br />
* <b>Note:</b> Tests that throw assumption failures will still report
* the endTest method, which may differ from how the addError and addFailure
* methods work, it's up for any implementing classes to handle this.
* @param test the details of the test and failure that have triggered this report.
* @param exception the AssumptionViolatedException thrown from the current assumption failure.
*/
void testAssumptionFailure(Test test, Throwable exception);
}

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

@@ -0,0 +1,99 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.junit;

import java.util.ArrayList;
import java.util.List;

import junit.framework.Test;
import junit.framework.TestListener;
import junit.framework.TestResult;

/**
* Records ignored and skipped tests reported as part of the execution of
* JUnit 4 tests.
*
*/
public class IgnoredTestResult extends TestResult {


private List<IgnoredTestListener> listeners = new ArrayList<IgnoredTestListener>();
private List<TestIgnored> ignored = new ArrayList<TestIgnored>();
private List<TestIgnored> skipped = new ArrayList<TestIgnored>();

public IgnoredTestResult() {
super();
}


public synchronized void addListener(TestListener listener) {
if (listener instanceof IgnoredTestListener) {
listeners.add((IgnoredTestListener)listener);
}
super.addListener(listener);
}

public synchronized void removeListener(TestListener listener) {
if (listener instanceof IgnoredTestListener) {
listeners.remove(listener);
}
super.removeListener(listener);
}

/**
* Record a test as having been ignored, normally by the @Ignore annotation.
* @param test the test that was ignored.
* @throws Exception is the listener thrown an exception on handling the notification.
*/
public synchronized void testIgnored(Test test) throws Exception {
ignored.add(new TestIgnored(test));
for (IgnoredTestListener listener : listeners) {
listener.testIgnored(test);
}
}

/**
* Report how many tests were ignored.
* @return the number of tests reported as ignored during the current execution.
*/
public long ignoredCount() {
return ignored.size();
}

/**
* Records a test as having an assumption failure so JUnit will no longer be executing it.
* Under normal circumstances this would be counted as a skipped test.
* @param test the test to record
* @param cause the details of the test and assumption failure.
*/
public void testAssumptionFailure(Test test, Throwable cause) {
skipped.add(new TestIgnored(test));
for (IgnoredTestListener listener : listeners) {
listener.testAssumptionFailure(test, cause);
}
}

/**
* Report how many tests has assumption failures.
* @return the number of tests that reported assumption failures during the current execution.
*/
public long skippedCount() {
return skipped.size();
}
}

+ 4
- 45
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter.java View File

@@ -20,20 +20,16 @@ package org.apache.tools.ant.taskdefs.optional.junit;

import java.util.Iterator;
import java.util.List;
import junit.framework.JUnit4TestAdapterCache;
import junit.framework.Test;
import junit.framework.TestResult;
import org.junit.runner.Description;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;

/**
* Adapter between JUnit 3.8.x API and JUnit 4.x API for execution of tests
* and listening of events (test start, test finish, test failure).
* and listening of events (test start, test finish, test failure, test skipped).
* The constructor is passed a JUnit 4 test class and a list of name of methods
* in it that should be executed. Method {@link #run run(TestResult)} executes
* the given JUnit-4-style test methods and notifies the given {@code TestResult}
@@ -46,7 +42,7 @@ public class JUnit4TestMethodAdapter implements Test {
private final Class testClass;
private final String[] methodNames;
private final Runner runner;
private final Cache cache;
private final CustomJUnit4TestAdapterCache cache;

/**
* Creates a new adapter for the given class and a method within the class.
@@ -75,7 +71,7 @@ public class JUnit4TestMethodAdapter implements Test {
}
this.testClass = testClass;
this.methodNames = (String[]) methodNames.clone();
this.cache = Cache.instance;
this.cache = CustomJUnit4TestAdapterCache.getInstance();

// Warning: If 'testClass' is an old-style (pre-JUnit-4) class,
// then all its test methods will be executed by the returned runner!
@@ -104,7 +100,7 @@ public class JUnit4TestMethodAdapter implements Test {
public Class getTestClass() {
return testClass;
}
public void run(final TestResult result) {
runner.run(cache.getNotifier(result));
}
@@ -188,42 +184,5 @@ public class JUnit4TestMethodAdapter implements Test {

}

/**
* Effectively a copy of {@code JUnit4TestAdapterCache}, except that its
* method {@code getNotifier()} does not require an argument
* of type {@code JUnit4TestAdapter}.
*/
private static final class Cache extends JUnit4TestAdapterCache {
private static final long serialVersionUID = 8454901854293461610L;

private static final Cache instance = new Cache();

public static JUnit4TestAdapterCache getDefault() {
return instance;
}
public RunNotifier getNotifier(final TestResult result) {
RunNotifier notifier = new RunNotifier();
notifier.addListener(new RunListener() {
public void testFailure(Failure failure) throws Exception {
result.addError(asTest(failure.getDescription()),
failure.getException());
}

public void testFinished(Description description)
throws Exception {
result.endTest(asTest(description));
}

public void testStarted(Description description)
throws Exception {
result.startTest(asTest(description));
}
});
return notifier;
}

}

}

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

@@ -1645,7 +1645,7 @@ public class JUnitTask extends Task {
classLoader.setThreadContextLoader();
}

test.setCounts(1, 0, 1);
test.setCounts(1, 0, 1, 0);
test.setProperties(getProject().getProperties());
for (int i = 0; i < feArray.length; i++) {
FormatterElement fe = feArray[i];


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

@@ -62,6 +62,11 @@ public class JUnitTest extends BaseTest implements Cloneable {
// part of the result. So we'd better derive a new class from TestResult
// and deal with it. (SB)
private long runs, failures, errors;
/**
@since Ant 1.9.0
*/
private long skips;

private long runTime;

// Snapshot of the system properties
@@ -352,16 +357,31 @@ public class JUnitTest extends BaseTest implements Cloneable {
}

/**
* Set the number of runs, failures and errors.
* Set the number of runs, failures, errors, and skipped tests.
* @param runs the number of runs.
* @param failures the number of failures.
* @param errors the number of errors.
* Kept for backward compatibility with Ant 1.8.4
*/
public void setCounts(long runs, long failures, long errors) {
this.runs = runs;
this.failures = failures;
this.errors = errors;
}
/**
* Set the number of runs, failures, errors, and skipped tests.
* @param runs the number of runs.
* @param failures the number of failures.
* @param errors the number of errors.
* @param skips the number of skipped tests.
* @since Ant 1.9.0
*/
public void setCounts(long runs, long failures, long errors, long skips) {
this.runs = runs;
this.failures = failures;
this.errors = errors;
this.skips = skips;
}

/**
* Set the runtime.
@@ -395,6 +415,14 @@ public class JUnitTest extends BaseTest implements Cloneable {
return errors;
}

/**
* Get the number of skipped tests.
* @return the number of skipped tests.
*/
public long skipCount() {
return skips;
}

/**
* Get the run time.
* @return the run time in milliseconds.


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

@@ -36,6 +36,7 @@ import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
import junit.framework.AssertionFailedError;
import junit.framework.JUnit4TestAdapterCache;
import junit.framework.Test;
import junit.framework.TestFailure;
import junit.framework.TestListener;
@@ -76,7 +77,7 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
/**
* Collects TestResults.
*/
private TestResult res;
private IgnoredTestResult res;

/**
* Do we filter junit.*.* stack frames out of failure and error exceptions.
@@ -289,6 +290,7 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
boolean filtertrace, boolean haltOnFailure,
boolean showOutput, boolean logTestListenerEvents,
ClassLoader loader) {
super();
JUnitTestRunner.filtertrace = filtertrace; // XXX clumsy, should use instance field somehow
this.junitTest = test;
this.haltOnError = haltOnError;
@@ -350,7 +352,7 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
* Run the test.
*/
public void run() {
res = new TestResult();
res = new IgnoredTestResult();
res.addListener(wrapListener(this));
final int size = formatters.size();
for (int i = 0; i < size; i++) {
@@ -468,8 +470,8 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
formalParams = new Class[] {Class.class, String[].class};
actualParams = new Object[] {testClass, methods};
} else {
formalParams = new Class[] {Class.class};
actualParams = new Object[] {testClass};
formalParams = new Class[] {Class.class, JUnit4TestAdapterCache.class};
actualParams = new Object[] {testClass, CustomJUnit4TestAdapterCache.getInstance()};
}
suite =
(Test) junit4TestAdapterClass
@@ -512,7 +514,7 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
((TestListener) formatters.elementAt(i))
.addError(null, exception);
}
junitTest.setCounts(1, 0, 1);
junitTest.setCounts(1, 0, 1, 0);
junitTest.setRunTime(0);
} else {
try {
@@ -522,10 +524,10 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
if (junit4 ||
suite.getClass().getName().equals(JUNIT_4_TEST_ADAPTER)) {
int[] cnts = findJUnit4FailureErrorCount(res);
junitTest.setCounts(res.runCount(), cnts[0], cnts[1]);
junitTest.setCounts(res.runCount() + res.ignoredCount(), cnts[0], cnts[1], res.ignoredCount() + res.skippedCount());
} else {
junitTest.setCounts(res.runCount(), res.failureCount(),
res.errorCount());
junitTest.setCounts(res.runCount() + res.ignoredCount(), res.failureCount(),
res.errorCount(), res.ignoredCount() + res.skippedCount());
}
junitTest.setRunTime(System.currentTimeMillis() - start);
}
@@ -1101,8 +1103,8 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR
*
* @since Ant 1.7
*/
private TestListener wrapListener(final TestListener testListener) {
return new TestListener() {
private TestListenerWrapper wrapListener(final TestListener testListener) {
return new TestListenerWrapper(testListener) {
public void addError(Test test, Throwable t) {
if (junit4 && t instanceof AssertionFailedError) {
// JUnit 4 does not distinguish between errors and failures


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

@@ -26,11 +26,14 @@ import java.text.NumberFormat;
import java.util.Hashtable;

import junit.framework.AssertionFailedError;
import junit.framework.JUnit4TestCaseFacade;
import junit.framework.Test;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.StringUtils;
import org.junit.Ignore;
import org.junit.runner.notification.Failure;


/**
@@ -38,7 +41,7 @@ import org.apache.tools.ant.util.StringUtils;
*
*/

public class PlainJUnitResultFormatter implements JUnitResultFormatter {
public class PlainJUnitResultFormatter implements JUnitResultFormatter, IgnoredTestListener {

private static final double ONE_SECOND = 1000.0;

@@ -123,6 +126,8 @@ public class PlainJUnitResultFormatter implements JUnitResultFormatter {
sb.append(suite.failureCount());
sb.append(", Errors: ");
sb.append(suite.errorCount());
sb.append(", Skipped: ");
sb.append(suite.skipCount());
sb.append(", Time elapsed: ");
sb.append(nf.format(suite.getRunTime() / ONE_SECOND));
sb.append(" sec");
@@ -258,4 +263,40 @@ public class PlainJUnitResultFormatter implements JUnitResultFormatter {
}
}

@Override
public void testIgnored(Test test) {
String message = null;
if (test instanceof JUnit4TestCaseFacade) {
JUnit4TestCaseFacade facade = (JUnit4TestCaseFacade) test;
Ignore annotation = facade.getDescription().getAnnotation(Ignore.class);
if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) {
message = annotation.value();
}
}
formatSkip(test, message);
}


public void formatSkip(Test test, String message) {
if (test != null) {
endTest(test);
}

try {
wri.write("\tSKIPPED");
if (message != null) {
wri.write(": ");
wri.write(message);
}
wri.newLine();
} catch (IOException ex) {
throw new BuildException(ex);
}

}

@Override
public void testAssumptionFailure(Test test, Throwable throwable) {
formatSkip(test, throwable.getMessage());
}
} // PlainJUnitResultFormatter

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

@@ -144,6 +144,8 @@ public class SummaryJUnitResultFormatter
sb.append(suite.failureCount());
sb.append(", Errors: ");
sb.append(suite.errorCount());
sb.append(", Skipped: ");
sb.append(suite.skipCount());
sb.append(", Time elapsed: ");
sb.append(nf.format(suite.getRunTime() / ONE_SECOND));
sb.append(" sec");


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

@@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.junit;

import junit.framework.Test;

public class TestIgnored {

private Test test;

public TestIgnored(Test test) {
this.test = test;
}

public Test getTest() {
return test;
}

}

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

@@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.junit;

import junit.framework.AssertionFailedError;
import junit.framework.JUnit4TestAdapterCache;
import junit.framework.Test;
import junit.framework.TestListener;

import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;

public class TestListenerWrapper implements TestListener, IgnoredTestListener {

private TestListener wrapped;

public TestListenerWrapper(TestListener listener) {
super();
wrapped = listener;
}

@Override
public void addError(Test test, Throwable throwable) {
wrapped.addError(test, throwable);
}

@Override
public void addFailure(Test test, AssertionFailedError assertionFailedError) {
wrapped.addFailure(test, assertionFailedError);
}

@Override
public void endTest(Test test) {
wrapped.endTest(test);
}

@Override
public void startTest(Test test) {
wrapped.startTest(test);
}

@Override
public void testIgnored(Test test) {
if (wrapped instanceof IgnoredTestListener) {
((IgnoredTestListener)wrapped).testIgnored(test);
}
}

@Override
public void testAssumptionFailure(Test test, Throwable throwable) {
if (wrapped instanceof IgnoredTestListener) {
((IgnoredTestListener)wrapped).testAssumptionFailure(test, throwable);
}
}


}

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

@@ -106,6 +106,8 @@ public interface XMLConstants {
/** tests attribute for testsuite elements */
String ATTR_TESTS = "tests";

String ATTR_SKIPPED = "skipped";

/** type attribute for failure and error elements */
String ATTR_TYPE = "type";



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

@@ -23,20 +23,26 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Date;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import junit.framework.AssertionFailedError;
import junit.framework.JUnit4TestCaseFacade;
import junit.framework.Test;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.util.DOMElementWriter;
import org.apache.tools.ant.util.DateUtils;
import org.apache.tools.ant.util.FileUtils;
import org.junit.Ignore;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
@@ -48,7 +54,7 @@ import org.w3c.dom.Text;
* @see FormatterElement
*/

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

private static final double ONE_SECOND = 1000.0;

@@ -73,16 +79,29 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan
private Element rootElement;
/**
* Element for the current test.
*
* The keying of this map is a bit of a hack: tests are keyed by caseName(className) since
* the Test we get for Test-start isn't the same as the Test we get during test-assumption-fail,
* so we can't easily match Test objects without manually iterating over all keys and checking
* individual fields.
*/
private Hashtable testElements = new Hashtable();
private Hashtable<String, Element> testElements = new Hashtable<String, Element>();
/**
* tests that failed.
*/
private Hashtable failedTests = new Hashtable();
/**
* Tests that were skipped.
*/
private Hashtable<String, Test> skippedTests = new Hashtable<String, Test>();
/**
* Tests that were ignored. See the note above about the key being a bit of a hack.
*/
private Hashtable<String, Test> ignoredTests = new Hashtable<String, Test>();
/**
* Timing helper.
*/
private Hashtable testStarts = new Hashtable();
private Hashtable<String, Long> testStarts = new Hashtable<String, Long>();
/**
* Where to write the log to.
*/
@@ -161,6 +180,7 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan
rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount());
rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount());
rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount());
rootElement.setAttribute(ATTR_SKIPPED, "" + suite.skipCount());
rootElement.setAttribute(
ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND));
if (out != null) {
@@ -193,9 +213,13 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan
* @param t the test.
*/
public void startTest(Test t) {
testStarts.put(t, new Long(System.currentTimeMillis()));
testStarts.put(createDescription(t), System.currentTimeMillis());
}

private static String createDescription(Test test) throws BuildException {
return JUnitVersionHelper.getTestCaseName(test) + "(" + JUnitVersionHelper.getTestCaseClassName(test) + ")";
}

/**
* Interface TestListener.
*
@@ -203,15 +227,16 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan
* @param test the test.
*/
public void endTest(Test test) {
String testDescription = createDescription(test);

// Fix for bug #5637 - if a junit.extensions.TestSetup is
// used and throws an exception during setUp then startTest
// would never have been called
if (!testStarts.containsKey(test)) {
if (!testStarts.containsKey(testDescription)) {
startTest(test);
}

Element currentTest = null;
if (!failedTests.containsKey(test)) {
Element currentTest;
if (!failedTests.containsKey(test) && !skippedTests.containsKey(testDescription) && !ignoredTests.containsKey(testDescription)) {
currentTest = doc.createElement(TESTCASE);
String n = JUnitVersionHelper.getTestCaseName(test);
currentTest.setAttribute(ATTR_NAME,
@@ -221,15 +246,14 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan
currentTest.setAttribute(ATTR_CLASSNAME,
JUnitVersionHelper.getTestCaseClassName(test));
rootElement.appendChild(currentTest);
testElements.put(test, currentTest);
testElements.put(createDescription(test), currentTest);
} else {
currentTest = (Element) testElements.get(test);
currentTest = testElements.get(testDescription);
}

Long l = (Long) testStarts.get(test);
Long l = testStarts.get(createDescription(test));
currentTest.setAttribute(ATTR_TIME,
"" + ((System.currentTimeMillis()
- l.longValue()) / ONE_SECOND));
"" + ((System.currentTimeMillis() - l) / ONE_SECOND));
}

/**
@@ -272,9 +296,9 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan
}

Element nested = doc.createElement(type);
Element currentTest = null;
Element currentTest;
if (test != null) {
currentTest = (Element) testElements.get(test);
currentTest = testElements.get(createDescription(test));
} else {
currentTest = rootElement;
}
@@ -298,4 +322,63 @@ public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstan
nested.appendChild(doc.createCDATASection(output));
}

@Override
public void testIgnored(Test test) {
String message = null;
if (test != null && test instanceof JUnit4TestCaseFacade) {
//try and get the message coded as part of the ignore
/*
* org.junit.runner.Description contains a getAnnotation(Class) method... but this
* wasn't in older versions of JUnit4 so we have to try and do this by reflection
*/
try {
Class<?> testClass = Class.forName(JUnitVersionHelper.getTestCaseClassName(test));
Method testMethod = testClass.getMethod(JUnitVersionHelper.getTestCaseName(test));
Ignore annotation = testMethod.getAnnotation(Ignore.class);
if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) {
message = annotation.value();
}
} catch (NoSuchMethodException e) {
// silently ignore - we'll report a skip with no message
} catch (ClassNotFoundException e) {
// silently ignore - we'll report a skip with no message
}
}
formatSkip(test, message);
if (test != null) {
ignoredTests.put(createDescription(test), test);
}
}


public void formatSkip(Test test, String message) {
if (test != null) {
endTest(test);
}

Element nested = doc.createElement("skipped");

if (message != null) {
nested.setAttribute("message", message);
}

Element currentTest;
if (test != null) {
currentTest = testElements.get(createDescription(test));
} else {
currentTest = rootElement;
}

currentTest.appendChild(nested);

}

@Override
public void testAssumptionFailure(Test test, Throwable failure) {
String message = failure.getMessage();
formatSkip(test, message);
skippedTests.put(createDescription(test), test);

}
} // XMLJUnitResultFormatter

+ 1
- 0
src/tests/antunit/taskdefs/optional/junit/junit-test.xml View File

@@ -20,6 +20,7 @@

<path id="junit">
<fileset dir="../../../../../../lib/optional" includes="junit*" />
<fileset dir="../../../../../../lib/optional" includes="hamcrest-core*" />
</path>

<macrodef name="empty-test">


+ 38
- 1
src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java View File

@@ -25,6 +25,14 @@ import java.io.IOException;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildFileTest;
import org.apache.tools.ant.util.JavaEnvUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

public class JUnitTaskTest extends BuildFileTest {

@@ -262,7 +270,7 @@ public class JUnitTaskTest extends BuildFileTest {
line);
line = reader.readLine();
assertNotNull(line);
assertTrue(line.startsWith("Tests run: 1, Failures: 0, Errors: 0, Time elapsed:"));
assertTrue(line.startsWith("Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed:"));
line = reader.readLine();
assertEquals("------------- Standard Output ---------------",
line);
@@ -296,4 +304,33 @@ public class JUnitTaskTest extends BuildFileTest {
assertEquals(search, line);
}

public void testJunit4Skip() throws Exception {
executeTarget("testSkippableTests");

DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(getProject().getResource("out/TEST-org.example.junit.Junit4Skippable.xml").getInputStream());

assertEquals("Incorrect number of nodes created", 8, doc.getElementsByTagName("testcase").getLength());

XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();

assertEquals("Incorrect number of skipped tests in header", 4, Integer.parseInt(xpath.compile("//testsuite/@skipped").evaluate(doc)));
assertEquals("Incorrect number of error tests in header", 1, Integer.parseInt(xpath.compile("//testsuite/@errors").evaluate(doc)));
assertEquals("Incorrect number of failure tests in header", 2, Integer.parseInt(xpath.compile("//testsuite/@failures").evaluate(doc)));
assertEquals("Incorrect number of tests in header", 8, Integer.parseInt(xpath.compile("//testsuite/@tests").evaluate(doc)));


assertEquals("Incorrect ignore message on explicit ignored test", "Please don't ignore me!", xpath.compile("//testsuite/testcase[@name='explicitIgnoreTest']/skipped/@message").evaluate(doc));
assertEquals("No message should be set on Ignored tests with no Ignore annotation text", 0, ((Node)xpath.compile("//testsuite/testcase[@name='explicitlyIgnoreTestNoMessage']/skipped").evaluate(doc, XPathConstants.NODE)).getAttributes().getLength());
assertEquals("Incorrect ignore message on implicit ignored test", "This test will be ignored", xpath.compile("//testsuite/testcase[@name='implicitlyIgnoreTest']/skipped/@message").evaluate(doc));
assertNotNull("Implicit ignore test should have an ignore element", xpath.compile("//testsuite/testcase[@name='implicitlyIgnoreTestNoMessage']/skipped").evaluate(doc, XPathConstants.NODE));

}

public void testTestMethods() throws Exception {
executeTarget("testTestMethods");
}

}

+ 56
- 0
src/tests/junit/org/example/junit/Junit4Skippable.java View File

@@ -0,0 +1,56 @@
package org.example.junit;

import org.junit.Assume;
import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

public class Junit4Skippable {

@Test
public void passingTest() {
assertTrue("This test passed", true);
}

@Ignore("Please don't ignore me!")
@Test
public void explicitIgnoreTest() {
fail("This test should be skipped");
}

@Test
public void implicitlyIgnoreTest() {
Assume.assumeFalse("This test will be ignored", true);
fail("I told you, this test should have been ignored!");
}

@Test
@Ignore
public void explicitlyIgnoreTestNoMessage() {
fail("This test should be skipped");
}

@Test
public void implicitlyIgnoreTestNoMessage() {
Assume.assumeFalse(true);
fail("I told you, this test should have been ignored!");
}

@Test
public void failingTest() {
fail("I told you this test was going to fail");
}

@Test
public void failingTestNoMessage() {
fail();
}

@Test
public void errorTest() {
throw new RuntimeException("Whoops, this test went wrong");
}

}

Loading…
Cancel
Save