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 }