    001    package junit.textui;
    002
    003    import java.io.PrintStream;
    004    import java.text.NumberFormat;
    005    import java.util.Enumeration;
    006
    007    import junit.framework.AssertionFailedError;
    008    import junit.framework.Test;
    009    import junit.framework.TestFailure;
    010    import junit.framework.TestListener;
    011    import junit.framework.TestResult;
    012    import junit.runner.BaseTestRunner;
    013
    014    public class ResultPrinter implements TestListener {
    015        PrintStream fWriter;
    016        int fColumn = 0;
    017
    018        public ResultPrinter(PrintStream writer) {
    019            fWriter = writer;
    020        }
    021
    022        /* API for use by textui.TestRunner */
    023
    024        synchronized void print(TestResult result, long runTime) {
    025            printHeader(runTime);
    026            printErrors(result);
    027            printFailures(result);
    028            printFooter(result);
    029        }
    030
    031        void printWaitPrompt() {
    032            getWriter().println();
    033            getWriter().println("<RETURN> to continue");
    034        }
    035
    036        /* Internal methods */
    037
    038        protected void printHeader(long runTime) {
    039            getWriter().println();
    040            getWriter().println("Time: " + elapsedTimeAsString(runTime));
    041        }
    042
    043        protected void printErrors(TestResult result) {
    044            printDefects(result.errors(), result.errorCount(), "error");
    045        }
    046
    047        protected void printFailures(TestResult result) {
    048            printDefects(result.failures(), result.failureCount(), "failure");
    049        }
    050
    051        protected void printDefects(Enumeration<TestFailure> booBoos, int count, String type) {
    052            if (count == 0) return;
    053            if (count == 1) {
    054                getWriter().println("There was " + count + " " + type + ":");
    055            } else {
    056                getWriter().println("There were " + count + " " + type + "s:");
    057            }
    058            for (int i = 1; booBoos.hasMoreElements(); i++) {
    059                printDefect(booBoos.nextElement(), i);
    060            }
    061        }
    062
    063        public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes
    064            printDefectHeader(booBoo, count);
    065            printDefectTrace(booBoo);
    066        }
    067
    068        protected void printDefectHeader(TestFailure booBoo, int count) {
    069            // I feel like making this a println, then adding a line giving the throwable a chance to print something
    070            // before we get to the stack trace.
    071            getWriter().print(count + ") " + booBoo.failedTest());
    072        }
    073
    074        protected void printDefectTrace(TestFailure booBoo) {
    075            getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace()));
    076        }
    077
    078        protected void printFooter(TestResult result) {
    079            if (result.wasSuccessful()) {
    080                getWriter().println();
    081                getWriter().print("OK");
    082                getWriter().println(" (" + result.runCount() + " test" + (result.runCount() == 1 ? "" : "s") + ")");
    083
    084            } else {
    085                getWriter().println();
    086                getWriter().println("FAILURES!!!");
    087                getWriter().println("Tests run: " + result.runCount() +
    088                        ",  Failures: " + result.failureCount() +
    089                        ",  Errors: " + result.errorCount());
    090            }
    091            getWriter().println();
    092        }
    093
    094        /**
    095         * Returns the formatted string of the elapsed time.
    096         * Duplicated from BaseTestRunner. Fix it.
    097         */
    098        protected String elapsedTimeAsString(long runTime) {
    099            return NumberFormat.getInstance().format((double) runTime / 1000);
    100        }
    101
    102        public PrintStream getWriter() {
    103            return fWriter;
    104        }
    105
    106        /**
    107         * @see junit.framework.TestListener#addError(Test, Throwable)
    108         */
    109        public void addError(Test test, Throwable e) {
    110            getWriter().print("E");
    111        }
    112
    113        /**
    114         * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
    115         */
    116        public void addFailure(Test test, AssertionFailedError t) {
    117            getWriter().print("F");
    118        }
    119
    120        /**
    121         * @see junit.framework.TestListener#endTest(Test)
    122         */
    123        public void endTest(Test test) {
    124        }
    125
    126        /**
    127         * @see junit.framework.TestListener#startTest(Test)
    128         */
    129        public void startTest(Test test) {
    130            getWriter().print(".");
    131            if (fColumn++ >= 40) {
    132                getWriter().println();
    133                fColumn = 0;
    134            }
    135        }
    136
    137    }