View | Details | Raw Unified | Return to bug 43969
Collapse All | Expand All

(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java (-18 / +101 lines)
Lines 23-42 Link Here
23
import java.io.OutputStream;
23
import java.io.OutputStream;
24
import java.io.OutputStreamWriter;
24
import java.io.OutputStreamWriter;
25
import java.io.Writer;
25
import java.io.Writer;
26
import java.lang.reflect.Method;
27
import java.net.InetAddress;
28
import java.net.UnknownHostException;
29
import java.util.Date;
26
import java.util.Enumeration;
30
import java.util.Enumeration;
27
import java.util.Hashtable;
31
import java.util.Hashtable;
28
import java.util.Properties;
32
import java.util.Properties;
29
import java.util.Date;
33
30
import java.net.InetAddress;
31
import java.net.UnknownHostException;
32
import javax.xml.parsers.DocumentBuilder;
34
import javax.xml.parsers.DocumentBuilder;
33
import javax.xml.parsers.DocumentBuilderFactory;
35
import javax.xml.parsers.DocumentBuilderFactory;
36
34
import junit.framework.AssertionFailedError;
37
import junit.framework.AssertionFailedError;
38
import junit.framework.JUnit4TestCaseFacade;
35
import junit.framework.Test;
39
import junit.framework.Test;
40
36
import org.apache.tools.ant.BuildException;
41
import org.apache.tools.ant.BuildException;
37
import org.apache.tools.ant.util.DOMElementWriter;
42
import org.apache.tools.ant.util.DOMElementWriter;
38
import org.apache.tools.ant.util.DateUtils;
43
import org.apache.tools.ant.util.DateUtils;
39
import org.apache.tools.ant.util.FileUtils;
44
import org.apache.tools.ant.util.FileUtils;
45
import org.junit.Ignore;
40
import org.w3c.dom.Document;
46
import org.w3c.dom.Document;
41
import org.w3c.dom.Element;
47
import org.w3c.dom.Element;
42
import org.w3c.dom.Text;
48
import org.w3c.dom.Text;
Lines 48-54 Link Here
48
 * @see FormatterElement
54
 * @see FormatterElement
49
 */
55
 */
50
56
51
public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants {
57
public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants, IgnoredTestListener {
52
58
53
    private static final double ONE_SECOND = 1000.0;
59
    private static final double ONE_SECOND = 1000.0;
54
60
Lines 73-88 Link Here
73
    private Element rootElement;
79
    private Element rootElement;
74
    /**
80
    /**
75
     * Element for the current test.
81
     * Element for the current test.
82
     * 
83
     * The keying of this map is a bit of a hack: tests are keyed by caseName(className) since
84
     * the Test we get for Test-start isn't the same as the Test we get during test-assumption-fail,
85
     * so we can't easily match Test objects without manually iterating over all keys and checking
86
     * individual fields.
76
     */
87
     */
77
    private Hashtable testElements = new Hashtable();
88
    private Hashtable<String, Element> testElements = new Hashtable<String, Element>();
78
    /**
89
    /**
79
     * tests that failed.
90
     * tests that failed.
80
     */
91
     */
81
    private Hashtable failedTests = new Hashtable();
92
    private Hashtable failedTests = new Hashtable();
82
    /**
93
    /**
94
     * Tests that were skipped.
95
     */
96
    private Hashtable<String, Test> skippedTests = new Hashtable<String, Test>();
97
    /**
98
     * Tests that were ignored. See the note above about the key being a bit of a hack.
99
     */
100
    private Hashtable<String, Test> ignoredTests = new Hashtable<String, Test>();
101
    /**
83
     * Timing helper.
102
     * Timing helper.
84
     */
103
     */
85
    private Hashtable testStarts = new Hashtable();
104
    private Hashtable<String, Long> testStarts = new Hashtable<String, Long>();
86
    /**
105
    /**
87
     * Where to write the log to.
106
     * Where to write the log to.
88
     */
107
     */
Lines 161-166 Link Here
161
        rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount());
180
        rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount());
162
        rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount());
181
        rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount());
163
        rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount());
182
        rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount());
183
        rootElement.setAttribute(ATTR_SKIPPED, "" + suite.skipCount());
164
        rootElement.setAttribute(
184
        rootElement.setAttribute(
165
            ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND));
185
            ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND));
166
        if (out != null) {
186
        if (out != null) {
Lines 193-201 Link Here
193
     * @param t the test.
213
     * @param t the test.
194
     */
214
     */
195
    public void startTest(Test t) {
215
    public void startTest(Test t) {
196
        testStarts.put(t, new Long(System.currentTimeMillis()));
216
        testStarts.put(createDescription(t), System.currentTimeMillis());
197
    }
217
    }
198
218
219
    private static String createDescription(Test test) throws BuildException {
220
        return JUnitVersionHelper.getTestCaseName(test) + "(" + JUnitVersionHelper.getTestCaseClassName(test) + ")";
221
	}
222
199
    /**
223
    /**
200
     * Interface TestListener.
224
     * Interface TestListener.
201
     *
225
     *
Lines 203-217 Link Here
203
     * @param test the test.
227
     * @param test the test.
204
     */
228
     */
205
    public void endTest(Test test) {
229
    public void endTest(Test test) {
230
        String testDescription = createDescription(test);
231
206
        // Fix for bug #5637 - if a junit.extensions.TestSetup is
232
        // Fix for bug #5637 - if a junit.extensions.TestSetup is
207
        // used and throws an exception during setUp then startTest
233
        // used and throws an exception during setUp then startTest
208
        // would never have been called
234
        // would never have been called
209
        if (!testStarts.containsKey(test)) {
235
        if (!testStarts.containsKey(testDescription)) {
210
            startTest(test);
236
            startTest(test);
211
        }
237
        }
212
238
        Element currentTest;
213
        Element currentTest = null;
239
        if (!failedTests.containsKey(test) && !skippedTests.containsKey(testDescription) && !ignoredTests.containsKey(testDescription)) {
214
        if (!failedTests.containsKey(test)) {
215
            currentTest = doc.createElement(TESTCASE);
240
            currentTest = doc.createElement(TESTCASE);
216
            String n = JUnitVersionHelper.getTestCaseName(test);
241
            String n = JUnitVersionHelper.getTestCaseName(test);
217
            currentTest.setAttribute(ATTR_NAME,
242
            currentTest.setAttribute(ATTR_NAME,
Lines 221-235 Link Here
221
            currentTest.setAttribute(ATTR_CLASSNAME,
246
            currentTest.setAttribute(ATTR_CLASSNAME,
222
                    JUnitVersionHelper.getTestCaseClassName(test));
247
                    JUnitVersionHelper.getTestCaseClassName(test));
223
            rootElement.appendChild(currentTest);
248
            rootElement.appendChild(currentTest);
224
            testElements.put(test, currentTest);
249
            testElements.put(createDescription(test), currentTest);
225
        } else {
250
        } else {
226
            currentTest = (Element) testElements.get(test);
251
            currentTest = testElements.get(testDescription);
227
        }
252
        }
228
253
229
        Long l = (Long) testStarts.get(test);
254
        Long l = testStarts.get(createDescription(test));
230
        currentTest.setAttribute(ATTR_TIME,
255
        currentTest.setAttribute(ATTR_TIME,
231
            "" + ((System.currentTimeMillis()
256
            "" + ((System.currentTimeMillis() - l) / ONE_SECOND));
232
                   - l.longValue()) / ONE_SECOND));
233
    }
257
    }
234
258
235
    /**
259
    /**
Lines 272-280 Link Here
272
        }
296
        }
273
297
274
        Element nested = doc.createElement(type);
298
        Element nested = doc.createElement(type);
275
        Element currentTest = null;
299
        Element currentTest;
276
        if (test != null) {
300
        if (test != null) {
277
            currentTest = (Element) testElements.get(test);
301
            currentTest = testElements.get(createDescription(test));
278
        } else {
302
        } else {
279
            currentTest = rootElement;
303
            currentTest = rootElement;
280
        }
304
        }
Lines 298-301 Link Here
298
        nested.appendChild(doc.createCDATASection(output));
322
        nested.appendChild(doc.createCDATASection(output));
299
    }
323
    }
300
324
325
    @Override
326
    public void testIgnored(Test test) {
327
        String message = null;
328
        if (test != null && test instanceof JUnit4TestCaseFacade) {
329
        	//try and get the message coded as part of the ignore
330
        	/*
331
        	 * org.junit.runner.Description contains a getAnnotation(Class) method... but this
332
        	 * wasn't in older versions of JUnit4 so we have to try and do this by reflection
333
        	 */
334
        	try {
335
        		Class<?> testClass = Class.forName(JUnitVersionHelper.getTestCaseClassName(test));
336
        	
337
                Method testMethod = testClass.getMethod(JUnitVersionHelper.getTestCaseName(test));
338
                Ignore annotation = testMethod.getAnnotation(Ignore.class);
339
                if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) {
340
                    message = annotation.value();
341
                }
342
        	} catch (NoSuchMethodException e) {
343
				// silently ignore - we'll report a skip with no message
344
			} catch (ClassNotFoundException e) {
345
				// silently ignore - we'll report a skip with no message
346
			}
347
        }
348
        formatSkip(test, message);
349
        if (test != null) {
350
            ignoredTests.put(createDescription(test), test);
351
        }
352
    }
353
354
355
    public void formatSkip(Test test, String message) {
356
        if (test != null) {
357
            endTest(test);
358
        }
359
360
        Element nested = doc.createElement("skipped");
361
362
        if (message != null) {
363
            nested.setAttribute("message", message);
364
        }
365
366
        Element currentTest;
367
        if (test != null) {
368
            currentTest = testElements.get(createDescription(test));
369
        } else {
370
            currentTest = rootElement;
371
        }
372
373
        currentTest.appendChild(nested);
374
375
    }
376
377
    @Override
378
    public void testAssumptionFailure(Test test, Throwable failure) {
379
        String message = failure.getMessage();
380
        formatSkip(test, message);
381
        skippedTests.put(createDescription(test), test);
382
383
    }
301
} // XMLJUnitResultFormatter
384
} // XMLJUnitResultFormatter
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/TestListenerWrapper.java (+56 lines)
Line 0 Link Here
1
package org.apache.tools.ant.taskdefs.optional.junit;
2
3
import junit.framework.AssertionFailedError;
4
import junit.framework.JUnit4TestAdapterCache;
5
import junit.framework.Test;
6
import junit.framework.TestListener;
7
8
import org.junit.internal.AssumptionViolatedException;
9
import org.junit.runner.Description;
10
import org.junit.runner.notification.Failure;
11
12
public class TestListenerWrapper implements TestListener, IgnoredTestListener {
13
14
    private TestListener wrapped;
15
16
    public TestListenerWrapper(TestListener listener) {
17
        super();
18
        wrapped = listener;
19
    }
20
21
    @Override
22
    public void addError(Test test, Throwable throwable) {
23
        wrapped.addError(test, throwable);
24
    }
25
26
    @Override
27
    public void addFailure(Test test, AssertionFailedError assertionFailedError) {
28
        wrapped.addFailure(test, assertionFailedError);
29
    }
30
31
    @Override
32
    public void endTest(Test test) {
33
        wrapped.endTest(test);
34
    }
35
36
    @Override
37
    public void startTest(Test test) {
38
        wrapped.startTest(test);
39
    }
40
41
    @Override
42
    public void testIgnored(Test test) {
43
        if (wrapped instanceof IgnoredTestListener) {
44
            ((IgnoredTestListener)wrapped).testIgnored(test);
45
        }
46
    }
47
48
    @Override
49
    public void testAssumptionFailure(Test test, Throwable throwable) {
50
        if (wrapped instanceof IgnoredTestListener) {
51
            ((IgnoredTestListener)wrapped).testAssumptionFailure(test, throwable);
52
        }
53
    }
54
55
56
}
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestResult.java (+81 lines)
Line 0 Link Here
1
package org.apache.tools.ant.taskdefs.optional.junit;
2
3
import java.util.ArrayList;
4
import java.util.List;
5
6
import junit.framework.Test;
7
import junit.framework.TestListener;
8
import junit.framework.TestResult;
9
10
/**
11
 * Records ignored and skipped tests reported as part of the execution of
12
 * JUnit 4 tests.
13
 *
14
 * @author Michael Clarke
15
 */
16
public class IgnoredTestResult extends TestResult {
17
18
19
    private List<IgnoredTestListener> listeners = new ArrayList<IgnoredTestListener>();
20
    private List<TestIgnored> ignored = new ArrayList<TestIgnored>();
21
    private List<TestIgnored> skipped = new ArrayList<TestIgnored>();
22
23
    public IgnoredTestResult() {
24
        super();
25
    }
26
27
28
    public synchronized void addListener(TestListener listener) {
29
        if (listener instanceof IgnoredTestListener) {
30
            listeners.add((IgnoredTestListener)listener);
31
        }
32
        super.addListener(listener);
33
    }
34
35
    public synchronized  void removeListener(TestListener listener) {
36
        if (listener instanceof IgnoredTestListener) {
37
            listeners.remove(listener);
38
        }
39
        super.removeListener(listener);
40
    }
41
42
    /**
43
     * Record a test as having been ignored, normally by the @Ignore annotation.
44
     * @param test the test that was ignored.
45
     * @throws Exception is the listener thrown an exception on handling the notification.
46
     */
47
    public synchronized void testIgnored(Test test) throws Exception {
48
        ignored.add(new TestIgnored(test));
49
        for (IgnoredTestListener listener : listeners) {
50
            listener.testIgnored(test);
51
        }
52
    }
53
54
    /**
55
     * Report how many tests were ignored.
56
     * @return the number of tests reported as ignored during the current execution.
57
     */
58
    public long ignoredCount() {
59
        return ignored.size();
60
    }
61
62
    /**
63
     * Records a test as having an assumption failure so JUnit will no longer be executing it.
64
     * Under normal circumstances this would be counted as a skipped test.
65
     * @param failure the details of the test and assumption failure.
66
     */
67
    public void testAssumptionFailure(Test test, Throwable cause) {
68
    	skipped.add(new TestIgnored(test));
69
        for (IgnoredTestListener listener : listeners) {
70
            listener.testAssumptionFailure(test, cause);
71
        }
72
    }
73
74
    /**
75
     * Report how many tests has assumption failures.
76
     * @return the number of tests that reported assumption failures during the current execution.
77
     */
78
    public long skippedCount() {
79
        return skipped.size();
80
    }
81
}
(-)src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java (-2 / +10 lines)
Lines 25-31 Link Here
25
import org.apache.tools.ant.BuildException;
25
import org.apache.tools.ant.BuildException;
26
import org.apache.tools.ant.BuildFileTest;
26
import org.apache.tools.ant.BuildFileTest;
27
import org.apache.tools.ant.util.JavaEnvUtils;
27
import org.apache.tools.ant.util.JavaEnvUtils;
28
import org.w3c.dom.Document;
29
import org.w3c.dom.Node;
28
30
31
import javax.xml.parsers.DocumentBuilder;
32
import javax.xml.parsers.DocumentBuilderFactory;
33
import javax.xml.xpath.XPath;
34
import javax.xml.xpath.XPathConstants;
35
import javax.xml.xpath.XPathFactory;
36
29
public class JUnitTaskTest extends BuildFileTest {
37
public class JUnitTaskTest extends BuildFileTest {
30
38
31
    /**
39
    /**
Lines 262-268 Link Here
262
                         line);
270
                         line);
263
            line = reader.readLine();
271
            line = reader.readLine();
264
            assertNotNull(line);
272
            assertNotNull(line);
265
            assertTrue(line.startsWith("Tests run: 1, Failures: 0, Errors: 0, Time elapsed:"));
273
            assertTrue(line.startsWith("Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed:"));
266
            line = reader.readLine();
274
            line = reader.readLine();
267
            assertEquals("------------- Standard Output ---------------",
275
            assertEquals("------------- Standard Output ---------------",
268
                         line);
276
                         line);
Lines 296-299 Link Here
296
        assertEquals(search, line);
304
        assertEquals(search, line);
297
    }
305
    }
298
306
299
}
307
}
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java (+2 lines)
Lines 144-149 Link Here
144
        sb.append(suite.failureCount());
144
        sb.append(suite.failureCount());
145
        sb.append(", Errors: ");
145
        sb.append(", Errors: ");
146
        sb.append(suite.errorCount());
146
        sb.append(suite.errorCount());
147
        sb.append(", Skipped: ");
148
        sb.append(suite.skipCount());
147
        sb.append(", Time elapsed: ");
149
        sb.append(", Time elapsed: ");
148
        sb.append(nf.format(suite.getRunTime() / ONE_SECOND));
150
        sb.append(nf.format(suite.getRunTime() / ONE_SECOND));
149
        sb.append(" sec");
151
        sb.append(" sec");
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLConstants.java (+2 lines)
Lines 106-111 Link Here
106
    /** tests attribute for testsuite elements */
106
    /** tests attribute for testsuite elements */
107
    String ATTR_TESTS = "tests";
107
    String ATTR_TESTS = "tests";
108
108
109
    String ATTR_SKIPPED = "skipped";
110
109
    /** type attribute for failure and error elements */
111
    /** type attribute for failure and error elements */
110
    String ATTR_TYPE = "type";
112
    String ATTR_TYPE = "type";
111
113
(-)lib/libraries.properties (-1 / +1 lines)
Lines 45-51 Link Here
45
jasper-runtime.version=${jasper-compiler.version}
45
jasper-runtime.version=${jasper-compiler.version}
46
jdepend.version=2.9.1
46
jdepend.version=2.9.1
47
jruby.version=0.9.8
47
jruby.version=0.9.8
48
junit.version=4.8.1
48
junit.version=4.11
49
jsch.version=0.1.42
49
jsch.version=0.1.42
50
jython.version=2.1
50
jython.version=2.1
51
#log4j 1.2.15 requires JMS and a few other Sun jars that are not in the m2 repo
51
#log4j 1.2.15 requires JMS and a few other Sun jars that are not in the m2 repo
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/TestIgnored.java (+17 lines)
Line 0 Link Here
1
package org.apache.tools.ant.taskdefs.optional.junit;
2
3
import junit.framework.Test;
4
5
public class TestIgnored {
6
7
    private Test test;
8
9
    public TestIgnored(Test test) {
10
        this.test = test;
11
    }
12
13
    public Test getTest() {
14
        return test;
15
    }
16
17
}
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/CustomJUnit4TestAdapterCache.java (+63 lines)
Line 0 Link Here
1
package org.apache.tools.ant.taskdefs.optional.junit;
2
3
import junit.framework.JUnit4TestAdapter;
4
import junit.framework.JUnit4TestAdapterCache;
5
import junit.framework.TestResult;
6
import org.junit.runner.Description;
7
import org.junit.runner.notification.Failure;
8
import org.junit.runner.notification.RunListener;
9
import org.junit.runner.notification.RunNotifier;
10
11
/**
12
 * Provides a custom implementation of the notifier for a Junit4TestAdapter
13
 * so that skipped and ignored tests can be reported to the existing
14
 * <tt></tt>TestListener</tt>s.
15
 *
16
 * @author Michael Clarke
17
 */
18
public class CustomJUnit4TestAdapterCache extends JUnit4TestAdapterCache {
19
20
    public CustomJUnit4TestAdapterCache() {
21
        super();
22
    }
23
24
    public RunNotifier getNotifier(final TestResult result, final JUnit4TestAdapter adapter) {
25
26
        if (!(result instanceof IgnoredTestResult)) {
27
            //the TestResult doesn't support our ignored method, continue with default functionality
28
            return super.getNotifier(result, adapter);
29
        }
30
31
        final IgnoredTestResult resultWrapper = (IgnoredTestResult) result;
32
33
        RunNotifier notifier = new RunNotifier();
34
        notifier.addListener(new RunListener() {
35
            @Override
36
            public void testFailure(Failure failure) throws Exception {
37
                result.addError(asTest(failure.getDescription()), failure.getException());
38
            }
39
40
            @Override
41
            public void testFinished(Description description) throws Exception {
42
                result.endTest(asTest(description));
43
            }
44
45
            @Override
46
            public void testStarted(Description description) throws Exception {
47
                resultWrapper.startTest(asTest(description));
48
            }
49
50
            @Override
51
            public void testIgnored(Description description) throws Exception {
52
                resultWrapper.testIgnored(asTest(description));
53
            }
54
55
            @Override
56
            public void testAssumptionFailure(Failure failure) {
57
                resultWrapper.testAssumptionFailure(asTest(failure.getDescription()), failure.getException());
58
            }
59
        });
60
61
        return notifier;
62
    }
63
}
(-)src/etc/testcases/taskdefs/optional/junit.xml (+17 lines)
Lines 276-279 Link Here
276
    </junit>
276
    </junit>
277
  </target>
277
  </target>
278
278
279
  <!-- Junit4 Ignore and Assume for skipping tests -->
280
  <target name="testSkippableTests">
281
    <mkdir dir="out"/>
282
    <junit fork="true">
283
            <classpath refid="test"/>
284
            <formatter type="xml"/>
285
            <classpath refid="test"/>
286
            <batchtest todir="out">
287
                <fileset dir="../../../../tests/junit">
288
                    <include
289
                            name="org/example/junit/Junit4Skippable.java"/>
290
                    <!-- tests remove out-dir on tearDown -->
291
                </fileset>
292
            </batchtest>
293
    </junit>
294
  </target>
295
279
</project>
296
</project>
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnit4TestMethodAdapter.java (-2 / +8 lines)
Lines 33-39 Link Here
33
33
34
/**
34
/**
35
 * Adapter between JUnit 3.8.x API and JUnit 4.x API for execution of tests
35
 * Adapter between JUnit 3.8.x API and JUnit 4.x API for execution of tests
36
 * and listening of events (test start, test finish, test failure).
36
 * and listening of events (test start, test finish, test failure, test skipped).
37
 * The constructor is passed a JUnit 4 test class and a list of name of methods
37
 * The constructor is passed a JUnit 4 test class and a list of name of methods
38
 * in it that should be executed. Method {@link #run run(TestResult)} executes
38
 * in it that should be executed. Method {@link #run run(TestResult)} executes
39
 * the given JUnit-4-style test methods and notifies the given {@code TestResult}
39
 * the given JUnit-4-style test methods and notifies the given {@code TestResult}
Lines 104-110 Link Here
104
    public Class getTestClass() {
104
    public Class getTestClass() {
105
        return testClass;
105
        return testClass;
106
    }
106
    }
107
    
107
108
    public void run(final TestResult result) {
108
    public void run(final TestResult result) {
109
        runner.run(cache.getNotifier(result));
109
        runner.run(cache.getNotifier(result));
110
    }
110
    }
Lines 219-224 Link Here
219
                    public void testStarted(Description description)
219
                    public void testStarted(Description description)
220
                                    throws Exception {
220
                                    throws Exception {
221
                        result.startTest(asTest(description));
221
                        result.startTest(asTest(description));
222
                    }
223
224
                    public void testIgnored(Description description) throws Exception {
225
                        if (result instanceof IgnoredTestResult) {
226
                            ((IgnoredTestResult)result).testIgnored(asTest(description));
227
                        }
222
                    }
228
                    }
223
            });
229
            });
224
            return notifier;
230
            return notifier;
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java (-1 / +43 lines)
Lines 25-35 Link Here
25
import java.text.NumberFormat;
25
import java.text.NumberFormat;
26
26
27
import junit.framework.AssertionFailedError;
27
import junit.framework.AssertionFailedError;
28
import junit.framework.JUnit4TestCaseFacade;
28
import junit.framework.Test;
29
import junit.framework.Test;
29
30
30
import org.apache.tools.ant.BuildException;
31
import org.apache.tools.ant.BuildException;
31
import org.apache.tools.ant.util.FileUtils;
32
import org.apache.tools.ant.util.FileUtils;
32
import org.apache.tools.ant.util.StringUtils;
33
import org.apache.tools.ant.util.StringUtils;
34
import org.junit.Ignore;
33
35
34
/**
36
/**
35
 * Prints plain text output of the test to a specified Writer.
37
 * Prints plain text output of the test to a specified Writer.
Lines 38-44 Link Here
38
 * @see FormatterElement
40
 * @see FormatterElement
39
 * @see PlainJUnitResultFormatter
41
 * @see PlainJUnitResultFormatter
40
 */
42
 */
41
public class BriefJUnitResultFormatter implements JUnitResultFormatter {
43
public class BriefJUnitResultFormatter implements JUnitResultFormatter, IgnoredTestListener {
42
44
43
    private static final double ONE_SECOND = 1000.0;
45
    private static final double ONE_SECOND = 1000.0;
44
46
Lines 141-146 Link Here
141
        sb.append(suite.failureCount());
143
        sb.append(suite.failureCount());
142
        sb.append(", Errors: ");
144
        sb.append(", Errors: ");
143
        sb.append(suite.errorCount());
145
        sb.append(suite.errorCount());
146
        sb.append(", Skipped: ");
147
        sb.append(suite.skipCount());
144
        sb.append(", Time elapsed: ");
148
        sb.append(", Time elapsed: ");
145
        sb.append(numberFormat.format(suite.getRunTime() / ONE_SECOND));
149
        sb.append(numberFormat.format(suite.getRunTime() / ONE_SECOND));
146
        sb.append(" sec");
150
        sb.append(" sec");
Lines 266-270 Link Here
266
        } catch (IOException ex) {
270
        } catch (IOException ex) {
267
            throw new BuildException(ex);
271
            throw new BuildException(ex);
268
        }
272
        }
273
    }
274
275
276
    @Override
277
    public void testIgnored(Test test) {
278
        String message = null;
279
        if (test instanceof JUnit4TestCaseFacade) {
280
            JUnit4TestCaseFacade facade = (JUnit4TestCaseFacade) test;
281
            Ignore annotation = facade.getDescription().getAnnotation(Ignore.class);
282
            if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) {
283
                message = annotation.value();
284
            }
285
        }
286
        formatSkip(test, message);
287
    }
288
289
290
    public void formatSkip(Test test, String message) {
291
        if (test != null) {
292
            endTest(test);
293
        }
294
295
        try {
296
            resultWriter.write(formatTest(test) + "SKIPPED");
297
            if (message != null) {
298
                resultWriter.write(": ");
299
                resultWriter.write(message);
300
            }
301
            resultWriter.newLine();
302
        } catch (IOException ex) {
303
            throw new BuildException(ex);
304
        }
305
306
    }
307
308
    @Override
309
    public void testAssumptionFailure(Test test, Throwable cause) {
310
        formatSkip(test, cause.getMessage());
269
    }
311
    }
270
}
312
}
(-)src/tests/junit/org/example/junit/Junit4Skippable.java (+56 lines)
Line 0 Link Here
1
package org.example.junit;
2
3
import org.junit.Assume;
4
import org.junit.Ignore;
5
import org.junit.Test;
6
7
import static org.junit.Assert.assertTrue;
8
import static org.junit.Assert.fail;
9
10
public class Junit4Skippable {
11
12
    @Test
13
    public void passingTest() {
14
        assertTrue("This test passed", true);
15
    }
16
17
    @Ignore("Please don't ignore me!")
18
    @Test
19
    public void explicitIgnoreTest() {
20
        fail("This test should be skipped");
21
    }
22
23
    @Test
24
    public void implicitlyIgnoreTest() {
25
        Assume.assumeFalse("This test will be ignored", true);
26
        fail("I told you, this test should have been ignored!");
27
    }
28
29
    @Test
30
    @Ignore
31
    public void explicitlyIgnoreTestNoMessage() {
32
        fail("This test should be skipped");
33
    }
34
35
    @Test
36
    public void implicitlyIgnoreTestNoMessage() {
37
        Assume.assumeFalse(true);
38
        fail("I told you, this test should have been ignored!");
39
    }
40
41
    @Test
42
    public void failingTest() {
43
        fail("I told you this test was going to fail");
44
    }
45
46
    @Test
47
    public void failingTestNoMessage() {
48
        fail();
49
    }
50
51
    @Test
52
    public void errorTest() {
53
        throw new RuntimeException("Whoops, this test went wrong");
54
    }
55
56
}
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestListener.java (+36 lines)
Line 0 Link Here
1
package org.apache.tools.ant.taskdefs.optional.junit;
2
3
import junit.framework.Test;
4
import junit.framework.TestListener;
5
import org.junit.runner.notification.Failure;
6
7
/**
8
 * Provides the functionality for TestListeners to be able to be notified of
9
 * the necessary Junit4 events for test being ignored (@Ignore annotation)
10
 * or skipped (Assume failures). Tests written in Junit4 will report against
11
 * the methods in this interface alongside the methods in the existing TestListener
12
 * @author Michael Clarke
13
 */
14
public interface IgnoredTestListener extends TestListener {
15
16
    /**
17
     * Reports when a test has been marked with the @Ignore annotation. The parameter
18
     * should normally be typed to Junit's {@link junit.framework.JUnit4TestCaseFacade}
19
     * so implementing classes should be able to get the details of the ignore by casting
20
     * the argument and retrieving the descriptor from the test.
21
     * @param test
22
     */
23
    void testIgnored(Test test);
24
25
    /**
26
     * Receive a report that a test has failed an assumption. Within JUnit4
27
     * this is normally treated as a test being skipped, although how any
28
     * listener handles this is up to that specific listener.<br />
29
     * <b>Note:</b> Tests that throw assumption failures will still report
30
     * the endTest method, which may differ from how the addError and addFailure
31
     * methods work, it's up for any implementing classes to handle this.
32
     * @param test the details of the test and failure that have triggered this report.
33
     * @param exception the AssumptionViolatedException thrown from the current assumption failure.
34
     */
35
    void testAssumptionFailure(Test test, Throwable exception);
36
}
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java (-3 / +13 lines)
Lines 61-67 Link Here
61
    // @todo this is duplicating TestResult information. Only the time is not
61
    // @todo this is duplicating TestResult information. Only the time is not
62
    // part of the result. So we'd better derive a new class from TestResult
62
    // part of the result. So we'd better derive a new class from TestResult
63
    // and deal with it. (SB)
63
    // and deal with it. (SB)
64
    private long runs, failures, errors;
64
    private long runs, failures, errors, skips;
65
    private long runTime;
65
    private long runTime;
66
66
67
    // Snapshot of the system properties
67
    // Snapshot of the system properties
Lines 352-366 Link Here
352
    }
352
    }
353
353
354
    /**
354
    /**
355
     * Set the number of runs, failures and errors.
355
     * Set the number of runs, failures, errors, and skipped tests.
356
     * @param runs     the number of runs.
356
     * @param runs     the number of runs.
357
     * @param failures the number of failures.
357
     * @param failures the number of failures.
358
     * @param errors   the number of errors.
358
     * @param errors   the number of errors.
359
     * @params skips   the number of skipped tests.
359
     */
360
     */
360
    public void setCounts(long runs, long failures, long errors) {
361
    public void setCounts(long runs, long failures, long errors, long skips) {
361
        this.runs = runs;
362
        this.runs = runs;
362
        this.failures = failures;
363
        this.failures = failures;
363
        this.errors = errors;
364
        this.errors = errors;
365
        this.skips = skips;
364
    }
366
    }
365
367
366
    /**
368
    /**
Lines 393-398 Link Here
393
     */
395
     */
394
    public long errorCount() {
396
    public long errorCount() {
395
        return errors;
397
        return errors;
398
    }
399
400
    /**
401
     * Get the number of skipped tests.
402
     * @return the number of skipped tests.
403
     */
404
    public long skipCount() {
405
        return skips;
396
    }
406
    }
397
407
398
    /**
408
    /**
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java (-1 / +1 lines)
Lines 1645-1651 Link Here
1645
                classLoader.setThreadContextLoader();
1645
                classLoader.setThreadContextLoader();
1646
            }
1646
            }
1647
1647
1648
            test.setCounts(1, 0, 1);
1648
            test.setCounts(1, 0, 1, 0);
1649
            test.setProperties(getProject().getProperties());
1649
            test.setProperties(getProject().getProperties());
1650
            for (int i = 0; i < feArray.length; i++) {
1650
            for (int i = 0; i < feArray.length; i++) {
1651
                FormatterElement fe = feArray[i];
1651
                FormatterElement fe = feArray[i];
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/PlainJUnitResultFormatter.java (-1 / +42 lines)
Lines 26-36 Link Here
26
import java.util.Hashtable;
26
import java.util.Hashtable;
27
27
28
import junit.framework.AssertionFailedError;
28
import junit.framework.AssertionFailedError;
29
import junit.framework.JUnit4TestCaseFacade;
29
import junit.framework.Test;
30
import junit.framework.Test;
30
31
31
import org.apache.tools.ant.BuildException;
32
import org.apache.tools.ant.BuildException;
32
import org.apache.tools.ant.util.FileUtils;
33
import org.apache.tools.ant.util.FileUtils;
33
import org.apache.tools.ant.util.StringUtils;
34
import org.apache.tools.ant.util.StringUtils;
35
import org.junit.Ignore;
36
import org.junit.runner.notification.Failure;
34
37
35
38
36
/**
39
/**
Lines 38-44 Link Here
38
 *
41
 *
39
 */
42
 */
40
43
41
public class PlainJUnitResultFormatter implements JUnitResultFormatter {
44
public class PlainJUnitResultFormatter implements JUnitResultFormatter, IgnoredTestListener {
42
45
43
    private static final double ONE_SECOND = 1000.0;
46
    private static final double ONE_SECOND = 1000.0;
44
47
Lines 123-128 Link Here
123
        sb.append(suite.failureCount());
126
        sb.append(suite.failureCount());
124
        sb.append(", Errors: ");
127
        sb.append(", Errors: ");
125
        sb.append(suite.errorCount());
128
        sb.append(suite.errorCount());
129
        sb.append(", Skipped: ");
130
        sb.append(suite.skipCount());
126
        sb.append(", Time elapsed: ");
131
        sb.append(", Time elapsed: ");
127
        sb.append(nf.format(suite.getRunTime() / ONE_SECOND));
132
        sb.append(nf.format(suite.getRunTime() / ONE_SECOND));
128
        sb.append(" sec");
133
        sb.append(" sec");
Lines 258-261 Link Here
258
        }
263
        }
259
    }
264
    }
260
265
266
    @Override
267
    public void testIgnored(Test test) {
268
        String message = null;
269
        if (test instanceof JUnit4TestCaseFacade) {
270
            JUnit4TestCaseFacade facade = (JUnit4TestCaseFacade) test;
271
            Ignore annotation = facade.getDescription().getAnnotation(Ignore.class);
272
            if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) {
273
                message = annotation.value();
274
            }
275
        }
276
        formatSkip(test, message);
277
    }
278
279
280
    public void formatSkip(Test test, String message) {
281
        if (test != null) {
282
            endTest(test);
283
        }
284
285
        try {
286
            wri.write("\tSKIPPED");
287
            if (message != null) {
288
                wri.write(": ");
289
                wri.write(message);
290
            }
291
            wri.newLine();
292
        } catch (IOException ex) {
293
            throw new BuildException(ex);
294
        }
295
296
    }
297
298
    @Override
299
    public void testAssumptionFailure(Test test, Throwable throwable) {
300
        formatSkip(test, throwable.getMessage());
301
    }
261
} // PlainJUnitResultFormatter
302
} // PlainJUnitResultFormatter
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java (-10 / +12 lines)
Lines 36-41 Link Here
36
import java.util.StringTokenizer;
36
import java.util.StringTokenizer;
37
import java.util.Vector;
37
import java.util.Vector;
38
import junit.framework.AssertionFailedError;
38
import junit.framework.AssertionFailedError;
39
import junit.framework.JUnit4TestAdapterCache;
39
import junit.framework.Test;
40
import junit.framework.Test;
40
import junit.framework.TestFailure;
41
import junit.framework.TestFailure;
41
import junit.framework.TestListener;
42
import junit.framework.TestListener;
Lines 76-82 Link Here
76
    /**
77
    /**
77
     * Collects TestResults.
78
     * Collects TestResults.
78
     */
79
     */
79
    private TestResult res;
80
    private IgnoredTestResult res;
80
81
81
    /**
82
    /**
82
     * Do we filter junit.*.* stack frames out of failure and error exceptions.
83
     * Do we filter junit.*.* stack frames out of failure and error exceptions.
Lines 289-294 Link Here
289
                           boolean filtertrace, boolean haltOnFailure,
290
                           boolean filtertrace, boolean haltOnFailure,
290
                           boolean showOutput, boolean logTestListenerEvents,
291
                           boolean showOutput, boolean logTestListenerEvents,
291
                           ClassLoader loader) {
292
                           ClassLoader loader) {
293
        super();
292
        JUnitTestRunner.filtertrace = filtertrace; // XXX clumsy, should use instance field somehow
294
        JUnitTestRunner.filtertrace = filtertrace; // XXX clumsy, should use instance field somehow
293
        this.junitTest = test;
295
        this.junitTest = test;
294
        this.haltOnError = haltOnError;
296
        this.haltOnError = haltOnError;
Lines 350-356 Link Here
350
     * Run the test.
352
     * Run the test.
351
     */
353
     */
352
    public void run() {
354
    public void run() {
353
        res = new TestResult();
355
        res = new IgnoredTestResult();
354
        res.addListener(wrapListener(this));
356
        res.addListener(wrapListener(this));
355
        final int size = formatters.size();
357
        final int size = formatters.size();
356
        for (int i = 0; i < size; i++) {
358
        for (int i = 0; i < size; i++) {
Lines 468-475 Link Here
468
                            formalParams = new Class[] {Class.class, String[].class};
470
                            formalParams = new Class[] {Class.class, String[].class};
469
                            actualParams = new Object[] {testClass, methods};
471
                            actualParams = new Object[] {testClass, methods};
470
                        } else {
472
                        } else {
471
                            formalParams = new Class[] {Class.class};
473
                            formalParams = new Class[] {Class.class, JUnit4TestAdapterCache.class};
472
                            actualParams = new Object[] {testClass};
474
                            actualParams = new Object[] {testClass, new CustomJUnit4TestAdapterCache()};
473
                        }
475
                        }
474
                        suite =
476
                        suite =
475
                            (Test) junit4TestAdapterClass
477
                            (Test) junit4TestAdapterClass
Lines 512-518 Link Here
512
                    ((TestListener) formatters.elementAt(i))
514
                    ((TestListener) formatters.elementAt(i))
513
                        .addError(null, exception);
515
                        .addError(null, exception);
514
                }
516
                }
515
                junitTest.setCounts(1, 0, 1);
517
                junitTest.setCounts(1, 0, 1, 0);
516
                junitTest.setRunTime(0);
518
                junitTest.setRunTime(0);
517
            } else {
519
            } else {
518
                try {
520
                try {
Lines 522-531 Link Here
522
                    if (junit4 ||
524
                    if (junit4 ||
523
                        suite.getClass().getName().equals(JUNIT_4_TEST_ADAPTER)) {
525
                        suite.getClass().getName().equals(JUNIT_4_TEST_ADAPTER)) {
524
                        int[] cnts = findJUnit4FailureErrorCount(res);
526
                        int[] cnts = findJUnit4FailureErrorCount(res);
525
                        junitTest.setCounts(res.runCount(), cnts[0], cnts[1]);
527
                        junitTest.setCounts(res.runCount() + res.ignoredCount(), cnts[0], cnts[1], res.ignoredCount() + res.skippedCount());
526
                    } else {
528
                    } else {
527
                        junitTest.setCounts(res.runCount(), res.failureCount(),
529
                        junitTest.setCounts(res.runCount() + res.ignoredCount(), res.failureCount(),
528
                                res.errorCount());
530
                                res.errorCount(), res.ignoredCount() + res.skippedCount());
529
                    }
531
                    }
530
                    junitTest.setRunTime(System.currentTimeMillis() - start);
532
                    junitTest.setRunTime(System.currentTimeMillis() - start);
531
                }
533
                }
Lines 1101-1108 Link Here
1101
     *
1103
     *
1102
     * @since Ant 1.7
1104
     * @since Ant 1.7
1103
     */
1105
     */
1104
    private TestListener wrapListener(final TestListener testListener) {
1106
    private TestListenerWrapper wrapListener(final TestListener testListener) {
1105
        return new TestListener() {
1107
        return new TestListenerWrapper(testListener) {
1106
            public void addError(Test test, Throwable t) {
1108
            public void addError(Test test, Throwable t) {
1107
                if (junit4 && t instanceof AssertionFailedError) {
1109
                if (junit4 && t instanceof AssertionFailedError) {
1108
                    // JUnit 4 does not distinguish between errors and failures
1110
                    // JUnit 4 does not distinguish between errors and failures

Return to bug 43969