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