View Javadoc
1   package org.andromda.maven.plugin.cartridge;
2   
3   import java.io.File;
4   import java.io.IOException;
5   import java.io.PrintWriter;
6   import java.io.StringWriter;
7   import java.util.ArrayList;
8   import java.util.Collection;
9   import junit.framework.AssertionFailedError;
10  import junit.framework.Test;
11  import junit.framework.TestListener;
12  import org.apache.commons.io.FileUtils;
13  
14  /**
15   * Formats the cartridge test results into the correct format.
16   *
17   * @author Chad Brandon
18   * @author Bob Fields
19   */
20  public class CartridgeTestFormatter
21      implements TestListener
22  {
23      /**
24       * Stores the report file location.
25       */
26      private File reportFile;
27  
28      /**
29       * Stores the contents of the report.
30       */
31      private StringWriter report;
32  
33      /**
34       * The print writer for the report.
35       */
36      private PrintWriter reportWriter;
37  
38      /**
39       * Ignore test failures, just show failure messages
40       */
41      private boolean testFailureIgnore = false;
42  
43      /**
44       *
45       */
46      public CartridgeTestFormatter()
47      {
48          this.report = new StringWriter();
49          this.reportWriter = new PrintWriter(this.report);
50      }
51  
52      /**
53       * Sets the file that will contain the report results (i.e.
54       * the results of the cartridge test run).
55       *
56       * @param reportFile the file to which the report output will be written.
57       */
58      public void setReportFile(final File reportFile)
59      {
60          this.reportFile = reportFile;
61      }
62  
63      /**
64       * Keeps track of the number of errors.
65       */
66      private int numberOfErrors = 0;
67  
68      /**
69       * @see junit.framework.TestListener#addError(junit.framework.Test, Throwable)
70       */
71      public void addError(
72          Test test,
73          Throwable throwable)
74      {
75          this.numberOfErrors++;
76          this.collectFailure(
77              test,
78              throwable);
79      }
80  
81      /**
82       * Keeps track of the number of failures.
83       */
84      private int numberOfFailures = 0;
85  
86      /**
87       * @see junit.framework.TestListener#addFailure(junit.framework.Test, junit.framework.AssertionFailedError)
88       */
89      public void addFailure(
90          Test test,
91          AssertionFailedError failure)
92      {
93          this.numberOfFailures++;
94          this.collectFailure(
95              test,
96              failure);
97      }
98  
99      /**
100      * @see junit.framework.TestListener#endTest(junit.framework.Test)
101      */
102     public void endTest(Test test)
103     {
104     }
105 
106     /**
107      * Keeps track of the number of tests run.
108      */
109     private int numberOfTests = 0;
110 
111     /**
112      * @see junit.framework.TestListener#startTest(junit.framework.Test)
113      */
114     public void startTest(Test test)
115     {
116         this.numberOfTests++;
117     }
118 
119     /**
120      * Stores the start time of the test suite
121      */
122     private long startTime = 0;
123 
124     /**
125      * Stores the new line separator.
126      */
127     private static final String newLine = System.getProperty("line.separator");
128 
129     /**
130      * The testsuite started.
131      * @param name
132      */
133     public void startTestSuite(final String name)
134     {
135         startTime = System.currentTimeMillis();
136         this.reportWriter.println("-------------------------------------------------------------------------------");
137         this.reportWriter.println(name + " Test Suite");
138         this.reportWriter.println("-------------------------------------------------------------------------------");
139     }
140 
141     /**
142      * Adds a failure to the current <code>failures</code>
143      * collection (these are rendered at the end of test suite
144      * execution).
145      *
146      * @param test the actual test.
147      * @param throwable the failure information.
148      */
149     private void collectFailure(
150         Test test,
151         Throwable throwable)
152     {
153         this.failures.add(new Failure(
154                 test,
155                 throwable));
156     }
157 
158     private Collection<Failure> failures = new ArrayList<Failure>();
159 
160     /**
161      * Signifies the test suite ended and returns the summary of the
162      * test.
163      *
164      * @param test the test suite being run.
165      * @return the test summary.
166      */
167     String endTestSuite(Test test)
168     {
169         final double elapsed = ((System.currentTimeMillis() - this.startTime) / 1000.0);
170         final StringBuilder summary = new StringBuilder("Tests: " + String.valueOf(this.numberOfTests) + ", ");
171         summary.append("Failures: ").append(String.valueOf(this.numberOfFailures)).append(", ");
172         summary.append("Errors: ").append(String.valueOf(this.numberOfErrors)).append(", ");
173         summary.append("Time elapsed: ").append(elapsed).append(" sec");
174         summary.append(newLine);
175         this.reportWriter.print(summary);
176         if (this.numberOfFailures > 0)
177         {
178             this.reportWriter.println("Failures: " + this.numberOfFailures);
179             this.reportWriter.println("-------------------------------------------------------------------------------");
180             int ctr = 1;
181             for (final Failure failure : this.failures)
182             {
183                 final Throwable information = failure.information;
184                 if (information instanceof AssertionFailedError)
185                 {
186                     FileComparator comparator = (FileComparator)failure.test;
187                     this.reportWriter.println(ctr + ") " + comparator.getActualFile());
188                 }
189             }
190             this.reportWriter.println("-------------------------------------------------------------------------------");
191             this.reportWriter.println();
192         }
193 
194         for (final Failure failure : this.failures)
195         {
196             FileComparator comparator = (FileComparator) failure.test;
197             final Throwable information = failure.information;
198             if (information instanceof AssertionFailedError)
199             {
200                 this.reportWriter.println("FAILURE: " + comparator.getActualFile());
201                 this.reportWriter.println(failure.information.getMessage());
202             }
203             else
204             {
205                 this.reportWriter.println("ERROR:");
206                 information.printStackTrace(this.reportWriter);
207             }
208             this.reportWriter.println();
209         }
210 
211         if (this.reportFile != null)
212         {
213             try
214             {
215                 FileUtils.writeStringToFile(this.reportFile, report.toString());
216             }
217             catch (IOException exception)
218             {
219                 if (isTestFailureIgnore())
220                 {
221                     this.reportWriter.println(exception);
222                 }
223                 else
224                 {
225                     throw new RuntimeException(exception);
226                 }
227             }
228         }
229         return summary.toString();
230     }
231 
232     /**
233      * Stores the information about a test failure.
234      */
235     private static final class Failure
236     {
237         Test test;
238         Throwable information;
239 
240         Failure(
241             final Test test,
242             final Throwable information)
243         {
244             this.test = test;
245             this.information = information;
246         }
247     }
248 
249     /**
250      * @return the testFailureIgnore
251      */
252     public boolean isTestFailureIgnore()
253     {
254         return this.testFailureIgnore;
255     }
256 
257     /**
258      * @param testFailureIgnore the testFailureIgnore to set
259      */
260     public void setTestFailureIgnore(boolean testFailureIgnore)
261     {
262         this.testFailureIgnore = testFailureIgnore;
263     }
264 }