001    package org.junit.runner;
002    
003    import java.util.Comparator;
004    
005    import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
006    import org.junit.internal.requests.ClassRequest;
007    import org.junit.internal.requests.FilterRequest;
008    import org.junit.internal.requests.SortingRequest;
009    import org.junit.internal.runners.ErrorReportingRunner;
010    import org.junit.runner.manipulation.Filter;
011    import org.junit.runners.model.InitializationError;
012    
013    /**
014     * A <code>Request</code> is an abstract description of tests to be run. Older versions of
015     * JUnit did not need such a concept--tests to be run were described either by classes containing
016     * tests or a tree of {@link  org.junit.Test}s. However, we want to support filtering and sorting,
017     * so we need a more abstract specification than the tests themselves and a richer
018     * specification than just the classes.
019     *
020     * <p>The flow when JUnit runs tests is that a <code>Request</code> specifies some tests to be run -&gt;
021     * a {@link org.junit.runner.Runner} is created for each class implied by the <code>Request</code> -&gt;
022     * the {@link org.junit.runner.Runner} returns a detailed {@link org.junit.runner.Description}
023     * which is a tree structure of the tests to be run.
024     *
025     * @since 4.0
026     */
027    public abstract class Request {
028        /**
029         * Create a <code>Request</code> that, when processed, will run a single test.
030         * This is done by filtering out all other tests. This method is used to support rerunning
031         * single tests.
032         *
033         * @param clazz the class of the test
034         * @param methodName the name of the test
035         * @return a <code>Request</code> that will cause a single test be run
036         */
037        public static Request method(Class<?> clazz, String methodName) {
038            Description method = Description.createTestDescription(clazz, methodName);
039            return Request.aClass(clazz).filterWith(method);
040        }
041    
042        /**
043         * Create a <code>Request</code> that, when processed, will run all the tests
044         * in a class. The odd name is necessary because <code>class</code> is a reserved word.
045         *
046         * @param clazz the class containing the tests
047         * @return a <code>Request</code> that will cause all tests in the class to be run
048         */
049        public static Request aClass(Class<?> clazz) {
050            return new ClassRequest(clazz);
051        }
052    
053        /**
054         * Create a <code>Request</code> that, when processed, will run all the tests
055         * in a class. If the class has a suite() method, it will be ignored.
056         *
057         * @param clazz the class containing the tests
058         * @return a <code>Request</code> that will cause all tests in the class to be run
059         */
060        public static Request classWithoutSuiteMethod(Class<?> clazz) {
061            return new ClassRequest(clazz, false);
062        }
063    
064        /**
065         * Create a <code>Request</code> that, when processed, will run all the tests
066         * in a set of classes.
067         *
068         * @param computer Helps construct Runners from classes
069         * @param classes the classes containing the tests
070         * @return a <code>Request</code> that will cause all tests in the classes to be run
071         */
072        public static Request classes(Computer computer, Class<?>... classes) {
073            try {
074                AllDefaultPossibilitiesBuilder builder = new AllDefaultPossibilitiesBuilder(true);
075                Runner suite = computer.getSuite(builder, classes);
076                return runner(suite);
077            } catch (InitializationError e) {
078                throw new RuntimeException(
079                        "Bug in saff's brain: Suite constructor, called as above, should always complete");
080            }
081        }
082    
083        /**
084         * Create a <code>Request</code> that, when processed, will run all the tests
085         * in a set of classes with the default <code>Computer</code>.
086         *
087         * @param classes the classes containing the tests
088         * @return a <code>Request</code> that will cause all tests in the classes to be run
089         */
090        public static Request classes(Class<?>... classes) {
091            return classes(JUnitCore.defaultComputer(), classes);
092        }
093    
094    
095        /**
096         * Creates a {@link Request} that, when processed, will report an error for the given
097         * test class with the given cause.
098         */
099        public static Request errorReport(Class<?> klass, Throwable cause) {
100            return runner(new ErrorReportingRunner(klass, cause));
101        }
102    
103        /**
104         * @param runner the runner to return
105         * @return a <code>Request</code> that will run the given runner when invoked
106         */
107        public static Request runner(final Runner runner) {
108            return new Request() {
109                @Override
110                public Runner getRunner() {
111                    return runner;
112                }
113            };
114        }
115    
116        /**
117         * Returns a {@link Runner} for this Request
118         *
119         * @return corresponding {@link Runner} for this Request
120         */
121        public abstract Runner getRunner();
122    
123        /**
124         * Returns a Request that only contains those tests that should run when
125         * <code>filter</code> is applied
126         *
127         * @param filter The {@link Filter} to apply to this Request
128         * @return the filtered Request
129         */
130        public Request filterWith(Filter filter) {
131            return new FilterRequest(this, filter);
132        }
133    
134        /**
135         * Returns a Request that only runs contains tests whose {@link Description}
136         * equals <code>desiredDescription</code>
137         *
138         * @param desiredDescription {@link Description} of those tests that should be run
139         * @return the filtered Request
140         */
141        public Request filterWith(final Description desiredDescription) {
142            return filterWith(Filter.matchMethodDescription(desiredDescription));
143        }
144    
145        /**
146         * Returns a Request whose Tests can be run in a certain order, defined by
147         * <code>comparator</code>
148         * <p>
149         * For example, here is code to run a test suite in alphabetical order:
150         * <pre>
151         * private static Comparator&lt;Description&gt; forward() {
152         * return new Comparator&lt;Description&gt;() {
153         * public int compare(Description o1, Description o2) {
154         * return o1.getDisplayName().compareTo(o2.getDisplayName());
155         * }
156         * };
157         * }
158         *
159         * public static main() {
160         * new JUnitCore().run(Request.aClass(AllTests.class).sortWith(forward()));
161         * }
162         * </pre>
163         *
164         * @param comparator definition of the order of the tests in this Request
165         * @return a Request with ordered Tests
166         */
167        public Request sortWith(Comparator<Description> comparator) {
168            return new SortingRequest(this, comparator);
169        }
170    }