Home | History | Annotate | Download | only in runner
      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 -&gt;
     21  * a {@link org.junit.runner.Runner} is created for each class implied by the <code>Request</code> -&gt;
     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      */
     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      */
     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      */
     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      */
     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      */
     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      */
     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      */
    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&lt;Description&gt; forward() {
    152      * return new Comparator&lt;Description&gt;() {
    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