001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs.optional.junit;
020:
021: import java.io.IOException;
022: import java.io.OutputStream;
023: import java.io.PrintWriter;
024: import java.io.StringWriter;
025: import java.text.NumberFormat;
026: import java.util.Hashtable;
027:
028: import junit.framework.AssertionFailedError;
029: import junit.framework.Test;
030:
031: import org.apache.tools.ant.BuildException;
032: import org.apache.tools.ant.util.FileUtils;
033: import org.apache.tools.ant.util.StringUtils;
034:
035: /**
036: * Prints plain text output of the test to a specified Writer.
037: *
038: */
039:
040: public class PlainJUnitResultFormatter implements JUnitResultFormatter {
041:
042: /**
043: * Formatter for timings.
044: */
045: private NumberFormat nf = NumberFormat.getInstance();
046: /**
047: * Timing helper.
048: */
049: private Hashtable testStarts = new Hashtable();
050: /**
051: * Where to write the log to.
052: */
053: private OutputStream out;
054: /**
055: * Helper to store intermediate output.
056: */
057: private StringWriter inner;
058: /**
059: * Convenience layer on top of {@link #inner inner}.
060: */
061: private PrintWriter wri;
062: /**
063: * Suppress endTest if testcase failed.
064: */
065: private Hashtable failed = new Hashtable();
066:
067: private String systemOutput = null;
068: private String systemError = null;
069:
070: /** No arg constructor */
071: public PlainJUnitResultFormatter() {
072: inner = new StringWriter();
073: wri = new PrintWriter(inner);
074: }
075:
076: /** {@inheritDoc}. */
077: public void setOutput(OutputStream out) {
078: this .out = out;
079: }
080:
081: /** {@inheritDoc}. */
082: public void setSystemOutput(String out) {
083: systemOutput = out;
084: }
085:
086: /** {@inheritDoc}. */
087: public void setSystemError(String err) {
088: systemError = err;
089: }
090:
091: /**
092: * The whole testsuite started.
093: * @param suite the test suite
094: * @throws BuildException if unable to write the output
095: */
096: public void startTestSuite(JUnitTest suite) throws BuildException {
097: if (out == null) {
098: return; // Quick return - no output do nothing.
099: }
100: StringBuffer sb = new StringBuffer("Testsuite: ");
101: sb.append(suite.getName());
102: sb.append(StringUtils.LINE_SEP);
103: try {
104: out.write(sb.toString().getBytes());
105: out.flush();
106: } catch (IOException ex) {
107: throw new BuildException("Unable to write output", ex);
108: }
109: }
110:
111: /**
112: * The whole testsuite ended.
113: * @param suite the test suite
114: * @throws BuildException if unable to write the output
115: */
116: public void endTestSuite(JUnitTest suite) throws BuildException {
117: StringBuffer sb = new StringBuffer("Tests run: ");
118: sb.append(suite.runCount());
119: sb.append(", Failures: ");
120: sb.append(suite.failureCount());
121: sb.append(", Errors: ");
122: sb.append(suite.errorCount());
123: sb.append(", Time elapsed: ");
124: sb.append(nf.format(suite.getRunTime() / 1000.0));
125: sb.append(" sec");
126: sb.append(StringUtils.LINE_SEP);
127:
128: // append the err and output streams to the log
129: if (systemOutput != null && systemOutput.length() > 0) {
130: sb
131: .append(
132: "------------- Standard Output ---------------")
133: .append(StringUtils.LINE_SEP)
134: .append(systemOutput)
135: .append(
136: "------------- ---------------- ---------------")
137: .append(StringUtils.LINE_SEP);
138: }
139:
140: if (systemError != null && systemError.length() > 0) {
141: sb
142: .append(
143: "------------- Standard Error -----------------")
144: .append(StringUtils.LINE_SEP)
145: .append(systemError)
146: .append(
147: "------------- ---------------- ---------------")
148: .append(StringUtils.LINE_SEP);
149: }
150:
151: sb.append(StringUtils.LINE_SEP);
152:
153: if (out != null) {
154: try {
155: out.write(sb.toString().getBytes());
156: wri.close();
157: out.write(inner.toString().getBytes());
158: out.flush();
159: } catch (IOException ioex) {
160: throw new BuildException("Unable to write output", ioex);
161: } finally {
162: if (out != System.out && out != System.err) {
163: FileUtils.close(out);
164: }
165: }
166: }
167: }
168:
169: /**
170: * Interface TestListener.
171: *
172: * <p>A new Test is started.
173: * @param t the test.
174: */
175: public void startTest(Test t) {
176: testStarts.put(t, new Long(System.currentTimeMillis()));
177: failed.put(t, Boolean.FALSE);
178: }
179:
180: /**
181: * Interface TestListener.
182: *
183: * <p>A Test is finished.
184: * @param test the test.
185: */
186: public void endTest(Test test) {
187: if (Boolean.TRUE.equals(failed.get(test))) {
188: return;
189: }
190: synchronized (wri) {
191: wri.print("Testcase: "
192: + JUnitVersionHelper.getTestCaseName(test));
193: Long l = (Long) testStarts.get(test);
194: double seconds = 0;
195: // can be null if an error occurred in setUp
196: if (l != null) {
197: seconds = (System.currentTimeMillis() - l.longValue()) / 1000.0;
198: }
199:
200: wri.println(" took " + nf.format(seconds) + " sec");
201: }
202: }
203:
204: /**
205: * Interface TestListener for JUnit <= 3.4.
206: *
207: * <p>A Test failed.
208: * @param test the test.
209: * @param t the exception.
210: */
211: public void addFailure(Test test, Throwable t) {
212: formatError("\tFAILED", test, t);
213: }
214:
215: /**
216: * Interface TestListener for JUnit > 3.4.
217: *
218: * <p>A Test failed.
219: * @param test the test.
220: * @param t the assertion that failed.
221: */
222: public void addFailure(Test test, AssertionFailedError t) {
223: addFailure(test, (Throwable) t);
224: }
225:
226: /**
227: * Interface TestListener.
228: *
229: * <p>An error occurred while running the test.
230: * @param test the test.
231: * @param t the exception.
232: */
233: public void addError(Test test, Throwable t) {
234: formatError("\tCaused an ERROR", test, t);
235: }
236:
237: private void formatError(String type, Test test, Throwable t) {
238: synchronized (wri) {
239: if (test != null) {
240: endTest(test);
241: failed.put(test, Boolean.TRUE);
242: }
243:
244: wri.println(type);
245: wri.println(t.getMessage());
246: String strace = JUnitTestRunner.getFilteredTrace(t);
247: wri.print(strace);
248: wri.println("");
249: }
250: }
251:
252: } // PlainJUnitResultFormatter
|