1 package org.apache.maven.plugins.surefire.report;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.text.NumberFormat;
25 import java.text.ParseException;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.StringTokenizer;
32
33 import javax.xml.parsers.ParserConfigurationException;
34 import javax.xml.parsers.SAXParser;
35 import javax.xml.parsers.SAXParserFactory;
36
37 import org.xml.sax.Attributes;
38 import org.xml.sax.SAXException;
39 import org.xml.sax.helpers.DefaultHandler;
40
41
42
43
44 public class TestSuiteXmlParser
45 extends DefaultHandler
46 {
47 private ReportTestSuite defaultSuite;
48 private ReportTestSuite currentSuite;
49 private Map classesToSuites;
50 private final NumberFormat numberFormat = NumberFormat.getInstance();
51
52
53
54
55 private StringBuffer currentElement;
56
57 private ReportTestCase testCase;
58
59 public Collection parse( String xmlPath )
60 throws ParserConfigurationException, SAXException, IOException
61 {
62 SAXParserFactory factory = SAXParserFactory.newInstance();
63
64 SAXParser saxParser = factory.newSAXParser();
65
66 classesToSuites = new HashMap();
67
68 saxParser.parse( new File( xmlPath ), this );
69
70 if ( currentSuite != defaultSuite )
71 {
72 if ( defaultSuite.getNumberOfTests() == 0 )
73 {
74 classesToSuites.remove( defaultSuite.getFullClassName() );
75 }
76 }
77
78 return classesToSuites.values();
79 }
80
81
82 public void startElement( String uri, String localName, String qName, Attributes attributes )
83 throws SAXException
84 {
85 try
86 {
87 if ( "testsuite".equals( qName ) )
88 {
89 currentSuite = defaultSuite = new ReportTestSuite();
90
91 try
92 {
93 Number time = numberFormat.parse( attributes.getValue( "time" ) );
94
95 defaultSuite.setTimeElapsed( time.floatValue() );
96 }
97 catch ( NullPointerException npe )
98 {
99 System.err.println( "WARNING: no time attribute found on testsuite element" );
100 }
101
102
103 if ( attributes.getValue( "group" ) != null && !"".equals( attributes.getValue( "group" ) ) )
104 {
105 String packageName = attributes.getValue( "group" );
106 String name = attributes.getValue( "name" );
107
108 defaultSuite.setFullClassName( packageName + "." + name );
109 }
110 else
111 {
112 String fullClassName = attributes.getValue( "name" );
113 defaultSuite.setFullClassName( fullClassName );
114 }
115
116 classesToSuites.put( defaultSuite.getFullClassName(), defaultSuite );
117 }
118 else if ( "testcase".equals( qName ) )
119 {
120 currentElement = new StringBuffer();
121
122 testCase = new ReportTestCase();
123
124 testCase.setName( attributes.getValue( "name" ) );
125
126 String fullClassName = attributes.getValue( "classname" );
127
128
129 if ( fullClassName != null )
130 {
131 currentSuite = (ReportTestSuite) classesToSuites.get( fullClassName );
132 if ( currentSuite == null )
133 {
134 currentSuite = new ReportTestSuite();
135 currentSuite.setFullClassName( fullClassName );
136 classesToSuites.put( fullClassName, currentSuite );
137 }
138 }
139
140 testCase.setFullClassName( currentSuite.getFullClassName() );
141 testCase.setClassName( currentSuite.getName() );
142 testCase.setFullName( currentSuite.getFullClassName() + "." + testCase.getName() );
143
144 String timeAsString = attributes.getValue( "time" );
145
146 Number time = new Integer( 0 );
147
148 if ( timeAsString != null )
149 {
150 time = numberFormat.parse( timeAsString );
151 }
152
153 testCase.setTime( time.floatValue() );
154
155 if ( currentSuite != defaultSuite )
156 {
157 currentSuite.setTimeElapsed( time.floatValue() + currentSuite.getTimeElapsed() );
158 }
159 }
160 else if ( "failure".equals( qName ) )
161 {
162 testCase.addFailure( attributes.getValue( "message" ), attributes.getValue( "type" ) );
163 currentSuite.setNumberOfFailures( 1 + currentSuite.getNumberOfFailures() );
164 }
165 else if ( "error".equals( qName ) )
166 {
167 testCase.addFailure( attributes.getValue( "message" ), attributes.getValue( "type" ) );
168 currentSuite.setNumberOfErrors( 1 + currentSuite.getNumberOfErrors() );
169 }
170 else if ( "skipped".equals( qName ) )
171 {
172 testCase.addFailure( "skipped", "skipped" );
173 currentSuite.setNumberOfSkipped( 1 + currentSuite.getNumberOfSkipped() );
174 }
175 }
176 catch ( ParseException e )
177 {
178 throw new SAXException( e.getMessage(), e );
179 }
180 }
181
182
183 public void endElement( String uri, String localName, String qName )
184 throws SAXException
185 {
186 if ( "testcase".equals( qName ) )
187 {
188 currentSuite.getTestCases().add( testCase );
189 }
190 else if ( "failure".equals( qName ) )
191 {
192 Map failure = testCase.getFailure();
193
194 failure.put( "detail", parseCause( currentElement.toString() ) );
195 }
196 else if ( "error".equals( qName ) )
197 {
198 Map error = testCase.getFailure();
199
200 error.put( "detail", parseCause( currentElement.toString() ) );
201 }
202 else if ( "time".equals( qName ) )
203 {
204 try
205 {
206 Number time = numberFormat.parse( currentElement.toString() );
207 defaultSuite.setTimeElapsed( time.floatValue() );
208 }
209 catch ( ParseException e )
210 {
211 throw new SAXException( e.getMessage(), e );
212 }
213 }
214
215 }
216
217
218 public void characters( char[] ch, int start, int length )
219 throws SAXException
220 {
221 String s = new String( ch, start, length );
222
223 if ( !"".equals( s.trim() ) )
224 {
225 currentElement.append( s );
226 }
227 }
228
229 private List parseCause( String detail )
230 {
231 String fullName = testCase.getFullName();
232 String name = fullName.substring( fullName.lastIndexOf( "." ) + 1 );
233 return parseCause( detail, name );
234 }
235
236 private List parseCause( String detail, String compareTo )
237 {
238 StringTokenizer stringTokenizer = new StringTokenizer( detail, "\n" );
239 List parsedDetail = new ArrayList( stringTokenizer.countTokens() );
240
241 while ( stringTokenizer.hasMoreTokens() )
242 {
243 String lineString = stringTokenizer.nextToken().trim();
244 parsedDetail.add( lineString );
245 if ( lineString.indexOf( compareTo ) >= 0 )
246 {
247 break;
248 }
249 }
250
251 return parsedDetail;
252 }
253
254 }