001package org.junit.runner;
002
003import junit.runner.Version;
004import org.junit.internal.JUnitSystem;
005import org.junit.internal.RealSystem;
006import org.junit.internal.TextListener;
007import org.junit.internal.runners.JUnit38ClassRunner;
008import org.junit.runner.notification.RunListener;
009import org.junit.runner.notification.RunNotifier;
010
011/**
012 * <code>JUnitCore</code> is a facade for running tests. It supports running JUnit 4 tests,
013 * JUnit 3.8.x tests, and mixtures. To run tests from the command line, run
014 * <code>java org.junit.runner.JUnitCore TestClass1 TestClass2 ...</code>.
015 * For one-shot test runs, use the static method {@link #runClasses(Class[])}.
016 * If you want to add special listeners,
017 * create an instance of {@link org.junit.runner.JUnitCore} first and use it to run the tests.
018 *
019 * @see org.junit.runner.Result
020 * @see org.junit.runner.notification.RunListener
021 * @see org.junit.runner.Request
022 * @since 4.0
023 */
024public class JUnitCore {
025    private final RunNotifier notifier = new RunNotifier();
026
027    /**
028     * Run the tests contained in the classes named in the <code>args</code>.
029     * If all tests run successfully, exit with a status of 0. Otherwise exit with a status of 1.
030     * Write feedback while tests are running and write
031     * stack traces for all failed tests after the tests all complete.
032     *
033     * @param args names of classes in which to find tests to run
034     */
035    public static void main(String... args) {
036        Result result = new JUnitCore().runMain(new RealSystem(), args);
037        System.exit(result.wasSuccessful() ? 0 : 1);
038    }
039
040    /**
041     * Run the tests contained in <code>classes</code>. Write feedback while the tests
042     * are running and write stack traces for all failed tests after all tests complete. This is
043     * similar to {@link #main(String[])}, but intended to be used programmatically.
044     *
045     * @param classes Classes in which to find tests
046     * @return a {@link Result} describing the details of the test run and the failed tests.
047     */
048    public static Result runClasses(Class<?>... classes) {
049        return runClasses(defaultComputer(), classes);
050    }
051
052    /**
053     * Run the tests contained in <code>classes</code>. Write feedback while the tests
054     * are running and write stack traces for all failed tests after all tests complete. This is
055     * similar to {@link #main(String[])}, but intended to be used programmatically.
056     *
057     * @param computer Helps construct Runners from classes
058     * @param classes  Classes in which to find tests
059     * @return a {@link Result} describing the details of the test run and the failed tests.
060     */
061    public static Result runClasses(Computer computer, Class<?>... classes) {
062        return new JUnitCore().run(computer, classes);
063    }
064
065    /**
066     * @param system
067     * @param args from main()
068     */
069    Result runMain(JUnitSystem system, String... args) {
070        system.out().println("JUnit version " + Version.id());
071
072        JUnitCommandLineParseResult jUnitCommandLineParseResult = JUnitCommandLineParseResult.parse(args);
073
074        RunListener listener = new TextListener(system);
075        addListener(listener);
076
077        return run(jUnitCommandLineParseResult.createRequest(defaultComputer()));
078    }
079
080    /**
081     * @return the version number of this release
082     */
083    public String getVersion() {
084        return Version.id();
085    }
086
087    /**
088     * Run all the tests in <code>classes</code>.
089     *
090     * @param classes the classes containing tests
091     * @return a {@link Result} describing the details of the test run and the failed tests.
092     */
093    public Result run(Class<?>... classes) {
094        return run(defaultComputer(), classes);
095    }
096
097    /**
098     * Run all the tests in <code>classes</code>.
099     *
100     * @param computer Helps construct Runners from classes
101     * @param classes the classes containing tests
102     * @return a {@link Result} describing the details of the test run and the failed tests.
103     */
104    public Result run(Computer computer, Class<?>... classes) {
105        return run(Request.classes(computer, classes));
106    }
107
108    /**
109     * Run all the tests contained in <code>request</code>.
110     *
111     * @param request the request describing tests
112     * @return a {@link Result} describing the details of the test run and the failed tests.
113     */
114    public Result run(Request request) {
115        return run(request.getRunner());
116    }
117
118    /**
119     * Run all the tests contained in JUnit 3.8.x <code>test</code>. Here for backward compatibility.
120     *
121     * @param test the old-style test
122     * @return a {@link Result} describing the details of the test run and the failed tests.
123     */
124    public Result run(junit.framework.Test test) {
125        return run(new JUnit38ClassRunner(test));
126    }
127
128    /**
129     * Do not use. Testing purposes only.
130     */
131    public Result run(Runner runner) {
132        Result result = new Result();
133        RunListener listener = result.createListener();
134        notifier.addFirstListener(listener);
135        try {
136            notifier.fireTestRunStarted(runner.getDescription());
137            runner.run(notifier);
138            notifier.fireTestRunFinished(result);
139        } finally {
140            removeListener(listener);
141        }
142        return result;
143    }
144
145    /**
146     * Add a listener to be notified as the tests run.
147     *
148     * @param listener the listener to add
149     * @see org.junit.runner.notification.RunListener
150     */
151    public void addListener(RunListener listener) {
152        notifier.addListener(listener);
153    }
154
155    /**
156     * Remove a listener.
157     *
158     * @param listener the listener to remove
159     */
160    public void removeListener(RunListener listener) {
161        notifier.removeListener(listener);
162    }
163
164    static Computer defaultComputer() {
165        return new Computer();
166    }
167}