1
2package junit.textui;
3
4import java.io.PrintStream;
5import java.text.NumberFormat;
6import java.util.Enumeration;
7
8import junit.framework.AssertionFailedError;
9import junit.framework.Test;
10import junit.framework.TestFailure;
11import junit.framework.TestListener;
12import junit.framework.TestResult;
13import junit.runner.BaseTestRunner;
14
15public class ResultPrinter implements TestListener {
16	PrintStream fWriter;
17	int fColumn= 0;
18
19	public ResultPrinter(PrintStream writer) {
20		fWriter= writer;
21	}
22
23	/* API for use by textui.TestRunner
24	 */
25
26	synchronized void print(TestResult result, long runTime) {
27		printHeader(runTime);
28	    printErrors(result);
29	    printFailures(result);
30	    printFooter(result);
31	}
32
33	void printWaitPrompt() {
34		getWriter().println();
35		getWriter().println("<RETURN> to continue");
36	}
37
38	/* Internal methods
39	 */
40
41	protected void printHeader(long runTime) {
42		getWriter().println();
43		getWriter().println("Time: "+elapsedTimeAsString(runTime));
44	}
45
46	protected void printErrors(TestResult result) {
47		printDefects(result.errors(), result.errorCount(), "error");
48	}
49
50	protected void printFailures(TestResult result) {
51		printDefects(result.failures(), result.failureCount(), "failure");
52	}
53
54	protected void printDefects(Enumeration booBoos, int count, String type) {
55		if (count == 0) return;
56		if (count == 1)
57			getWriter().println("There was " + count + " " + type + ":");
58		else
59			getWriter().println("There were " + count + " " + type + "s:");
60		for (int i= 1; booBoos.hasMoreElements(); i++) {
61			printDefect((TestFailure) booBoos.nextElement(), i);
62		}
63	}
64
65	public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes
66		printDefectHeader(booBoo, count);
67		printDefectTrace(booBoo);
68	}
69
70	protected void printDefectHeader(TestFailure booBoo, int count) {
71		// I feel like making this a println, then adding a line giving the throwable a chance to print something
72		// before we get to the stack trace.
73		getWriter().print(count + ") " + booBoo.failedTest());
74	}
75
76	protected void printDefectTrace(TestFailure booBoo) {
77		getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace()));
78	}
79
80	protected void printFooter(TestResult result) {
81		if (result.wasSuccessful()) {
82			getWriter().println();
83			getWriter().print("OK");
84			getWriter().println (" (" + result.runCount() + " test" + (result.runCount() == 1 ? "": "s") + ")");
85
86		} else {
87			getWriter().println();
88			getWriter().println("FAILURES!!!");
89			getWriter().println("Tests run: "+result.runCount()+
90				         ",  Failures: "+result.failureCount()+
91				         ",  Errors: "+result.errorCount());
92		}
93	    getWriter().println();
94	}
95
96
97	/**
98	 * Returns the formatted string of the elapsed time.
99	 * Duplicated from BaseTestRunner. Fix it.
100	 */
101	protected String elapsedTimeAsString(long runTime) {
102		return NumberFormat.getInstance().format((double)runTime/1000);
103	}
104
105	public PrintStream getWriter() {
106		return fWriter;
107	}
108	/**
109	 * @see junit.framework.TestListener#addError(Test, Throwable)
110	 */
111	public void addError(Test test, Throwable t) {
112		getWriter().print("E");
113	}
114
115	/**
116	 * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
117	 */
118	public void addFailure(Test test, AssertionFailedError t) {
119		getWriter().print("F");
120	}
121
122	/**
123	 * @see junit.framework.TestListener#endTest(Test)
124	 */
125	public void endTest(Test test) {
126	}
127
128	/**
129	 * @see junit.framework.TestListener#startTest(Test)
130	 */
131	public void startTest(Test test) {
132		getWriter().print(".");
133		if (fColumn++ >= 40) {
134			getWriter().println();
135			fColumn= 0;
136		}
137	}
138
139}
140