001    package junit.framework;
002    
003    import java.util.List;
004    
005    import org.junit.Ignore;
006    import org.junit.runner.Describable;
007    import org.junit.runner.Description;
008    import org.junit.runner.Request;
009    import org.junit.runner.Runner;
010    import org.junit.runner.manipulation.Filter;
011    import org.junit.runner.manipulation.Filterable;
012    import org.junit.runner.manipulation.Orderer;
013    import org.junit.runner.manipulation.InvalidOrderingException;
014    import org.junit.runner.manipulation.NoTestsRemainException;
015    import org.junit.runner.manipulation.Orderable;
016    import org.junit.runner.manipulation.Sorter;
017    
018    /**
019     * The JUnit4TestAdapter enables running JUnit-4-style tests using a JUnit-3-style test runner.
020     *
021     * <p> To use it, add the following to a test class:
022     * <pre>
023          public static Test suite() {
024            return new JUnit4TestAdapter(<em>YourJUnit4TestClass</em>.class);
025          }
026    </pre>
027     */
028    public class JUnit4TestAdapter implements Test, Filterable, Orderable, Describable {
029        private final Class<?> fNewTestClass;
030    
031        private final Runner fRunner;
032    
033        private final JUnit4TestAdapterCache fCache;
034    
035        public JUnit4TestAdapter(Class<?> newTestClass) {
036            this(newTestClass, JUnit4TestAdapterCache.getDefault());
037        }
038    
039        public JUnit4TestAdapter(final Class<?> newTestClass, JUnit4TestAdapterCache cache) {
040            fCache = cache;
041            fNewTestClass = newTestClass;
042            fRunner = Request.classWithoutSuiteMethod(newTestClass).getRunner();
043        }
044    
045        public int countTestCases() {
046            return fRunner.testCount();
047        }
048    
049        public void run(TestResult result) {
050            fRunner.run(fCache.getNotifier(result, this));
051        }
052    
053        // reflective interface for Eclipse
054        public List<Test> getTests() {
055            return fCache.asTestList(getDescription());
056        }
057    
058        // reflective interface for Eclipse
059        public Class<?> getTestClass() {
060            return fNewTestClass;
061        }
062    
063        public Description getDescription() {
064            Description description = fRunner.getDescription();
065            return removeIgnored(description);
066        }
067    
068        private Description removeIgnored(Description description) {
069            if (isIgnored(description)) {
070                return Description.EMPTY;
071            }
072            Description result = description.childlessCopy();
073            for (Description each : description.getChildren()) {
074                Description child = removeIgnored(each);
075                if (!child.isEmpty()) {
076                    result.addChild(child);
077                }
078            }
079            return result;
080        }
081    
082        private boolean isIgnored(Description description) {
083            return description.getAnnotation(Ignore.class) != null;
084        }
085    
086        @Override
087        public String toString() {
088            return fNewTestClass.getName();
089        }
090    
091        public void filter(Filter filter) throws NoTestsRemainException {
092            filter.apply(fRunner);
093        }
094    
095        public void sort(Sorter sorter) {
096            sorter.apply(fRunner);
097        }
098    
099        /**
100         * {@inheritDoc}
101         *
102         * @since 4.13
103         */
104        public void order(Orderer orderer) throws InvalidOrderingException {
105            orderer.apply(fRunner);
106        }
107    }