1 package org.junit.runner; 2 3 import java.util.Comparator; 4 5 import org.junit.internal.builders.AllDefaultPossibilitiesBuilder; 6 import org.junit.internal.requests.ClassRequest; 7 import org.junit.internal.requests.FilterRequest; 8 import org.junit.internal.requests.SortingRequest; 9 import org.junit.internal.runners.ErrorReportingRunner; 10 import org.junit.runner.manipulation.Filter; 11 import org.junit.runners.model.InitializationError; 12 13 /** 14 * A <code>Request</code> is an abstract description of tests to be run. Older versions of 15 * JUnit did not need such a concept--tests to be run were described either by classes containing 16 * tests or a tree of {@link org.junit.Test}s. However, we want to support filtering and sorting, 17 * so we need a more abstract specification than the tests themselves and a richer 18 * specification than just the classes. 19 * 20 * <p>The flow when JUnit runs tests is that a <code>Request</code> specifies some tests to be run -> 21 * a {@link org.junit.runner.Runner} is created for each class implied by the <code>Request</code> -> 22 * the {@link org.junit.runner.Runner} returns a detailed {@link org.junit.runner.Description} 23 * which is a tree structure of the tests to be run. 24 * 25 * @since 4.0 26 */ 27 public abstract class Request { 28 /** 29 * Create a <code>Request</code> that, when processed, will run a single test. 30 * This is done by filtering out all other tests. This method is used to support rerunning 31 * single tests. 32 * 33 * @param clazz the class of the test 34 * @param methodName the name of the test 35 * @return a <code>Request</code> that will cause a single test be run 36 */ method(Class<?> clazz, String methodName)37 public static Request method(Class<?> clazz, String methodName) { 38 Description method = Description.createTestDescription(clazz, methodName); 39 return Request.aClass(clazz).filterWith(method); 40 } 41 42 /** 43 * Create a <code>Request</code> that, when processed, will run all the tests 44 * in a class. The odd name is necessary because <code>class</code> is a reserved word. 45 * 46 * @param clazz the class containing the tests 47 * @return a <code>Request</code> that will cause all tests in the class to be run 48 */ aClass(Class<?> clazz)49 public static Request aClass(Class<?> clazz) { 50 return new ClassRequest(clazz); 51 } 52 53 /** 54 * Create a <code>Request</code> that, when processed, will run all the tests 55 * in a class. If the class has a suite() method, it will be ignored. 56 * 57 * @param clazz the class containing the tests 58 * @return a <code>Request</code> that will cause all tests in the class to be run 59 */ classWithoutSuiteMethod(Class<?> clazz)60 public static Request classWithoutSuiteMethod(Class<?> clazz) { 61 return new ClassRequest(clazz, false); 62 } 63 64 /** 65 * Create a <code>Request</code> that, when processed, will run all the tests 66 * in a set of classes. 67 * 68 * @param computer Helps construct Runners from classes 69 * @param classes the classes containing the tests 70 * @return a <code>Request</code> that will cause all tests in the classes to be run 71 */ classes(Computer computer, Class<?>... classes)72 public static Request classes(Computer computer, Class<?>... classes) { 73 try { 74 AllDefaultPossibilitiesBuilder builder = new AllDefaultPossibilitiesBuilder(true); 75 Runner suite = computer.getSuite(builder, classes); 76 return runner(suite); 77 } catch (InitializationError e) { 78 throw new RuntimeException( 79 "Bug in saff's brain: Suite constructor, called as above, should always complete"); 80 } 81 } 82 83 /** 84 * Create a <code>Request</code> that, when processed, will run all the tests 85 * in a set of classes with the default <code>Computer</code>. 86 * 87 * @param classes the classes containing the tests 88 * @return a <code>Request</code> that will cause all tests in the classes to be run 89 */ classes(Class<?>.... classes)90 public static Request classes(Class<?>... classes) { 91 return classes(JUnitCore.defaultComputer(), classes); 92 } 93 94 95 /** 96 * Creates a {@link Request} that, when processed, will report an error for the given 97 * test class with the given cause. 98 */ errorReport(Class<?> klass, Throwable cause)99 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 */ runner(final Runner runner)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 } 171