    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 }