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 }