001 package org.junit.runners;
002
003 import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_METHOD_VALIDATOR;
004 import static org.junit.internal.runners.rules.RuleMemberValidator.RULE_VALIDATOR;
005
006 import java.util.List;
007 import java.util.concurrent.ConcurrentHashMap;
008 import java.util.concurrent.TimeUnit;
009
010 import org.junit.After;
011 import org.junit.Before;
012 import org.junit.Ignore;
013 import org.junit.Rule;
014 import org.junit.Test;
015 import org.junit.Test.None;
016 import org.junit.internal.runners.model.ReflectiveCallable;
017 import org.junit.internal.runners.statements.ExpectException;
018 import org.junit.internal.runners.statements.Fail;
019 import org.junit.internal.runners.statements.FailOnTimeout;
020 import org.junit.internal.runners.statements.InvokeMethod;
021 import org.junit.internal.runners.statements.RunAfters;
022 import org.junit.internal.runners.statements.RunBefores;
023 import org.junit.rules.MethodRule;
024 import org.junit.rules.RunRules;
025 import org.junit.rules.TestRule;
026 import org.junit.runner.Description;
027 import org.junit.runner.notification.RunNotifier;
028 import org.junit.runners.model.FrameworkMethod;
029 import org.junit.runners.model.InitializationError;
030 import org.junit.runners.model.MultipleFailureException;
031 import org.junit.runners.model.Statement;
032
033 /**
034 * Implements the JUnit 4 standard test case class model, as defined by the
035 * annotations in the org.junit package. Many users will never notice this
036 * class: it is now the default test class runner, but it should have exactly
037 * the same behavior as the old test class runner ({@code JUnit4ClassRunner}).
038 * <p>
039 * BlockJUnit4ClassRunner has advantages for writers of custom JUnit runners
040 * that are slight changes to the default behavior, however:
041 *
042 * <ul>
043 * <li>It has a much simpler implementation based on {@link Statement}s,
044 * allowing new operations to be inserted into the appropriate point in the
045 * execution flow.
046 *
047 * <li>It is published, and extension and reuse are encouraged, whereas {@code
048 * JUnit4ClassRunner} was in an internal package, and is now deprecated.
049 * </ul>
050 * <p>
051 * In turn, in 2009 we introduced {@link Rule}s. In many cases where extending
052 * BlockJUnit4ClassRunner was necessary to add new behavior, {@link Rule}s can
053 * be used, which makes the extension more reusable and composable.
054 *
055 * @since 4.5
056 */
057 public class BlockJUnit4ClassRunner extends ParentRunner<FrameworkMethod> {
058 private final ConcurrentHashMap<FrameworkMethod, Description> methodDescriptions = new ConcurrentHashMap<FrameworkMethod, Description>();
059 /**
060 * Creates a BlockJUnit4ClassRunner to run {@code klass}
061 *
062 * @throws InitializationError if the test class is malformed.
063 */
064 public BlockJUnit4ClassRunner(Class<?> klass) throws InitializationError {
065 super(klass);
066 }
067
068 //
069 // Implementation of ParentRunner
070 //
071
072 @Override
073 protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
074 Description description = describeChild(method);
075 if (isIgnored(method)) {
076 notifier.fireTestIgnored(description);
077 } else {
078 runLeaf(methodBlock(method), description, notifier);
079 }
080 }
081
082 /**
083 * Evaluates whether {@link FrameworkMethod}s are ignored based on the
084 * {@link Ignore} annotation.
085 */
086 @Override
087 protected boolean isIgnored(FrameworkMethod child) {
088 return child.getAnnotation(Ignore.class) != null;
089 }
090
091 @Override
092 protected Description describeChild(FrameworkMethod method) {
093 Description description = methodDescriptions.get(method);
094
095 if (description == null) {
096 description = Description.createTestDescription(getTestClass().getJavaClass(),
097 testName(method), method.getAnnotations());
098 methodDescriptions.putIfAbsent(method, description);
099 }
100
101 return description;
102 }
103
104 @Override
105 protected List<FrameworkMethod> getChildren() {
106 return computeTestMethods();
107 }
108
109 //
110 // Override in subclasses
111 //
112
113 /**
114 * Returns the methods that run tests. Default implementation returns all
115 * methods annotated with {@code @Test} on this class and superclasses that
116 * are not overridden.
117 */
118 protected List<FrameworkMethod> computeTestMethods() {
119 return getTestClass().getAnnotatedMethods(Test.class);
120 }
121
122 @Override
123 protected void collectInitializationErrors(List<Throwable> errors) {
124 super.collectInitializationErrors(errors);
125
126 validateNoNonStaticInnerClass(errors);
127 validateConstructor(errors);
128 validateInstanceMethods(errors);
129 validateFields(errors);
130 validateMethods(errors);
131 }
132
133 protected void validateNoNonStaticInnerClass(List<Throwable> errors) {
134 if (getTestClass().isANonStaticInnerClass()) {
135 String gripe = "The inner class " + getTestClass().getName()
136 + " is not static.";
137 errors.add(new Exception(gripe));
138 }
139 }
140
141 /**
142 * Adds to {@code errors} if the test class has more than one constructor,
143 * or if the constructor takes parameters. Override if a subclass requires
144 * different validation rules.
145 */
146 protected void validateConstructor(List<Throwable> errors) {
147 validateOnlyOneConstructor(errors);
148 validateZeroArgConstructor(errors);
149 }
150
151 /**
152 * Adds to {@code errors} if the test class has more than one constructor
153 * (do not override)
154 */
155 protected void validateOnlyOneConstructor(List<Throwable> errors) {
156 if (!hasOneConstructor()) {
157 String gripe = "Test class should have exactly one public constructor";
158 errors.add(new Exception(gripe));
159 }
160 }
161
162 /**
163 * Adds to {@code errors} if the test class's single constructor takes
164 * parameters (do not override)
165 */
166 protected void validateZeroArgConstructor(List<Throwable> errors) {
167 if (!getTestClass().isANonStaticInnerClass()
168 && hasOneConstructor()
169 && (getTestClass().getOnlyConstructor().getParameterTypes().length != 0)) {
170 String gripe = "Test class should have exactly one public zero-argument constructor";
171 errors.add(new Exception(gripe));
172 }
173 }
174
175 private boolean hasOneConstructor() {
176 return getTestClass().getJavaClass().getConstructors().length == 1;
177 }
178
179 /**
180 * Adds to {@code errors} for each method annotated with {@code @Test},
181 * {@code @Before}, or {@code @After} that is not a public, void instance
182 * method with no arguments.
183 */
184 @Deprecated
185 protected void validateInstanceMethods(List<Throwable> errors) {
186 validatePublicVoidNoArgMethods(After.class, false, errors);
187 validatePublicVoidNoArgMethods(Before.class, false, errors);
188 validateTestMethods(errors);
189
190 if (computeTestMethods().size() == 0) {
191 errors.add(new Exception("No runnable methods"));
192 }
193 }
194
195 protected void validateFields(List<Throwable> errors) {
196 RULE_VALIDATOR.validate(getTestClass(), errors);
197 }
198
199 private void validateMethods(List<Throwable> errors) {
200 RULE_METHOD_VALIDATOR.validate(getTestClass(), errors);
201 }
202
203 /**
204 * Adds to {@code errors} for each method annotated with {@code @Test}that
205 * is not a public, void instance method with no arguments.
206 */
207 protected void validateTestMethods(List<Throwable> errors) {
208 validatePublicVoidNoArgMethods(Test.class, false, errors);
209 }
210
211 /**
212 * Returns a new fixture for running a test. Default implementation executes
213 * the test class's no-argument constructor (validation should have ensured
214 * one exists).
215 */
216 protected Object createTest() throws Exception {
217 return getTestClass().getOnlyConstructor().newInstance();
218 }
219
220 /**
221 * Returns the name that describes {@code method} for {@link Description}s.
222 * Default implementation is the method's name
223 */
224 protected String testName(FrameworkMethod method) {
225 return method.getName();
226 }
227
228 /**
229 * Returns a Statement that, when executed, either returns normally if
230 * {@code method} passes, or throws an exception if {@code method} fails.
231 *
232 * Here is an outline of the default implementation:
233 *
234 * <ul>
235 * <li>Invoke {@code method} on the result of {@code createTest()}, and
236 * throw any exceptions thrown by either operation.
237 * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
238 * expecting} attribute, return normally only if the previous step threw an
239 * exception of the correct type, and throw an exception otherwise.
240 * <li>HOWEVER, if {@code method}'s {@code @Test} annotation has the {@code
241 * timeout} attribute, throw an exception if the previous step takes more
242 * than the specified number of milliseconds.
243 * <li>ALWAYS run all non-overridden {@code @Before} methods on this class
244 * and superclasses before any of the previous steps; if any throws an
245 * Exception, stop execution and pass the exception on.
246 * <li>ALWAYS run all non-overridden {@code @After} methods on this class
247 * and superclasses after any of the previous steps; all After methods are
248 * always executed: exceptions thrown by previous steps are combined, if
249 * necessary, with exceptions from After methods into a
250 * {@link MultipleFailureException}.
251 * <li>ALWAYS allow {@code @Rule} fields to modify the execution of the
252 * above steps. A {@code Rule} may prevent all execution of the above steps,
253 * or add additional behavior before and after, or modify thrown exceptions.
254 * For more information, see {@link TestRule}
255 * </ul>
256 *
257 * This can be overridden in subclasses, either by overriding this method,
258 * or the implementations creating each sub-statement.
259 */
260 protected Statement methodBlock(FrameworkMethod method) {
261 Object test;
262 try {
263 test = new ReflectiveCallable() {
264 @Override
265 protected Object runReflectiveCall() throws Throwable {
266 return createTest();
267 }
268 }.run();
269 } catch (Throwable e) {
270 return new Fail(e);
271 }
272
273 Statement statement = methodInvoker(method, test);
274 statement = possiblyExpectingExceptions(method, test, statement);
275 statement = withPotentialTimeout(method, test, statement);
276 statement = withBefores(method, test, statement);
277 statement = withAfters(method, test, statement);
278 statement = withRules(method, test, statement);
279 return statement;
280 }
281
282 //
283 // Statement builders
284 //
285
286 /**
287 * Returns a {@link Statement} that invokes {@code method} on {@code test}
288 */
289 protected Statement methodInvoker(FrameworkMethod method, Object test) {
290 return new InvokeMethod(method, test);
291 }
292
293 /**
294 * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation
295 * has the {@code expecting} attribute, return normally only if {@code next}
296 * throws an exception of the correct type, and throw an exception
297 * otherwise.
298 */
299 protected Statement possiblyExpectingExceptions(FrameworkMethod method,
300 Object test, Statement next) {
301 Test annotation = method.getAnnotation(Test.class);
302 return expectsException(annotation) ? new ExpectException(next,
303 getExpectedException(annotation)) : next;
304 }
305
306 /**
307 * Returns a {@link Statement}: if {@code method}'s {@code @Test} annotation
308 * has the {@code timeout} attribute, throw an exception if {@code next}
309 * takes more than the specified number of milliseconds.
310 */
311 @Deprecated
312 protected Statement withPotentialTimeout(FrameworkMethod method,
313 Object test, Statement next) {
314 long timeout = getTimeout(method.getAnnotation(Test.class));
315 if (timeout <= 0) {
316 return next;
317 }
318 return FailOnTimeout.builder()
319 .withTimeout(timeout, TimeUnit.MILLISECONDS)
320 .build(next);
321 }
322
323 /**
324 * Returns a {@link Statement}: run all non-overridden {@code @Before}
325 * methods on this class and superclasses before running {@code next}; if
326 * any throws an Exception, stop execution and pass the exception on.
327 */
328 protected Statement withBefores(FrameworkMethod method, Object target,
329 Statement statement) {
330 List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods(
331 Before.class);
332 return befores.isEmpty() ? statement : new RunBefores(statement,
333 befores, target);
334 }
335
336 /**
337 * Returns a {@link Statement}: run all non-overridden {@code @After}
338 * methods on this class and superclasses before running {@code next}; all
339 * After methods are always executed: exceptions thrown by previous steps
340 * are combined, if necessary, with exceptions from After methods into a
341 * {@link MultipleFailureException}.
342 */
343 protected Statement withAfters(FrameworkMethod method, Object target,
344 Statement statement) {
345 List<FrameworkMethod> afters = getTestClass().getAnnotatedMethods(
346 After.class);
347 return afters.isEmpty() ? statement : new RunAfters(statement, afters,
348 target);
349 }
350
351 private Statement withRules(FrameworkMethod method, Object target,
352 Statement statement) {
353 List<TestRule> testRules = getTestRules(target);
354 Statement result = statement;
355 result = withMethodRules(method, testRules, target, result);
356 result = withTestRules(method, testRules, result);
357
358 return result;
359 }
360
361 private Statement withMethodRules(FrameworkMethod method, List<TestRule> testRules,
362 Object target, Statement result) {
363 for (org.junit.rules.MethodRule each : getMethodRules(target)) {
364 if (!testRules.contains(each)) {
365 result = each.apply(result, method, target);
366 }
367 }
368 return result;
369 }
370
371 private List<org.junit.rules.MethodRule> getMethodRules(Object target) {
372 return rules(target);
373 }
374
375 /**
376 * @param target the test case instance
377 * @return a list of MethodRules that should be applied when executing this
378 * test
379 */
380 protected List<MethodRule> rules(Object target) {
381 List<MethodRule> rules = getTestClass().getAnnotatedMethodValues(target,
382 Rule.class, MethodRule.class);
383
384 rules.addAll(getTestClass().getAnnotatedFieldValues(target,
385 Rule.class, MethodRule.class));
386
387 return rules;
388 }
389
390 /**
391 * Returns a {@link Statement}: apply all non-static fields
392 * annotated with {@link Rule}.
393 *
394 * @param statement The base statement
395 * @return a RunRules statement if any class-level {@link Rule}s are
396 * found, or the base statement
397 */
398 private Statement withTestRules(FrameworkMethod method, List<TestRule> testRules,
399 Statement statement) {
400 return testRules.isEmpty() ? statement :
401 new RunRules(statement, testRules, describeChild(method));
402 }
403
404 /**
405 * @param target the test case instance
406 * @return a list of TestRules that should be applied when executing this
407 * test
408 */
409 protected List<TestRule> getTestRules(Object target) {
410 List<TestRule> result = getTestClass().getAnnotatedMethodValues(target,
411 Rule.class, TestRule.class);
412
413 result.addAll(getTestClass().getAnnotatedFieldValues(target,
414 Rule.class, TestRule.class));
415
416 return result;
417 }
418
419 private Class<? extends Throwable> getExpectedException(Test annotation) {
420 if (annotation == null || annotation.expected() == None.class) {
421 return null;
422 } else {
423 return annotation.expected();
424 }
425 }
426
427 private boolean expectsException(Test annotation) {
428 return getExpectedException(annotation) != null;
429 }
430
431 private long getTimeout(Test annotation) {
432 if (annotation == null) {
433 return 0;
434 }
435 return annotation.timeout();
436 }
437 }