001package junit.textui;
002
003
004import java.io.PrintStream;
005
006import junit.framework.Test;
007import junit.framework.TestCase;
008import junit.framework.TestResult;
009import junit.framework.TestSuite;
010import junit.runner.BaseTestRunner;
011import junit.runner.Version;
012
013/**
014 * A command line based tool to run tests.
015 * <pre>
016 * java junit.textui.TestRunner [-wait] TestCaseClass
017 * </pre>
018 * <p>
019 * TestRunner expects the name of a TestCase class as argument.
020 * If this class defines a static <code>suite</code> method it
021 * will be invoked and the returned test is run. Otherwise all
022 * the methods starting with "test" having no arguments are run.
023 * <p>
024 * When the wait command line argument is given TestRunner
025 * waits until the users types RETURN.
026 * <p>
027 * TestRunner prints a trace as the tests are executed followed by a
028 * summary at the end.
029 */
030public class TestRunner extends BaseTestRunner {
031    private ResultPrinter fPrinter;
032
033    public static final int SUCCESS_EXIT = 0;
034    public static final int FAILURE_EXIT = 1;
035    public static final int EXCEPTION_EXIT = 2;
036
037    /**
038     * Constructs a TestRunner.
039     */
040    public TestRunner() {
041        this(System.out);
042    }
043
044    /**
045     * Constructs a TestRunner using the given stream for all the output
046     */
047    public TestRunner(PrintStream writer) {
048        this(new ResultPrinter(writer));
049    }
050
051    /**
052     * Constructs a TestRunner using the given ResultPrinter all the output
053     */
054    public TestRunner(ResultPrinter printer) {
055        fPrinter = printer;
056    }
057
058    /**
059     * Runs a suite extracted from a TestCase subclass.
060     */
061    static public void run(Class<? extends TestCase> testClass) {
062        run(new TestSuite(testClass));
063    }
064
065    /**
066     * Runs a single test and collects its results.
067     * This method can be used to start a test run
068     * from your program.
069     * <pre>
070     * public static void main (String[] args) {
071     *    test.textui.TestRunner.run(suite());
072     * }
073     * </pre>
074     */
075    static public TestResult run(Test test) {
076        TestRunner runner = new TestRunner();
077        return runner.doRun(test);
078    }
079
080    /**
081     * Runs a single test and waits until the user
082     * types RETURN.
083     */
084    static public void runAndWait(Test suite) {
085        TestRunner aTestRunner = new TestRunner();
086        aTestRunner.doRun(suite, true);
087    }
088
089    @Override
090    public void testFailed(int status, Test test, Throwable e) {
091    }
092
093    @Override
094    public void testStarted(String testName) {
095    }
096
097    @Override
098    public void testEnded(String testName) {
099    }
100
101    /**
102     * Creates the TestResult to be used for the test run.
103     */
104    protected TestResult createTestResult() {
105        return new TestResult();
106    }
107
108    public TestResult doRun(Test test) {
109        return doRun(test, false);
110    }
111
112    public TestResult doRun(Test suite, boolean wait) {
113        TestResult result = createTestResult();
114        result.addListener(fPrinter);
115        long startTime = System.currentTimeMillis();
116        suite.run(result);
117        long endTime = System.currentTimeMillis();
118        long runTime = endTime - startTime;
119        fPrinter.print(result, runTime);
120
121        pause(wait);
122        return result;
123    }
124
125    protected void pause(boolean wait) {
126        if (!wait) return;
127        fPrinter.printWaitPrompt();
128        try {
129            System.in.read();
130        } catch (Exception e) {
131        }
132    }
133
134    public static void main(String[] args) {
135        TestRunner aTestRunner = new TestRunner();
136        try {
137            TestResult r = aTestRunner.start(args);
138            if (!r.wasSuccessful()) {
139                System.exit(FAILURE_EXIT);
140            }
141            System.exit(SUCCESS_EXIT);
142        } catch (Exception e) {
143            System.err.println(e.getMessage());
144            System.exit(EXCEPTION_EXIT);
145        }
146    }
147
148    /**
149     * Starts a test run. Analyzes the command line arguments and runs the given
150     * test suite.
151     */
152    public TestResult start(String[] args) throws Exception {
153        String testCase = "";
154        String method = "";
155        boolean wait = false;
156
157        for (int i = 0; i < args.length; i++) {
158            if (args[i].equals("-wait")) {
159                wait = true;
160            } else if (args[i].equals("-c")) {
161                testCase = extractClassName(args[++i]);
162            } else if (args[i].equals("-m")) {
163                String arg = args[++i];
164                int lastIndex = arg.lastIndexOf('.');
165                testCase = arg.substring(0, lastIndex);
166                method = arg.substring(lastIndex + 1);
167            } else if (args[i].equals("-v")) {
168                System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
169            } else {
170                testCase = args[i];
171            }
172        }
173
174        if (testCase.equals("")) {
175            throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
176        }
177
178        try {
179            if (!method.equals("")) {
180                return runSingleMethod(testCase, method, wait);
181            }
182            Test suite = getTest(testCase);
183            return doRun(suite, wait);
184        } catch (Exception e) {
185            throw new Exception("Could not create and run test suite: " + e);
186        }
187    }
188
189    protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception {
190        Class<? extends TestCase> testClass = loadSuiteClass(testCase).asSubclass(TestCase.class);
191        Test test = TestSuite.createTest(testClass, method);
192        return doRun(test, wait);
193    }
194
195    @Override
196    protected void runFailed(String message) {
197        System.err.println(message);
198        System.exit(FAILURE_EXIT);
199    }
200
201    public void setPrinter(ResultPrinter printer) {
202        fPrinter = printer;
203    }
204
205
206}