001package org.junit.runner;
002
003import java.util.Comparator;
004
005import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
006import org.junit.internal.requests.ClassRequest;
007import org.junit.internal.requests.FilterRequest;
008import org.junit.internal.requests.OrderingRequest;
009import org.junit.internal.requests.SortingRequest;
010import org.junit.internal.runners.ErrorReportingRunner;
011import org.junit.runner.manipulation.Filter;
012import org.junit.runner.manipulation.Ordering;
013import 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 */
029public 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}