001package junit.textui; 002 003import java.io.PrintStream; 004import java.text.NumberFormat; 005import java.util.Enumeration; 006 007import junit.framework.AssertionFailedError; 008import junit.framework.Test; 009import junit.framework.TestFailure; 010import junit.framework.TestListener; 011import junit.framework.TestResult; 012import junit.runner.BaseTestRunner; 013 014public 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}