View Javadoc

1   /*
2    * Copyright 1999-2001,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  
17  package org.apache.commons.latka;
18  
19  // java imports
20  import java.io.IOException;
21  import java.io.PrintWriter;
22  import java.io.StringWriter;
23  // latka imports
24  import org.apache.commons.latka.event.LatkaEventListener;
25  import org.apache.commons.latka.event.ReportMessageEvent;
26  import org.apache.commons.latka.event.RequestErrorEvent;
27  import org.apache.commons.latka.event.RequestEvent;
28  import org.apache.commons.latka.event.RequestFailedEvent;
29  import org.apache.commons.latka.event.SuiteEvent;
30  import org.apache.commons.latka.http.Request;
31  // dom4j imports
32  import org.dom4j.Document;
33  import org.dom4j.DocumentFactory;
34  import org.dom4j.Element;
35  import org.dom4j.io.OutputFormat;
36  import org.dom4j.io.XMLWriter;
37  
38  /**
39   * This LatkaEventListener will generate an XML report
40   * of all tests run during an Latka XML suite.  XMLReporter
41   * instances are NOT reusable for multiple invocations
42   * of the {@link 
43   * org.apache.commons.latka.Latka#runTests(org.apache.commons.latka.Suite,
44   * org.apache.commons.latka.event.LatkaEventInfo) 
45   * Latka#runTests(Suite, LatkaEventInfo)} method.
46   *
47   * @author Morgan Delagrange
48   * @author dIon Gillard
49   * @version $Id: XMLReporter.java 155424 2005-02-26 13:09:29Z dirkv $
50   */
51  public class XMLReporter extends AbstractReporter implements LatkaEventListener {
52      /** dom4j document produced as output */
53      protected Document _doc         = null;
54      /** top level element of dom4j document, a <report> element*/
55      protected Element  _rootElement = null;
56      /** used for output as tests run */                   
57      protected PrintWriter _printWriter = new PrintWriter(System.out);
58  
59      protected boolean _didSuiteSucceed = true;
60  
61      protected DocumentFactory _factory = new DocumentFactory();
62  
63      /**
64       * Create an XML Reporter, initialising document property, as a new empty
65       * report with an unsuccessful suite
66       */
67      public XMLReporter() {
68          _rootElement = _factory.createElement("report");
69          //defaults to false, until a SuiteSuccess event occurs
70          _doc = _factory.createDocument(_rootElement);
71          _rootElement.addAttribute("suiteSuccess", "false");
72      }
73  
74      /**
75       * Returns the XML Document produced by this listener
76       *
77       * @return dom4j representation of the test report
78       */
79      public Document getDocument() {
80          return _doc;
81      }
82  
83      /**
84       * Returns the test report converted from dom4j to a
85       * text string.
86       *
87       * @return the test report as an XML string
88       * @throws IOException if the XML formatter cannot convert the dom4j object
89       *                     to text
90       */
91      public String getDocumentAsString() throws IOException {
92          // get the xml string from the listener
93          StringWriter writer = new StringWriter();
94          XMLWriter outputter = new XMLWriter(writer, new OutputFormat("  ", true));
95        
96          outputter.write(getDocument());
97  
98          String xmlDocument = writer.toString();
99  
100         return xmlDocument;
101     }
102 
103     /**
104      * @see AbstractReporter#requestError(RequestEvent) 
105      * @param event the event detailing the request in error
106      */
107     public void requestError(RequestEvent event) {
108         _didSuiteSucceed = false;
109 
110         _printWriter.print("E");
111         _printWriter.flush();
112 
113         RequestErrorEvent errorEvent = (RequestErrorEvent) event;
114         // <root><request><requestError><label>errortext</label>
115         // </requestError></request></root>
116         Element label = _factory.createElement("label")
117                             .addText(errorEvent.getError().toString());
118         Element requestError = _factory.createElement("requestError");
119         requestError.add(label);
120 
121         Element requestElement = createRequestElement(event);
122         requestElement.add(requestError);
123         _rootElement.add(requestElement);
124 
125     }
126 
127     /**
128      * @see AbstractReporter#requestSucceeded(RequestEvent)
129      * @param event the event detailing the request that succeeded
130      */
131     public void requestSucceeded(RequestEvent event) {
132 
133         _printWriter.print(".");
134         _printWriter.flush();
135     
136         Element requestElement = createRequestElement(event);
137         requestElement.add(_factory.createElement("requestSuccess"));
138         _rootElement.add(requestElement);
139     }
140 
141     /**
142      * @see AbstractReporter#requestFailed(RequestEvent)
143      * @param event the event detailing the request that failed
144      */
145     public void requestFailed(RequestEvent event) {
146         _didSuiteSucceed = false;
147 
148         _printWriter.print("F");
149         _printWriter.flush();
150     
151         RequestFailedEvent failedEvent = (RequestFailedEvent) event;
152 
153         // <root><request><requestFailure responseId="xxx"><label>XXX</label>
154         // </requestFailure></request></root>
155         Element label = _factory.createElement("label")
156                             .addText(failedEvent.getValidationException()
157                                                    .getMessage()
158                                                    .toString());
159         Element requestFailure = _factory.createElement("requestFailure")
160                                     .addAttribute("responseId",
161                                                   event.getResponse().toString()
162                                                  );
163         requestFailure.add(label);
164 
165         Element requestElement = createRequestElement(event);
166         requestElement.add(requestFailure);
167         _rootElement.add(requestElement);
168   }
169 
170     /**
171      * @see AbstractReporter#requestSkipped(RequestEvent)
172      * @param event the event detailing the request that was skipped
173      */
174     public void requestSkipped(RequestEvent event) {
175         _didSuiteSucceed = false;
176 
177         _printWriter.print("S");
178         _printWriter.flush();
179     
180         Request request = event.getRequest();
181         // <root><request><requestSkipped/></request></root>
182         Element requestElement = createRequestElement(event);
183         requestElement.add(_factory.createElement("requestSkipped"));
184         _rootElement.add(requestElement);
185 
186     }
187 
188     /**
189      * Add the {@link ReportMessageEvent#getMessage() message} of the provided
190      * event to the XML document as a &lt;reportMessage&gt; element with text
191      *
192      * @param event a {@link ReportMessageEvent}
193      */
194     public void reportMessage(ReportMessageEvent event) {
195         Element messageElement = _factory.createElement("reportMessage")
196           .addAttribute("message", event.getMessage());
197         _rootElement.add(messageElement);
198     }
199 
200     /**
201      * @see AbstractReporter#suiteCompleted(SuiteEvent)
202      * @param event the event detailing the completing Suite
203      */
204     public void suiteCompleted(SuiteEvent event) {
205         _rootElement.addAttribute("suiteSuccess",
206             String.valueOf(_didSuiteSucceed));
207     }
208 
209     /**
210      * Utility method that converts a RequestEvent object to its
211      * corresponding element in the dom4j object.
212      *
213      * @param event the request event sent to the listener
214      * @return the dom4j Element equivalent
215      */
216     protected Element createRequestElement(RequestEvent event) {
217         // the request object
218         Request request = event.getRequest();
219 
220         Element requestElement = _factory.createElement("request")
221             .addAttribute("requestTime",
222                           String.valueOf(request.getRequestTiming()))
223             .addAttribute("url", request.getURL().toString());
224 
225         String label = request.getLabel();
226         if (label != null) {
227             requestElement.addAttribute("label", label);
228         }
229 
230         return requestElement;
231     }
232 
233     /**
234      * During the execution, any diagnostic ouput will be sent
235      * to the stream designated here.  If no PrintWriter
236      * is set, output will be sent to standard out.
237      * 
238      * @param writer PrintWriter that will receive output generated during
239      *               the test
240      */
241     public void setPrintWriter(PrintWriter writer) {
242         _printWriter = writer;
243     }
244 
245 }