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 ->
021 * a {@link org.junit.runner.Runner} is created for each class implied by the <code>Request</code> ->
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<Description> forward() {
152 * return new Comparator<Description>() {
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 }