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 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 currentSuite.setTimeElapsed( time.floatValue() + currentSuite.getTimeElapsed() );
157 }
158 }
159 else if ( "failure".equals( qName ) )
160 {
161 testCase.addFailure( attributes.getValue( "message" ), attributes.getValue( "type" ) );
162 currentSuite.setNumberOfFailures( 1 + currentSuite.getNumberOfFailures() );
163 }
164 else if ( "error".equals( qName ) )
165 {
166 testCase.addFailure( attributes.getValue( "message" ), attributes.getValue( "type" ) );
167 currentSuite.setNumberOfErrors( 1 + currentSuite.getNumberOfErrors() );
168 }
169 else if ( "skipped".equals( qName ) )
170 {
171 testCase.addFailure( "skipped", "skipped" );
172 currentSuite.setNumberOfSkipped( 1 + currentSuite.getNumberOfSkipped() );
173 }
174 }
175 catch ( ParseException e )
176 {
177 throw new SAXException( e.getMessage(), e );
178 }
179 }
180
181
182 public void endElement( String uri, String localName, String qName )
183 throws SAXException
184 {
185 if ( "testcase".equals( qName ) )
186 {
187 currentSuite.getTestCases().add( testCase );
188 }
189 else if ( "failure".equals( qName ) )
190 {
191 Map failure = testCase.getFailure();
192
193 failure.put( "detail", parseCause( currentElement.toString() ) );
194 }
195 else if ( "error".equals( qName ) )
196 {
197 Map error = testCase.getFailure();
198
199 error.put( "detail", parseCause( currentElement.toString() ) );
200 }
201 else if ( "time".equals( qName ) )
202 {
203 try {
204 Number time = numberFormat.parse( currentElement.toString() );
205 defaultSuite.setTimeElapsed( time.floatValue() );
206 }
207 catch ( ParseException e )
208 {
209 throw new SAXException( e.getMessage(), e );
210 }
211 }
212
213 }
214
215
216 public void characters( char[] ch, int start, int length )
217 throws SAXException
218 {
219 String s = new String( ch, start, length );
220
221 if ( !"".equals( s.trim() ) )
222 {
223 currentElement.append( s );
224 }
225 }
226
227 private List parseCause( String detail )
228 {
229 String fullName = testCase.getFullName();
230 String name = fullName.substring( fullName.lastIndexOf( "." ) + 1 );
231 return parseCause( detail, name );
232 }
233
234 private List parseCause( String detail, String compareTo )
235 {
236 StringTokenizer stringTokenizer = new StringTokenizer( detail, "\n" );
237 List parsedDetail = new ArrayList( stringTokenizer.countTokens() );
238
239 while ( stringTokenizer.hasMoreTokens() )
240 {
241 String lineString = stringTokenizer.nextToken().trim();
242 parsedDetail.add( lineString );
243 if ( lineString.indexOf( compareTo ) >= 0 )
244 {
245 break;
246 }
247 }
248
249 return parsedDetail;
250 }
251
252 }