    001    package junit.textui;
    002
    003
    004    import java.io.PrintStream;
    005
    006    import junit.framework.Test;
    007    import junit.framework.TestCase;
    008    import junit.framework.TestResult;
    009    import junit.framework.TestSuite;
    010    import junit.runner.BaseTestRunner;
    011    import 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     */
    030    public 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    }