1   /*
2    * Copyright 2002,2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.jelly.tags.junit;
17  
18  import java.io.PrintWriter;
19  import java.io.StringWriter;
20  
21  import junit.framework.AssertionFailedError;
22  import junit.framework.Test;
23  import junit.framework.TestListener;
24  import junit.framework.TestResult;
25  
26  import org.apache.commons.jelly.JellyTagException;
27  import org.apache.commons.jelly.MissingAttributeException;
28  import org.apache.commons.jelly.TagSupport;
29  import org.apache.commons.jelly.XMLOutput;
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.xml.sax.SAXException;
33  import org.xml.sax.helpers.AttributesImpl;
34  
35  /***
36   * This tag will run the given Test which could be an individual TestCase or a TestSuite.
37   * The TestResult can be specified to capture the output, otherwise the results are output
38   * as XML so that they can be formatted in some custom manner.
39   *
40   * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
41   * @version $Revision: 155420 $
42   */
43  public class RunTag extends TagSupport {
44  
45      /*** The Log to which logging calls will be made. */
46      private static final Log log = LogFactory.getLog(RunTag.class);
47  
48      private Test test;
49      private TestResult result;
50      private TestListener listener;
51  
52      // Tag interface
53      //-------------------------------------------------------------------------
54      public void doTag(XMLOutput output) throws JellyTagException {
55          Test test = getTest();
56          if ( test == null ) {
57              test = (Test) context.getVariable("org.apache.commons.jelly.junit.suite");
58          }
59          if ( test == null ) {
60              throw new MissingAttributeException( "test" );
61          }
62          TestResult result = getResult();
63          if ( result == null ) {
64              result = createResult(output);
65          }
66          TestListener listener = getListener();
67          if ( listener == null ) {
68              listener = createTestListener(output);
69          }
70          result.addListener(listener);
71          test.run(result);
72      }
73  
74      // Properties
75      //-------------------------------------------------------------------------
76  
77      /***
78       * Returns the TestResult used to capture the output of the test.
79       * @return TestResult
80       */
81      public TestResult getResult() {
82          return result;
83      }
84  
85      /***
86       * Returns the Test to be ran.
87       * @return Test
88       */
89      public Test getTest() {
90          return test;
91      }
92  
93      /***
94       * Sets the JUnit TestResult used to capture the results of the tst
95       * @param result The TestResult to use
96       */
97      public void setResult(TestResult result) {
98          this.result = result;
99      }
100 
101     /***
102      * Sets the JUnit Test to run which could be an individual test or a TestSuite
103      * @param test The test to run
104      */
105     public void setTest(Test test) {
106         this.test = test;
107     }
108 
109     /***
110      * Returns the listener.
111      * @return TestListener
112      */
113     public TestListener getListener() {
114         return listener;
115     }
116 
117     /***
118      * Sets the TestListener.to be used to format the output of running the unit test cases
119      * @param listener The listener to set
120      */
121     public void setListener(TestListener listener) {
122         this.listener = listener;
123     }
124 
125 
126 
127     // Implementation methods
128     //-------------------------------------------------------------------------
129 
130     /***
131      * Factory method to create a new TestResult to capture the output of
132      * the test cases
133      */
134     protected TestResult createResult(XMLOutput output) {
135         return new TestResult();
136     }
137 
138     /***
139      * Factory method to create a new TestListener to capture the output of
140      * the test cases
141      */
142     protected TestListener createTestListener(final XMLOutput output) {
143         return new TestListener() {
144             public void addError(Test test, Throwable t) {
145                 try {
146                     output.startElement("error");
147 
148                     output.startElement("message");
149                     output.write(t.getMessage());
150                     output.endElement("message");
151 
152                     output.startElement("stack");
153                     output.write( stackTraceToString(t) );
154                     output.endElement("stack");
155 
156                     output.endElement("error");
157                 }
158                 catch (SAXException e) {
159                     handleSAXException(e);
160                 }
161             }
162 
163             public void addFailure(Test test, AssertionFailedError t) {
164                 try {
165                     output.startElement("failure");
166 
167                     output.startElement("message");
168                     output.write(t.getMessage());
169                     output.endElement("message");
170 
171                     output.startElement("stack");
172                     output.write( stackTraceToString(t) );
173                     output.endElement("stack");
174 
175                     output.endElement("failure");
176                 }
177                 catch (SAXException e) {
178                     handleSAXException(e);
179                 }
180             }
181 
182             public void endTest(Test test) {
183                 try {
184                     output.endElement("test");
185                 }
186                 catch (SAXException e) {
187                     handleSAXException(e);
188                 }
189             }
190 
191             public void startTest(Test test) {
192                 try {
193                     String name = test.toString();
194                     AttributesImpl attributes = new AttributesImpl();
195                     attributes.addAttribute("", "name", "name", "CDATA", name);
196 
197                     output.startElement("test", attributes);
198                 }
199                 catch (SAXException e) {
200                     handleSAXException(e);
201                 }
202             }
203         };
204     }
205 
206     /***
207      * @return the stack trace as a String
208      */
209     protected String stackTraceToString(Throwable t) {
210         StringWriter writer = new StringWriter();
211         t.printStackTrace(new PrintWriter(writer));
212         return writer.toString();
213     }
214 
215     /***
216      * Handles SAX Exceptions
217      */
218     protected void handleSAXException(SAXException e) {
219         log.error( "Caught: " + e, e );
220     }
221 }