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

(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java (-15 / +90 lines)
Lines 32-42 Link Here
32
import javax.xml.parsers.DocumentBuilder;
32
import javax.xml.parsers.DocumentBuilder;
33
import javax.xml.parsers.DocumentBuilderFactory;
33
import javax.xml.parsers.DocumentBuilderFactory;
34
import junit.framework.AssertionFailedError;
34
import junit.framework.AssertionFailedError;
35
import junit.framework.JUnit4TestCaseFacade;
35
import junit.framework.Test;
36
import junit.framework.Test;
36
import org.apache.tools.ant.BuildException;
37
import org.apache.tools.ant.BuildException;
37
import org.apache.tools.ant.util.DOMElementWriter;
38
import org.apache.tools.ant.util.DOMElementWriter;
38
import org.apache.tools.ant.util.DateUtils;
39
import org.apache.tools.ant.util.DateUtils;
39
import org.apache.tools.ant.util.FileUtils;
40
import org.apache.tools.ant.util.FileUtils;
41
import org.junit.Ignore;
42
import org.junit.runner.Description;
43
import org.junit.runner.notification.Failure;
40
import org.w3c.dom.Document;
44
import org.w3c.dom.Document;
41
import org.w3c.dom.Element;
45
import org.w3c.dom.Element;
42
import org.w3c.dom.Text;
46
import org.w3c.dom.Text;
Lines 48-54 Link Here
48
 * @see FormatterElement
52
 * @see FormatterElement
49
 */
53
 */
50
54
51
public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants {
55
public class XMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants, IgnoredTestListener {
52
56
53
    private static final double ONE_SECOND = 1000.0;
57
    private static final double ONE_SECOND = 1000.0;
54
58
Lines 74-88 Link Here
74
    /**
78
    /**
75
     * Element for the current test.
79
     * Element for the current test.
76
     */
80
     */
77
    private Hashtable testElements = new Hashtable();
81
    private Hashtable<Description, Element> testElements = new Hashtable<Description, Element>();
78
    /**
82
    /**
79
     * tests that failed.
83
     * tests that failed.
80
     */
84
     */
81
    private Hashtable failedTests = new Hashtable();
85
    private Hashtable failedTests = new Hashtable();
82
    /**
86
    /**
87
     * Tests that were skipped. This is a bit of a hack - tests are keyed by caseName(className) since
88
     * the Test we get for Test start isn't the same as the Test we get during test assumption fail,
89
     * so we can't easily match Test objects
90
     */
91
    private Hashtable<Description, Test> skippedTests = new Hashtable<Description, Test>();
92
    /**
93
     * Tests that were skipped. This is a bit of a hack - tests are keyed by caseName(className) since
94
     * the Test we get for Test start isn't the same as the Test we get during test assumption fail,
95
     * so we can't easily match Test objects
96
     */
97
    private Hashtable<Description, Test> ignoredTests = new Hashtable<Description, Test>();
98
    /**
83
     * Timing helper.
99
     * Timing helper.
84
     */
100
     */
85
    private Hashtable testStarts = new Hashtable();
101
    private Hashtable<Description, Long> testStarts = new Hashtable<Description, Long>();
86
    /**
102
    /**
87
     * Where to write the log to.
103
     * Where to write the log to.
88
     */
104
     */
Lines 158-166 Link Here
158
     * @throws BuildException on error.
174
     * @throws BuildException on error.
159
     */
175
     */
160
    public void endTestSuite(JUnitTest suite) throws BuildException {
176
    public void endTestSuite(JUnitTest suite) throws BuildException {
177
        /* to bring the tests attribute inline with other runners (e.g. surefire), we actually include ignored tests in
178
         * the total test count
179
         * we have an issue where tests that were skipped due to Assumption failures are recorded as started despite not
180
         * producing a final result (pass, fail, error) so we subtract their count from the overall totals
181
         */
161
        rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount());
182
        rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount());
162
        rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount());
183
        rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount());
163
        rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount());
184
        rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount());
185
        rootElement.setAttribute(ATTR_SKIPPED, "" + suite.skipCount());
164
        rootElement.setAttribute(
186
        rootElement.setAttribute(
165
            ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND));
187
            ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND));
166
        if (out != null) {
188
        if (out != null) {
Lines 193-201 Link Here
193
     * @param t the test.
215
     * @param t the test.
194
     */
216
     */
195
    public void startTest(Test t) {
217
    public void startTest(Test t) {
196
        testStarts.put(t, new Long(System.currentTimeMillis()));
218
        testStarts.put(createDescription(t), System.currentTimeMillis());
197
    }
219
    }
198
220
221
    private static Description createDescription(Test test) {
222
        return Description.createTestDescription(JUnitVersionHelper.getTestCaseClassName(test), JUnitVersionHelper.getTestCaseName(test));
223
    }
224
199
    /**
225
    /**
200
     * Interface TestListener.
226
     * Interface TestListener.
201
     *
227
     *
Lines 203-217 Link Here
203
     * @param test the test.
229
     * @param test the test.
204
     */
230
     */
205
    public void endTest(Test test) {
231
    public void endTest(Test test) {
232
        Description testDescription = createDescription(test);
233
206
        // Fix for bug #5637 - if a junit.extensions.TestSetup is
234
        // Fix for bug #5637 - if a junit.extensions.TestSetup is
207
        // used and throws an exception during setUp then startTest
235
        // used and throws an exception during setUp then startTest
208
        // would never have been called
236
        // would never have been called
209
        if (!testStarts.containsKey(test)) {
237
        if (!testStarts.containsKey(testDescription)) {
210
            startTest(test);
238
            startTest(test);
211
        }
239
        }
212
240
        Element currentTest;
213
        Element currentTest = null;
241
        if (!failedTests.containsKey(test) && !skippedTests.containsKey(testDescription) && !ignoredTests.containsKey(testDescription)) {
214
        if (!failedTests.containsKey(test)) {
215
            currentTest = doc.createElement(TESTCASE);
242
            currentTest = doc.createElement(TESTCASE);
216
            String n = JUnitVersionHelper.getTestCaseName(test);
243
            String n = JUnitVersionHelper.getTestCaseName(test);
217
            currentTest.setAttribute(ATTR_NAME,
244
            currentTest.setAttribute(ATTR_NAME,
Lines 221-235 Link Here
221
            currentTest.setAttribute(ATTR_CLASSNAME,
248
            currentTest.setAttribute(ATTR_CLASSNAME,
222
                    JUnitVersionHelper.getTestCaseClassName(test));
249
                    JUnitVersionHelper.getTestCaseClassName(test));
223
            rootElement.appendChild(currentTest);
250
            rootElement.appendChild(currentTest);
224
            testElements.put(test, currentTest);
251
            testElements.put(createDescription(test), currentTest);
225
        } else {
252
        } else {
226
            currentTest = (Element) testElements.get(test);
253
            currentTest = testElements.get(testDescription);
227
        }
254
        }
228
255
229
        Long l = (Long) testStarts.get(test);
256
        Long l = testStarts.get(createDescription(test));
230
        currentTest.setAttribute(ATTR_TIME,
257
        currentTest.setAttribute(ATTR_TIME,
231
            "" + ((System.currentTimeMillis()
258
            "" + ((System.currentTimeMillis() - l) / ONE_SECOND));
232
                   - l.longValue()) / ONE_SECOND));
233
    }
259
    }
234
260
235
    /**
261
    /**
Lines 272-280 Link Here
272
        }
298
        }
273
299
274
        Element nested = doc.createElement(type);
300
        Element nested = doc.createElement(type);
275
        Element currentTest = null;
301
        Element currentTest;
276
        if (test != null) {
302
        if (test != null) {
277
            currentTest = (Element) testElements.get(test);
303
            currentTest = testElements.get(createDescription(test));
278
        } else {
304
        } else {
279
            currentTest = rootElement;
305
            currentTest = rootElement;
280
        }
306
        }
Lines 298-301 Link Here
298
        nested.appendChild(doc.createCDATASection(output));
324
        nested.appendChild(doc.createCDATASection(output));
299
    }
325
    }
300
326
327
    @Override
328
    public void testIgnored(Test test) {
329
        String message = null;
330
        if (test != null) {
331
            if (test instanceof JUnit4TestCaseFacade) {
332
                JUnit4TestCaseFacade facade = (JUnit4TestCaseFacade) test;
333
                Ignore annotation = facade.getDescription().getAnnotation(Ignore.class);
334
                if (annotation != null && annotation.value() != null && !annotation.value().isEmpty()) {
335
                    message = annotation.value();
336
                }
337
            }
338
        }
339
        formatSkip(test, message);
340
        if (test != null) {
341
            ignoredTests.put(createDescription(test), test);
342
        }
343
    }
344
345
346
    public void formatSkip(Test test, String message) {
347
        if (test != null) {
348
            endTest(test);
349
        }
350
351
        Element nested = doc.createElement("skipped");
352
353
        if (message != null) {
354
            nested.setAttribute("message", message);
355
        }
356
357
        Element currentTest;
358
        if (test != null) {
359
            currentTest = testElements.get(createDescription(test));
360
        } else {
361
            currentTest = rootElement;
362
        }
363
364
        currentTest.appendChild(nested);
365
366
    }
367
368
    @Override
369
    public void testAssumptionFailure(Failure failure) {
370
        Test test = CustomJUnit4TestAdapterCache.getDefault().asTest(failure.getDescription());
371
        String message = failure.getMessage();
372
        formatSkip(test, message);
373
        skippedTests.put(createDescription(test), test);
374
375
    }
301
} // XMLJUnitResultFormatter
376
} // XMLJUnitResultFormatter
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/TestListenerWrapper.java (+87 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
import org.junit.internal.AssumptionViolatedException;
8
import org.junit.runner.Description;
9
import org.junit.runner.notification.Failure;
10
import org.junit.runner.notification.RunListener;
11
12
public class TestListenerWrapper extends RunListener implements 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
    private static Test convertDescription(Description description) {
42
        return JUnit4TestAdapterCache.getDefault().asTest(description);
43
    }
44
45
    @Override
46
    public void testStarted(Description description) {
47
        startTest(convertDescription(description));
48
    }
49
50
    @Override
51
    public void testFinished(Description description) {
52
        endTest(convertDescription(description));
53
    }
54
55
    @Override
56
    public void testFailure(Failure failure) {
57
        if (failure.getException() instanceof AssertionFailedError) {
58
             addFailure(convertDescription(failure.getDescription()), (AssertionFailedError) failure.getException());
59
        } else if (failure.getException() instanceof AssumptionViolatedException) {
60
             testAssumptionFailure(failure);
61
        } else {
62
             addError(convertDescription(failure.getDescription()), failure.getException());
63
        }
64
    }
65
66
    @Override
67
    public void testIgnored(Description description) {
68
        testIgnored(convertDescription(description));
69
    }
70
71
    @Override
72
    public void testIgnored(Test test) {
73
        if (wrapped instanceof IgnoredTestListener) {
74
            ((IgnoredTestListener)wrapped).testIgnored(test);
75
        }
76
    }
77
78
    @Override
79
    public void testAssumptionFailure(Failure failure) {
80
        failure.getDescription();
81
        if (wrapped instanceof IgnoredTestListener) {
82
            ((IgnoredTestListener)wrapped).testAssumptionFailure(failure);
83
        }
84
    }
85
86
87
}
(-)src/main/org/apache/tools/ant/taskdefs/optional/junit/IgnoredTestResult.java (+83 lines)
Line 0 Link Here
1
package org.apache.tools.ant.taskdefs.optional.junit;
2
3
import junit.framework.JUnit4TestAdapterCache;
4
import junit.framework.Test;
5
import junit.framework.TestListener;
6
import junit.framework.TestResult;
7
import org.junit.runner.notification.Failure;
8
9
import java.util.ArrayList;
10
import java.util.List;
11
12
/**
13
 * Records ignored and skipped tests reported as part of the execution of
14
 * JUnit 4 tests.
15
 *
16
 * @author Michael Clarke
17
 */
18
public class IgnoredTestResult extends TestResult {
19
20
21
    private List<IgnoredTestListener> listeners = new ArrayList<IgnoredTestListener>();
22
    private List<TestIgnored> ignored = new ArrayList<TestIgnored>();
23
    private List<TestIgnored> skipped = new ArrayList<TestIgnored>();
24
25
    public IgnoredTestResult() {
26
        super();
27
    }
28
29
30
    public synchronized void addListener(TestListener listener) {
31
        if (listener instanceof IgnoredTestListener) {
32
            listeners.add((IgnoredTestListener)listener);
33
        }
34
        super.addListener(listener);
35
    }
36
37
    public synchronized  void removeListener(TestListener listener) {
38
        if (listener instanceof IgnoredTestListener) {
39
            listeners.remove(listener);
40
        }
41
        super.removeListener(listener);
42
    }
43
44
    /**
45
     * Record a test as having been ignored, normally by the @Ignore annotation.
46
     * @param test the test that was ignored.
47
     * @throws Exception is the listener thrown an exception on handling the notification.
48
     */
49
    public synchronized void testIgnored(Test test) throws Exception {
50
        ignored.add(new TestIgnored(test));
51
        for (IgnoredTestListener listener : listeners) {
52
            listener.testIgnored(test);
53
        }
54
    }
55
56
    /**
57
     * Report how many tests were ignored.
58
     * @return the number of tests reported as ignored during the current execution.
59
     */
60
    public long ignoredCount() {
61
        return ignored.size();
62
    }
63
64
    /**
65
     * Records a test as having an assumption failure so JUnit will no longer be executing it.
66
     * Under normal circumstances this would be counted as a skipped test.
67
     * @param failure the details of the test and assumption failure.
68
     */
69
    public void testAssumptionFailure(Failure failure) {
70
        skipped.add(new TestIgnored(JUnit4TestAdapterCache.getDefault().asTest(failure.getDescription())));
71
        for (IgnoredTestListener listener : listeners) {
72
            listener.testAssumptionFailure(failure);
73
        }
74
    }
75
76
    /**
77
     * Report how many tests has assumption failures.
78
     * @return the number of tests that reported assumption failures during the current execution.
79
     */
80
    public long skippedCount() {
81
        return skipped.size();
82
    }
83
}
(-)src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java (-1 / +34 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 294-299 Link Here
294
    private void assertPrint(String line, String from, String to) {
302
    private void assertPrint(String line, String from, String to) {
295
        String search = from + " print to System." + to;
303
        String search = from + " print to System." + to;
296
        assertEquals(search, line);
304
        assertEquals(search, line);
305
    }
306
307
    public void testJunit4Skip() throws Exception {
308
        executeTarget("testSkippableTests");
309
310
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
311
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
312
        Document doc = dBuilder.parse(getProject().getResource("out/TEST-org.example.junit.Junit4Skippable.xml").getInputStream());
313
314
        assertEquals("Incorrect number of nodes created", 8, doc.getElementsByTagName("testcase").getLength());
315
316
        XPathFactory factory = XPathFactory.newInstance();
317
        XPath xpath = factory.newXPath();
318
319
        assertEquals("Incorrect number of skipped tests in header", 4, Integer.parseInt(xpath.compile("//testsuite/@skipped").evaluate(doc)));
320
        assertEquals("Incorrect number of error tests in header", 1, Integer.parseInt(xpath.compile("//testsuite/@errors").evaluate(doc)));
321
        assertEquals("Incorrect number of failure tests in header", 2, Integer.parseInt(xpath.compile("//testsuite/@failures").evaluate(doc)));
322
        assertEquals("Incorrect number of tests in header", 8, Integer.parseInt(xpath.compile("//testsuite/@tests").evaluate(doc)));
323
324
325
        assertEquals("Incorrect ignore message on explicit ignored test", "Please don't ignore me!", xpath.compile("//testsuite/testcase[@name='explicitIgnoreTest']/skipped/@message").evaluate(doc));
326
        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());
327
        assertEquals("Incorrect ignore message on implicit ignored test", "This test will be ignored", xpath.compile("//testsuite/testcase[@name='implicitlyIgnoreTest']/skipped/@message").evaluate(doc));
328
        assertNotNull("Implicit ignore test should have an ignore element", xpath.compile("//testsuite/testcase[@name='implicitlyIgnoreTestNoMessage']/skipped").evaluate(doc, XPathConstants.NODE));
329
297
    }
330
    }
298
331
299
}
332
}
(-)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(failure);
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 (-8 / +51 lines)
Lines 18-36 Link Here
18
18
19
package org.apache.tools.ant.taskdefs.optional.junit;
19
package org.apache.tools.ant.taskdefs.optional.junit;
20
20
21
import java.io.BufferedWriter;
22
import java.io.IOException;
23
import java.io.OutputStream;
24
import java.io.StringWriter;
25
import java.text.NumberFormat;
26
27
import junit.framework.AssertionFailedError;
21
import junit.framework.AssertionFailedError;
22
import junit.framework.JUnit4TestCaseFacade;
28
import junit.framework.Test;
23
import junit.framework.Test;
29
30
import org.apache.tools.ant.BuildException;
24
import org.apache.tools.ant.BuildException;
31
import org.apache.tools.ant.util.FileUtils;
25
import org.apache.tools.ant.util.FileUtils;
32
import org.apache.tools.ant.util.StringUtils;
26
import org.apache.tools.ant.util.StringUtils;
27
import org.junit.Ignore;
28
import org.junit.runner.notification.Failure;
33
29
30
import java.io.BufferedWriter;
31
import java.io.IOException;
32
import java.io.OutputStream;
33
import java.io.StringWriter;
34
import java.text.NumberFormat;
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.
36
 * Inspired by the PlainJUnitResultFormatter.
38
 * Inspired by the PlainJUnitResultFormatter.
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(Failure failure) {
310
        String message = failure.getMessage();
311
        formatSkip(CustomJUnit4TestAdapterCache.getDefault().asTest(failure.getDescription()), message);
269
    }
312
    }
270
}
313
}
(-)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 (+35 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
     * Received 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 the listener's author.<br />
29
     * <b>Note:</b> Tests that throw assumption failures will still report
30
     * the endTest method, which may differ from the addError and addFailure methods,
31
     * it's up for any implementing classes to handle this.
32
     * @param failure the details of the test and failure that have triggered this report.
33
     */
34
    void testAssumptionFailure(Failure failure);
35
}
(-)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 / +43 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(Failure failure) {
300
        String message = failure.getMessage();
301
        formatSkip(CustomJUnit4TestAdapterCache.getDefault().asTest(failure.getDescription()), message);
302
    }
261
} // PlainJUnitResultFormatter
303
} // 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