1eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinpackage junit.textui;
2eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
3eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
4eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinimport java.io.PrintStream;
5eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
6eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinimport junit.framework.Test;
7eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinimport junit.framework.TestCase;
8eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinimport junit.framework.TestResult;
9eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinimport junit.framework.TestSuite;
10eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinimport junit.runner.BaseTestRunner;
11eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinimport junit.runner.Version;
12eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
13eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin/**
14eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * A command line based tool to run tests.
15eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * <pre>
16eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * java junit.textui.TestRunner [-wait] TestCaseClass
17eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * </pre>
18eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin *
19eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * <p>TestRunner expects the name of a TestCase class as argument.
20eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * If this class defines a static <code>suite</code> method it
21eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * will be invoked and the returned test is run. Otherwise all
22eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * the methods starting with "test" having no arguments are run.</p>
23eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin *
24eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * <p> When the wait command line argument is given TestRunner
25eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * waits until the users types RETURN.</p>
26eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin *
27eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * <p>TestRunner prints a trace as the tests are executed followed by a
28eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin * summary at the end.</p>
29eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin */
30eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffinpublic class TestRunner extends BaseTestRunner {
31eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	private ResultPrinter fPrinter;
32eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
33eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public static final int SUCCESS_EXIT= 0;
34eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public static final int FAILURE_EXIT= 1;
35eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public static final int EXCEPTION_EXIT= 2;
36eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
37eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	/**
38eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * Constructs a TestRunner.
39eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 */
40eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public TestRunner() {
41eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		this(System.out);
42eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
43eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
44eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	/**
45eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * Constructs a TestRunner using the given stream for all the output
46eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 */
47eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public TestRunner(PrintStream writer) {
48eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		this(new ResultPrinter(writer));
49eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
50eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
51eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	/**
52eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * Constructs a TestRunner using the given ResultPrinter all the output
53eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 */
54eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public TestRunner(ResultPrinter printer) {
55eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		fPrinter= printer;
56eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
57eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
58eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	/**
59eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * Runs a suite extracted from a TestCase subclass.
60eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 */
61eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	static public void run(Class<? extends TestCase> testClass) {
62eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		run(new TestSuite(testClass));
63eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
64eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
65eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	/**
66eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * Runs a single test and collects its results.
67eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * This method can be used to start a test run
68eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * from your program.
69eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * <pre>
70eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * public static void main (String[] args) {
71eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 *    test.textui.TestRunner.run(suite());
72eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * }
73eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * </pre>
74eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 */
75eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	static public TestResult run(Test test) {
76eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		TestRunner runner= new TestRunner();
77eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		return runner.doRun(test);
78eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
79eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
80eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	/**
81eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * Runs a single test and waits until the user
82eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * types RETURN.
83eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 */
84eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	static public void runAndWait(Test suite) {
85eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		TestRunner aTestRunner= new TestRunner();
86eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		aTestRunner.doRun(suite, true);
87eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
88eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
89eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	@Override
90eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public void testFailed(int status, Test test, Throwable t) {
91eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
92eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
93eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	@Override
94eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public void testStarted(String testName) {
95eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
96eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
97eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	@Override
98eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public void testEnded(String testName) {
99eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
100eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
101eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	/**
102eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * Creates the TestResult to be used for the test run.
103eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 */
104eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	protected TestResult createTestResult() {
105eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		return new TestResult();
106eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
107eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
108eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public TestResult doRun(Test test) {
109eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		return doRun(test, false);
110eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
111eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
112eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public TestResult doRun(Test suite, boolean wait) {
113eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		TestResult result= createTestResult();
114eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		result.addListener(fPrinter);
115eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		long startTime= System.currentTimeMillis();
116eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		suite.run(result);
117eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		long endTime= System.currentTimeMillis();
118eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		long runTime= endTime-startTime;
119eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		fPrinter.print(result, runTime);
120eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
121eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		pause(wait);
122eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		return result;
123eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
124eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
125eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	protected void pause(boolean wait) {
126eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		if (!wait) return;
127eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		fPrinter.printWaitPrompt();
128eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		try {
129eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			System.in.read();
130eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		}
131eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		catch(Exception e) {
132eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		}
133eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
134eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
135eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public static void main(String args[]) {
136eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		TestRunner aTestRunner= new TestRunner();
137eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		try {
138eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			TestResult r= aTestRunner.start(args);
139eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			if (!r.wasSuccessful())
140eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				System.exit(FAILURE_EXIT);
141eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			System.exit(SUCCESS_EXIT);
142eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		} catch(Exception e) {
143eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			System.err.println(e.getMessage());
144eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			System.exit(EXCEPTION_EXIT);
145eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		}
146eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
147eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
148eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	/**
149eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * Starts a test run. Analyzes the command line arguments and runs the given
150eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 * test suite.
151eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	 */
152eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public TestResult start(String args[]) throws Exception {
153eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		String testCase= "";
154eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		String method= "";
155eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		boolean wait= false;
156eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
157eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		for (int i= 0; i < args.length; i++) {
158eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			if (args[i].equals("-wait"))
159eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				wait= true;
160eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			else if (args[i].equals("-c"))
161eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				testCase= extractClassName(args[++i]);
162eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			else if (args[i].equals("-m")) {
163eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				String arg= args[++i];
164eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				int lastIndex= arg.lastIndexOf('.');
165eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				testCase= arg.substring(0, lastIndex);
166eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				method= arg.substring(lastIndex + 1);
167eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			} else if (args[i].equals("-v"))
168eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				System.err.println("JUnit " + Version.id() + " by Kent Beck and Erich Gamma");
169eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			else
170eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				testCase= args[i];
171eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		}
172eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
173eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		if (testCase.equals(""))
174eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			throw new Exception("Usage: TestRunner [-wait] testCaseName, where name is the name of the TestCase class");
175eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
176eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		try {
177eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			if (!method.equals(""))
178eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin				return runSingleMethod(testCase, method, wait);
179eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			Test suite= getTest(testCase);
180eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			return doRun(suite, wait);
181eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		} catch (Exception e) {
182eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin			throw new Exception("Could not create and run test suite: " + e);
183eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		}
184eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
185eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
186eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	protected TestResult runSingleMethod(String testCase, String method, boolean wait) throws Exception {
187eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		Class<? extends TestCase> testClass= loadSuiteClass(testCase).asSubclass(TestCase.class);
188eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		Test test= TestSuite.createTest(testClass, method);
189eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		return doRun(test, wait);
190eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
191eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
192eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	@Override
193eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	protected void runFailed(String message) {
194eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		System.err.println(message);
195eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		System.exit(FAILURE_EXIT);
196eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
197eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
198eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	public void setPrinter(ResultPrinter printer) {
199eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin		fPrinter= printer;
200eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin	}
201eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
202eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin
203eef35dd29ae2cf9d78c052ef8b8a49aa4da55be9Paul Duffin}