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