Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/batik/test/AbstractTest.java


1   /*
2   
3      Copyright 2001-2003  The Apache Software Foundation 
4   
5      Licensed under the Apache License, Version 2.0 (the "License");
6      you may not use this file except in compliance with the License.
7      You may obtain a copy of the License at
8   
9          http://www.apache.org/licenses/LICENSE-2.0
10  
11     Unless required by applicable law or agreed to in writing, software
12     distributed under the License is distributed on an "AS IS" BASIS,
13     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14     See the License for the specific language governing permissions and
15     limitations under the License.
16  
17   */
18  package org.apache.batik.test;
19  
20  import java.io.StringWriter;
21  import java.io.PrintWriter;
22  
23  /**
24   * Base class containing convenience methods for writing tests. <br />
25   * There are at least three approaches to write new tests derived from
26   * <tt>AbstractTest</tt>:<br /><ul>
27   * <li>You can simply override the <tt>runImplBase</tt> method and 
28   * return true or false depending on whether or not the test fails.</li>
29   * <li>You can choose to report more complex test failure conditions 
30   * by overriding the <tt>runImpl</tt> method which returns a <tt>TestReport</tt>.
31   * In that case, you can use the convenience methods such as <tt>reportFailure</tt>
32   * <tt>reportSuccess</tt> or <tt>reportException</tt> to help build a <tt>TestReport</tt>,
33   * and use the <tt>TestReport</tt>'s <tt>addDescriptionEntry</tt> to populate
34   * the report with relevant error description.</li>
35   * <li>You can choose to use the various assertion methods such as <tt>assertNull</tt>,
36   * <tt>assertEquals</tt> or <tt>assertTrue</tt>. These methods throw exceptions which
37   * will be turned in <tt>TestReports</tt> by the <tt>AbstractTest</tt>.</li>
38   * </ul>
39   * 
40   * Here are some examples:
41   * <code>
42   * public class MyTestA extends AbstractTest {
43   * public boolean runImplBase() {
44   *    if(someConditionFails){
45   *       return false;
46   *    }
47   *    return true;
48   * }
49   * }
50   * </code>
51   * 
52   * <code>
53   * public class MyTestB extends AbstractTest {
54   * public TestReport runImpl() {
55   *    if(someConditionFails){
56   *       TestReport report = reportError(MY_ERROR_CODE);
57   *       report.addDescriptionEntry(ENTRY_KEY_MY_ERROR_DESCRIPTION_KEY,
58   *                                  myErrorDescriptionValue);
59   *       return report;
60   *    }
61   * 
62   *    return reportSuccess();
63   * }
64   * </code>
65   *
66   * <code>
67   * public class MyTestC extends AbstractTest {
68   * public TestReport runImpl() throws Exception {
69   *      assertTrue(somCondition);
70   *      assertEquals(valueA, valueB);
71   *      assertNull(shouldBeNullRef);
72   *
73   *      if(someErrorCondition){
74   *         error(MY_ERROR_CODE);
75   *      }
76   *
77   *      return reportSuccess();
78   * }
79   * </code>
80   *
81   * @author <a href="mailto:vhardy@apache.lorg">Vincent Hardy</a>
82   * @version $Id: AbstractTest.java,v 1.12 2004/08/18 07:16:55 vhardy Exp $
83   */
84  public abstract class AbstractTest implements Test {
85      /**
86       * This test's id.
87       */
88      protected String id = "";
89      
90      /**
91       * This test's parent, in case this test is part of 
92       * a suite.
93       */
94      protected TestSuite parent;
95  
96      /**
97       * This test's name. If null, the class' name is returned.
98       */
99      protected String name;
100     
101     /**
102      * TestReport
103      */
104     private DefaultTestReport report 
105         = new DefaultTestReport(this) {
106                 {
107                     setErrorCode(ERROR_INTERNAL_TEST_FAILURE);
108                     setPassed(false);
109                 }
110             };
111     
112     /**
113      * Returns this <tt>Test</tt>'s name. 
114      */
115     public String getName(){
116         if(name == null){
117             if (id != null && !"".equals(id)){
118                 return id;
119             } else {
120                 return getClass().getName();
121             }
122         }
123 
124         return name;
125     }
126 
127     /**
128      * Sets this test's name
129      */
130     public void setName(String name){
131         this.name = name;
132     }
133 
134     /**
135      * Return this <tt>Test</tt>'s id.
136      */
137     public String getId(){
138         return id;
139     }
140 
141     /**
142      * Return this <tt>Test</tt>'s qualified id.
143      */
144     public String getQualifiedId(){
145         if(parent == null){
146             return getId();
147         }
148         return getParent().getQualifiedId() + "." + getId();
149     }
150 
151     /**
152      * Set this <tt>Test</tt>'s id. Null is not allowed.
153      */
154     public void setId(String id){
155         if(id == null){
156             throw new IllegalArgumentException();
157         }
158 
159         this.id = id;
160     }
161 
162     public TestSuite getParent(){
163         return parent;
164     }
165 
166     public void setParent(TestSuite parent){
167         this.parent = parent;
168     }
169     
170     /**
171      * This default implementation of the run method
172      * catches any Exception thrown from the 
173      * runImpl method and creates a <tt>TestReport</tt>
174      * indicating an internal <tt>Test</tt> failure
175      * when that happens. Otherwise, this method
176      * simply returns the <tt>TestReport</tt> generated
177      * by the <tt>runImpl</tt> method.
178      */
179     public TestReport run(){
180         try{
181             return runImpl();
182         } catch(TestErrorConditionException e){
183             return e.getTestReport(this);
184         } catch(Exception e){
185             try {
186                 
187                 StringWriter trace = new StringWriter();
188                 e.printStackTrace(new PrintWriter(trace));
189                 
190                 TestReport.Entry[] entries = new TestReport.Entry[]{
191                     new TestReport.Entry
192                         (Messages.formatMessage
193                          (TestReport.ENTRY_KEY_INTERNAL_TEST_FAILURE_EXCEPTION_CLASS, null),
194                          e.getClass().getName()),
195                     new TestReport.Entry
196                         (Messages.formatMessage
197                          (TestReport.ENTRY_KEY_INTERNAL_TEST_FAILURE_EXCEPTION_MESSAGE, null),
198                          e.getMessage()),
199                     new TestReport.Entry
200                         (Messages.formatMessage
201                          (TestReport.ENTRY_KEY_INTERNAL_TEST_FAILURE_EXCEPTION_STACK_TRACE, null),
202                          trace.toString())
203                         };
204 
205                 report.setDescription(entries);
206 
207             }catch(Exception ex){
208                 ex.printStackTrace();
209             }finally {
210                 //
211                 // In case we are in severe trouble, even filling in the 
212                 // TestReport may fail. Because the TestReport instance
213                 // was created up-front, this ensures we can return 
214                 // the report, even though it may be incomplete.
215                 e.printStackTrace();
216                 System.out.println("SERIOUS ERROR");
217                 return report;
218             }
219                 
220         }
221     }
222 
223     /**
224      * Subclasses should implement this method with the content of 
225      * the test case. Typically, implementations will choose to 
226      * catch and process all exceptions and error conditions they
227      * are looking for in the code they exercise but will let 
228      * exceptions due to their own processing propagate. 
229      */
230     public TestReport runImpl() throws Exception {
231         boolean passed = runImplBasic();
232         
233         // No exception was thrown if we get to this 
234         // portion of rumImpl. The test result is 
235         // given by passed.
236         DefaultTestReport report = new DefaultTestReport(this);
237         if(!passed){
238             report.setErrorCode(TestReport.ERROR_TEST_FAILED);
239         }
240         report.setPassed(passed);
241         return report;
242     }
243     
244     /**
245      * In the simplest test implementation, developers can 
246      * simply implement the following method.
247      */
248     public boolean runImplBasic() throws Exception {
249         return true;
250     }
251     
252     /**
253      * Convenience method.
254      */
255     public TestReport reportSuccess() {
256         DefaultTestReport report = new DefaultTestReport(this);
257         report.setPassed(true);
258         return report;
259     }
260     
261     /**
262      * Convenience method to report a simple error code.
263      */
264     public TestReport reportError(String errorCode){
265         DefaultTestReport report = new DefaultTestReport(this);
266         report.setErrorCode(errorCode);
267         report.setPassed(false);
268         return report;
269     }
270     
271     /**
272      * Convenience method to report an error condition.
273      */
274     public void error(String errorCode) throws TestErrorConditionException {
275         throw new TestErrorConditionException(errorCode);
276     }
277 
278     /**
279      * Convenience method to check that a reference is null
280      */
281     public void assertNull(Object ref) throws AssertNullException {
282         if(ref != null){
283             throw new AssertNullException();
284         }
285     }
286 
287     /**
288      * Convenience method to check that a given boolean is true.
289      */
290     public void assertTrue(boolean b) throws AssertTrueException {
291         if (!b){
292             throw new AssertTrueException();
293         }
294     }
295         
296     /**
297      * Convenience method to check for a specific condition.
298      * Returns true if both objects are null or if ref is not
299      * null and ref.equals(cmp) is true.
300      */
301     public void assertEquals(Object ref, Object cmp) throws AssertEqualsException {
302         if(ref == null && cmp != null){
303             throw new AssertEqualsException(ref, cmp);
304         }
305 
306         if(ref != null && !ref.equals(cmp)){
307             throw new AssertEqualsException(ref, cmp);
308         }
309     }
310 
311     public void assertEquals(int ref, int cmp) throws AssertEqualsException {
312         assertEquals(new Integer(ref), new Integer(cmp));
313     }
314 
315     /**
316      * Convenience method to help implementations report errors.
317      * An <tt>AbstractTest</tt> extension will typically catch 
318      * exceptions for specific error conditions it wants to point 
319      * out. For example:<tt>
320      * public TestReport runImpl() throws Exception { <br />
321      *   try{ <br />
322      *      .... something .... <br />
323      *   catch(MySpecialException e){ <br />
324      *      return reportException(MY_SPECIAL_ERROR_CODE, e); <br />
325      *   } <br />
326      * <br />
327      * public static final String MY_SPECIAL_ERROR_CODE = "myNonQualifiedClassName.my.error.code" <br />
328      * <br />
329      * </tt> <br />
330      * Note that the implementor will also need to add an entry
331      * in its Messages.properties file. That file is expected to be 
332      * in a resource file called <tt>Messages</tt> having the same package 
333      * name as the <tt>Test</tt> class, appended with "<tt>.resources</tt>".
334      */
335     public TestReport reportException(String errorCode,
336                                       Exception e){
337         DefaultTestReport report 
338             = new DefaultTestReport(this);
339 
340         StringWriter trace = new StringWriter();
341         e.printStackTrace(new PrintWriter(trace));
342         report.setErrorCode(errorCode);
343 
344                 
345         TestReport.Entry[] entries = new TestReport.Entry[]{
346             new TestReport.Entry
347                 (Messages.formatMessage
348                  (TestReport.ENTRY_KEY_REPORTED_TEST_FAILURE_EXCEPTION_CLASS, null),
349                  e.getClass().getName()),
350             new TestReport.Entry
351                 (Messages.formatMessage
352                  (TestReport.ENTRY_KEY_REPORTED_TEST_FAILURE_EXCEPTION_MESSAGE, null),
353                  e.getMessage()),
354             new TestReport.Entry
355                 (Messages.formatMessage
356                  (TestReport.ENTRY_KEY_REPORTED_TEST_FAILURE_EXCEPTION_STACK_TRACE, null),
357                  trace.toString())
358                 };
359         report.setDescription(entries);
360         report.setPassed(false);
361         return report;
362     }
363             
364 
365 }