Repository: maven-surefire
Updated Branches:
  refs/heads/master dcb4730c1 -> 989479ea8


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/ReportTestSuite.java
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/ReportTestSuite.java
 
b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/ReportTestSuite.java
index 989eda4..a76b2ee 100644
--- 
a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/ReportTestSuite.java
+++ 
b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/ReportTestSuite.java
@@ -25,9 +25,9 @@ import java.util.List;
 /**
  *
  */
-public class ReportTestSuite
+public final class ReportTestSuite
 {
-    private List<ReportTestCase> testCases = new ArrayList<ReportTestCase>();
+    private final List<ReportTestCase> testCases = new 
ArrayList<ReportTestCase>();
 
     private int numberOfErrors;
 
@@ -49,7 +49,7 @@ public class ReportTestSuite
 
     public List<ReportTestCase> getTestCases()
     {
-        return this.testCases;
+        return testCases;
     }
 
     public int getNumberOfErrors()
@@ -57,9 +57,16 @@ public class ReportTestSuite
         return numberOfErrors;
     }
 
-    public void setNumberOfErrors( int numberOfErrors )
+    public ReportTestSuite setNumberOfErrors( int numberOfErrors )
     {
         this.numberOfErrors = numberOfErrors;
+        return this;
+    }
+
+    public ReportTestSuite incrementNumberOfErrors()
+    {
+        ++numberOfErrors;
+        return this;
     }
 
     public int getNumberOfFailures()
@@ -67,9 +74,16 @@ public class ReportTestSuite
         return numberOfFailures;
     }
 
-    public void setNumberOfFailures( int numberOfFailures )
+    public ReportTestSuite setNumberOfFailures( int numberOfFailures )
     {
         this.numberOfFailures = numberOfFailures;
+        return this;
+    }
+
+    public ReportTestSuite incrementNumberOfFailures()
+    {
+        ++numberOfFailures;
+        return this;
     }
 
     public int getNumberOfSkipped()
@@ -77,9 +91,16 @@ public class ReportTestSuite
         return numberOfSkipped;
     }
 
-    public void setNumberOfSkipped( int numberOfSkipped )
+    public ReportTestSuite setNumberOfSkipped( int numberOfSkipped )
     {
         this.numberOfSkipped = numberOfSkipped;
+        return this;
+    }
+
+    public ReportTestSuite incrementNumberOfSkipped()
+    {
+        ++numberOfSkipped;
+        return this;
     }
 
     public int getNumberOfFlakes()
@@ -87,9 +108,16 @@ public class ReportTestSuite
         return numberOfFlakes;
     }
 
-    public void setNumberOfFlakes( int numberOfFlakes )
+    public ReportTestSuite setNumberOfFlakes( int numberOfFlakes )
     {
         this.numberOfFlakes = numberOfFlakes;
+        return this;
+    }
+
+    public ReportTestSuite incrementNumberOfFlakes()
+    {
+        ++numberOfFlakes;
+        return this;
     }
 
     public int getNumberOfTests()
@@ -105,9 +133,10 @@ public class ReportTestSuite
         return 0;
     }
 
-    public void setNumberOfTests( int numberOfTests )
+    public ReportTestSuite setNumberOfTests( int numberOfTests )
     {
         this.numberOfTests = numberOfTests;
+        return this;
     }
 
     public String getName()
@@ -115,9 +144,10 @@ public class ReportTestSuite
         return name;
     }
 
-    public void setName( String name )
+    public ReportTestSuite setName( String name )
     {
         this.name = name;
+        return this;
     }
 
     public String getFullClassName()
@@ -125,22 +155,13 @@ public class ReportTestSuite
         return fullClassName;
     }
 
-    public void setFullClassName( String fullClassName )
+    public ReportTestSuite setFullClassName( String fullClassName )
     {
         this.fullClassName = fullClassName;
         int lastDotPosition = fullClassName.lastIndexOf( "." );
-
         name = fullClassName.substring( lastDotPosition + 1, 
fullClassName.length() );
-
-        if ( lastDotPosition < 0 )
-        {
-            /* no package name */
-            packageName = "";
-        }
-        else
-        {
-            packageName = fullClassName.substring( 0, lastDotPosition );
-        }
+        packageName = lastDotPosition == -1 ? "" : fullClassName.substring( 0, 
lastDotPosition );
+        return this;
     }
 
     public String getPackageName()
@@ -148,9 +169,10 @@ public class ReportTestSuite
         return packageName;
     }
 
-    public void setPackageName( String packageName )
+    public ReportTestSuite setPackageName( String packageName )
     {
         this.packageName = packageName;
+        return this;
     }
 
     public float getTimeElapsed()
@@ -158,14 +180,17 @@ public class ReportTestSuite
         return this.timeElapsed;
     }
 
-    public void setTimeElapsed( float timeElapsed )
+    public ReportTestSuite setTimeElapsed( float timeElapsed )
     {
         this.timeElapsed = timeElapsed;
+        return this;
     }
 
-    public void setTestCases( List<ReportTestCase> testCases )
+    ReportTestSuite setTestCases( List<ReportTestCase> testCases )
     {
-        this.testCases = testCases;
+        this.testCases.clear();
+        this.testCases.addAll( testCases );
+        return this;
     }
 
     /**
@@ -173,7 +198,7 @@ public class ReportTestSuite
      */
     public String toString()
     {
-        return fullClassName + " [" + getNumberOfTests() + "/" + 
getNumberOfFailures() + "/" + getNumberOfErrors() + "/"
-            + getNumberOfSkipped() + "]";
+        return fullClassName + " [" + getNumberOfTests() + "/" + 
getNumberOfFailures() + "/"
+            + getNumberOfErrors() + "/" + getNumberOfSkipped() + "]";
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
 
b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
index 6c05ef6..0c9bdbd 100644
--- 
a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
+++ 
b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/SurefireReportParser.java
@@ -23,6 +23,7 @@ import java.io.File;
 import java.io.IOException;
 import java.text.NumberFormat;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -39,57 +40,47 @@ import org.xml.sax.SAXException;
 /**
  *
  */
-public class SurefireReportParser
+public final class SurefireReportParser
 {
     private static final String INCLUDES = "*.xml";
 
     private static final String EXCLUDES =
                     "*.txt, testng-failed.xml, testng-failures.xml, 
testng-results.xml, failsafe-summary*.xml";
 
-    private NumberFormat numberFormat = NumberFormat.getInstance();
-
-    private List<File> reportsDirectories;
+    private static final int PCENT = 100;
 
     private final List<ReportTestSuite> testSuites = new 
ArrayList<ReportTestSuite>();
 
-    private static final int PCENT = 100;
+    private final NumberFormat numberFormat;
 
-    public SurefireReportParser()
-    {
-    }
+    private List<File> reportsDirectories;
 
     public SurefireReportParser( List<File> reportsDirectoriesFiles, Locale 
locale )
     {
-        this.reportsDirectories = reportsDirectoriesFiles;
-
-        setLocale( locale );
+        reportsDirectories = reportsDirectoriesFiles;
+        numberFormat = NumberFormat.getInstance( locale );
     }
 
     public List<ReportTestSuite> parseXMLReportFiles()
         throws MavenReportException
     {
-        List<File> xmlReportFileList = new ArrayList<File>();
+        final Collection<File> xmlReportFiles = new ArrayList<File>();
         for ( File reportsDirectory : reportsDirectories )
         {
-            if ( !reportsDirectory.exists() )
-            {
-                continue;
-            }
-            String[] xmlReportFiles = getIncludedFiles( reportsDirectory, 
INCLUDES, EXCLUDES );
-            for ( String xmlReportFile : xmlReportFiles )
+            if ( reportsDirectory.exists() )
             {
-                File xmlReport = new File( reportsDirectory, xmlReportFile );
-                xmlReportFileList.add( xmlReport );
+                for ( String xmlReportFile : getIncludedFiles( 
reportsDirectory, INCLUDES, EXCLUDES ) )
+                {
+                    xmlReportFiles.add( new File( reportsDirectory, 
xmlReportFile ) );
+                }
             }
         }
-        TestSuiteXmlParser parser = new TestSuiteXmlParser();
-        for ( File aXmlReportFileList : xmlReportFileList )
+        final TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        for ( File aXmlReportFileList : xmlReportFiles )
         {
-            List<ReportTestSuite> suites;
-
             try
             {
-                suites = parser.parse( aXmlReportFileList.getAbsolutePath() );
+                testSuites.addAll( parser.parse( 
aXmlReportFileList.getAbsolutePath() ) );
             }
             catch ( ParserConfigurationException e )
             {
@@ -103,8 +94,6 @@ public class SurefireReportParser
             {
                 throw new MavenReportException( "Error reading JUnit XML 
report " + aXmlReportFileList, e );
             }
-
-            testSuites.addAll( suites );
         }
 
         return testSuites;
@@ -172,17 +161,12 @@ public class SurefireReportParser
 
     public void setReportsDirectory( File reportsDirectory )
     {
-        this.reportsDirectories = Collections.singletonList( reportsDirectory 
);
-    }
-
-    public final void setLocale( Locale locale )
-    {
-        numberFormat = NumberFormat.getInstance( locale );
+        reportsDirectories = Collections.singletonList( reportsDirectory );
     }
 
     public NumberFormat getNumberFormat()
     {
-        return this.numberFormat;
+        return numberFormat;
     }
 
     public Map<String, List<ReportTestSuite>> getSuitesGroupByPackage( 
List<ReportTestSuite> testSuitesList )
@@ -208,33 +192,23 @@ public class SurefireReportParser
 
     public String computePercentage( int tests, int errors, int failures, int 
skipped )
     {
-        float percentage;
-        if ( tests == 0 )
-        {
-            percentage = 0;
-        }
-        else
-        {
-            percentage = ( (float) ( tests - errors - failures - skipped ) / 
(float) tests ) * PCENT;
-        }
-
+        float percentage =
+            tests == 0 ? 0 : ( (float) ( tests - errors - failures - skipped ) 
/ (float) tests ) * PCENT;
         return numberFormat.format( percentage );
     }
 
-    public List<ReportTestCase> getFailureDetails( List<ReportTestSuite> 
testSuitesList )
+    public List<ReportTestCase> getFailureDetails( List<ReportTestSuite> 
testSuites )
     {
         List<ReportTestCase> failureDetailList = new 
ArrayList<ReportTestCase>();
 
-        for ( ReportTestSuite suite : testSuitesList )
+        for ( ReportTestSuite suite : testSuites )
         {
-            List<ReportTestCase> testCaseList = suite.getTestCases();
-
-            if ( testCaseList != null )
+            List<ReportTestCase> testCases = suite.getTestCases();
+            if ( testCases != null )
             {
-                for ( ReportTestCase tCase : testCaseList )
+                for ( ReportTestCase tCase : testCases )
                 {
-
-                    if ( tCase.getFailure() != null )
+                    if ( tCase.hasFailure() )
                     {
                         failureDetailList.add( tCase );
                     }
@@ -254,7 +228,7 @@ public class SurefireReportParser
     public static boolean hasReportFiles( File directory )
     {
         return directory != null && directory.isDirectory()
-            && getIncludedFiles( directory, INCLUDES, EXCLUDES ).length > 0;
+            && getIncludedFiles( directory, INCLUDES, EXCLUDES ).length != 0;
     }
 
     private static String[] getIncludedFiles( File directory, String includes, 
String excludes )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
 
b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
index 8b6a549..be35b75 100644
--- 
a/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
+++ 
b/surefire-report-parser/src/main/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParser.java
@@ -19,12 +19,10 @@ package org.apache.maven.plugins.surefire.report;
  * under the License.
  */
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.io.StringReader;
 import java.text.NumberFormat;
 import java.text.ParseException;
 import java.util.ArrayList;
@@ -46,9 +44,11 @@ import org.xml.sax.helpers.DefaultHandler;
 /**
  *
  */
-public class TestSuiteXmlParser
+public final class TestSuiteXmlParser
     extends DefaultHandler
 {
+    private final NumberFormat numberFormat = NumberFormat.getInstance( 
Locale.ENGLISH );
+
     private ReportTestSuite defaultSuite;
 
     private ReportTestSuite currentSuite;
@@ -57,12 +57,7 @@ public class TestSuiteXmlParser
 
     private List<ReportTestSuite> suites;
 
-    private final NumberFormat numberFormat = NumberFormat.getInstance( 
Locale.ENGLISH );
-
-    /**
-     * @noinspection StringBufferField
-     */
-    private StringBuffer currentElement;
+    private StringBuilder currentElement;
 
     private ReportTestCase testCase;
 
@@ -71,11 +66,7 @@ public class TestSuiteXmlParser
     public List<ReportTestSuite> parse( String xmlPath )
         throws ParserConfigurationException, SAXException, IOException
     {
-
-        File f = new File( xmlPath );
-
-        FileInputStream fileInputStream = new FileInputStream( f );
-
+        FileInputStream fileInputStream = new FileInputStream( new File( 
xmlPath ) );
         InputStreamReader  inputStreamReader = new InputStreamReader( 
fileInputStream, "UTF-8" );
 
         try
@@ -120,121 +111,104 @@ public class TestSuiteXmlParser
     public void startElement( String uri, String localName, String qName, 
Attributes attributes )
         throws SAXException
     {
-        if ( !valid )
-        {
-            return;
-        }
-        try
+        if ( valid )
         {
-            if ( "testsuite".equals( qName ) )
+            try
             {
-                defaultSuite = new ReportTestSuite();
-                currentSuite = defaultSuite;
-
-                try
+                if ( "testsuite".equals( qName ) )
                 {
-                    Number time = numberFormat.parse( attributes.getValue( 
"time" ) );
+                    defaultSuite = new ReportTestSuite();
+                    currentSuite = defaultSuite;
 
-                    defaultSuite.setTimeElapsed( time.floatValue() );
-                }
-                catch ( NullPointerException npe )
-                {
-                    System.err.println( "WARNING: no time attribute found on 
testsuite element" );
-                }
+                    try
+                    {
+                        Number time = numberFormat.parse( attributes.getValue( 
"time" ) );
 
-                //check if group attribute is existing
-                if ( attributes.getValue( "group" ) != null && !"".equals( 
attributes.getValue( "group" ) ) )
-                {
-                    String packageName = attributes.getValue( "group" );
-                    String name = attributes.getValue( "name" );
+                        defaultSuite.setTimeElapsed( time.floatValue() );
+                    }
+                    catch ( NullPointerException e )
+                    {
+                        System.err.println( "WARNING: no time attribute found 
on testsuite element" );
+                    }
+
+                    final String name = attributes.getValue( "name" );
+                    final String group = attributes.getValue( "group" );
+                    defaultSuite.setFullClassName( StringUtils.isBlank( group )
+                                                       ? /*name is full class 
name*/ name
+                                                       : /*group is package 
name*/ group + "." + name );
 
-                    defaultSuite.setFullClassName( packageName + "." + name );
+                    suites.add( defaultSuite );
+                    classesToSuitesIndex.put( defaultSuite.getFullClassName(), 
suites.size() - 1 );
                 }
-                else
+                else if ( "testcase".equals( qName ) )
                 {
-                    String fullClassName = attributes.getValue( "name" );
-                    defaultSuite.setFullClassName( fullClassName );
-                }
-
-                suites.add( defaultSuite );
-                classesToSuitesIndex.put( defaultSuite.getFullClassName(), 
suites.size() - 1 );
-            }
-            else if ( "testcase".equals( qName ) )
-            {
-                currentElement = new StringBuffer();
+                    currentElement = new StringBuilder();
 
-                testCase = new ReportTestCase();
+                    testCase = new ReportTestCase()
+                        .setName( attributes.getValue( "name" ) );
 
-                testCase.setName( attributes.getValue( "name" ) );
+                    String fullClassName = attributes.getValue( "classname" );
 
-                String fullClassName = attributes.getValue( "classname" );
-
-                // if the testcase declares its own classname, it may need to 
belong to its own suite
-                if ( fullClassName != null )
-                {
-                    Integer currentSuiteIndex = classesToSuitesIndex.get( 
fullClassName );
-                    if ( currentSuiteIndex == null )
+                    // if the testcase declares its own classname, it may need 
to belong to its own suite
+                    if ( fullClassName != null )
                     {
-                        currentSuite = new ReportTestSuite();
-                        currentSuite.setFullClassName( fullClassName );
-                        suites.add( currentSuite );
-                        classesToSuitesIndex.put( fullClassName, suites.size() 
- 1 );
+                        Integer currentSuiteIndex = classesToSuitesIndex.get( 
fullClassName );
+                        if ( currentSuiteIndex == null )
+                        {
+                            currentSuite = new ReportTestSuite()
+                                .setFullClassName( fullClassName );
+                            suites.add( currentSuite );
+                            classesToSuitesIndex.put( fullClassName, 
suites.size() - 1 );
+                        }
+                        else
+                        {
+                            currentSuite = suites.get( currentSuiteIndex );
+                        }
                     }
-                    else
-                    {
-                        currentSuite = suites.get( currentSuiteIndex );
-                    }
-                }
 
-                testCase.setFullClassName( currentSuite.getFullClassName() );
-                testCase.setClassName( currentSuite.getName() );
-                testCase.setFullName( currentSuite.getFullClassName() + "." + 
testCase.getName() );
+                    final String timeAsString = attributes.getValue( "time" );
+                    final Number time = StringUtils.isBlank( timeAsString ) ? 
0 : numberFormat.parse( timeAsString );
 
-                String timeAsString = attributes.getValue( "time" );
+                    testCase.setFullClassName( currentSuite.getFullClassName() 
)
+                        .setClassName( currentSuite.getName() )
+                        .setFullName( currentSuite.getFullClassName() + "." + 
testCase.getName() )
+                        .setTime( time.floatValue() );
 
-                Number time = 0;
-
-                if ( timeAsString != null )
+                    if ( currentSuite != defaultSuite )
+                    {
+                        currentSuite.setTimeElapsed( testCase.getTime() + 
currentSuite.getTimeElapsed() );
+                    }
+                }
+                else if ( "failure".equals( qName ) )
                 {
-                    time = numberFormat.parse( timeAsString );
+                    testCase.setFailure( attributes.getValue( "message" ), 
attributes.getValue( "type" ) );
+                    currentSuite.incrementNumberOfFailures();
                 }
-
-                testCase.setTime( time.floatValue() );
-
-                if ( currentSuite != defaultSuite )
+                else if ( "error".equals( qName ) )
                 {
-                    currentSuite.setTimeElapsed( time.floatValue() + 
currentSuite.getTimeElapsed() );
+                    testCase.setFailure( attributes.getValue( "message" ), 
attributes.getValue( "type" ) );
+                    currentSuite.incrementNumberOfErrors();
+                }
+                else if ( "skipped".equals( qName ) )
+                {
+                    final String message = attributes.getValue( "message" );
+                    testCase.setFailure( message != null ? message : 
"skipped", "skipped" );
+                    currentSuite.incrementNumberOfSkipped();
+                }
+                else if ( "flakyFailure".equals( qName ) || 
"flakyError".equals( qName ) )
+                {
+                    currentSuite.incrementNumberOfFlakes();
+                }
+                else if ( "failsafe-summary".equals( qName ) )
+                {
+                    valid = false;
                 }
             }
-            else if ( "failure".equals( qName ) )
-            {
-                testCase.addFailure( attributes.getValue( "message" ), 
attributes.getValue( "type" ) );
-                currentSuite.setNumberOfFailures( 1 + 
currentSuite.getNumberOfFailures() );
-            }
-            else if ( "error".equals( qName ) )
-            {
-                testCase.addFailure( attributes.getValue( "message" ), 
attributes.getValue( "type" ) );
-                currentSuite.setNumberOfErrors( 1 + 
currentSuite.getNumberOfErrors() );
-            }
-            else if ( "skipped".equals( qName ) )
-            {
-                final String message = attributes.getValue( "message" );
-                testCase.addFailure( message != null ? message : "skipped", 
"skipped" );
-                currentSuite.setNumberOfSkipped( 1 + 
currentSuite.getNumberOfSkipped() );
-            }
-            else if ( "flakyFailure".equals( qName ) || "flakyError".equals( 
qName ) )
-            {
-                currentSuite.setNumberOfFlakes( 1 + 
currentSuite.getNumberOfFlakes() );
-            }
-            else if ( "failsafe-summary".equals( qName ) )
+            catch ( ParseException e )
             {
-                valid = false;
+                throw new SAXException( e.getMessage(), e );
             }
         }
-        catch ( ParseException e )
-        {
-            throw new SAXException( e.getMessage(), e );
-        }
     }
 
     /**
@@ -247,24 +221,16 @@ public class TestSuiteXmlParser
         {
             currentSuite.getTestCases().add( testCase );
         }
-        else if ( "failure".equals( qName ) )
-        {
-            Map<String, Object> failure = testCase.getFailure();
-
-            failure.put( "detail", parseCause( currentElement.toString() ) );
-        }
-        else if ( "error".equals( qName ) )
+        else if ( "failure".equals( qName ) || "error".equals( qName ) )
         {
-            Map<String, Object> error = testCase.getFailure();
-
-            error.put( "detail", parseCause( currentElement.toString() ) );
+            testCase.setFailureDetail( currentElement.toString() )
+                .setFailureErrorLine( parseErrorLine( currentElement, 
testCase.getFullClassName() ) );
         }
         else if ( "time".equals( qName ) )
         {
             try
             {
-                Number time = numberFormat.parse( currentElement.toString() );
-                defaultSuite.setTimeElapsed( time.floatValue() );
+                defaultSuite.setTimeElapsed( numberFormat.parse( 
currentElement.toString() ).floatValue() );
             }
             catch ( ParseException e )
             {
@@ -280,40 +246,87 @@ public class TestSuiteXmlParser
     public void characters( char[] ch, int start, int length )
         throws SAXException
     {
-        if ( valid )
+        assert start >= 0;
+        assert length >= 0;
+        if ( valid && isNotBlank( start, length, ch ) )
         {
-            final String s = new String( ch, start, length );
+            currentElement.append( ch, start, length );
+        }
+    }
 
-            if ( StringUtils.isNotBlank( s ) )
+    public boolean isValid()
+    {
+        return valid;
+    }
+
+    static boolean isNotBlank( int from, int len, char... s )
+    {
+        assert from >= 0;
+        assert len >= 0;
+        if ( s != null )
+        {
+            for ( int i = 0; i < len; i++ )
             {
-                currentElement.append( s );
+                char c = s[from++];
+                if ( c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != 
'\f' )
+                {
+                    return true;
+                }
             }
         }
+        return false;
     }
 
-    @SuppressWarnings( "checkstyle:innerassignment" )
-    private List<String> parseCause( String detail )
-        throws SAXException
+    static boolean isNumeric( StringBuilder s, final int from, final int to )
     {
-        List<String> parsedDetail = new ArrayList<String>();
-        try
+        assert from >= 0;
+        assert from <= to;
+        for ( int i = from; i != to; )
         {
-            BufferedReader lines = new BufferedReader( new StringReader( 
detail ) );
-            for ( String line; ( line = lines.readLine() ) != null; )
+            if ( !Character.isDigit( s.charAt( i++ ) ) )
             {
-                parsedDetail.add( line );
+                return false;
             }
-
-            return parsedDetail;
         }
-        catch ( IOException e )
+        return from != to;
+    }
+
+    static String parseErrorLine( StringBuilder currentElement, String 
fullClassName )
+    {
+        final String[] linePatterns = { "at " + fullClassName + '.', "at " + 
fullClassName + '$' };
+        int[] indexes = lastIndexOf( currentElement, linePatterns );
+        int patternStartsAt = indexes[0];
+        if ( patternStartsAt != -1 )
         {
-            throw new SAXException( e );
+            int searchFrom = patternStartsAt + ( linePatterns[ indexes[1] ] 
).length();
+            searchFrom = 1 + currentElement.indexOf( ":", searchFrom );
+            int searchTo = currentElement.indexOf( ")", searchFrom );
+            return isNumeric( currentElement, searchFrom, searchTo )
+                ? currentElement.substring( searchFrom, searchTo )
+                : "";
         }
+        return "";
     }
 
-    public boolean isValid()
+    static int[] lastIndexOf( StringBuilder source, String... linePatterns )
     {
-        return valid;
+        int end = source.indexOf( "Caused by:" );
+        if ( end == -1 )
+        {
+            end = source.length();
+        }
+        int startsAt = -1;
+        int pattern = -1;
+        for ( int i = 0; i < linePatterns.length; i++ )
+        {
+            String linePattern = linePatterns[i];
+            int currentStartsAt = source.lastIndexOf( linePattern, end );
+            if ( currentStartsAt > startsAt )
+            {
+                startsAt = currentStartsAt;
+                pattern = i;
+            }
+        }
+        return new int[] { startsAt, pattern };
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java
 
b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java
index ecf529a..a0abbfa 100644
--- 
a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java
+++ 
b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestCaseTest.java
@@ -40,17 +40,6 @@ public class ReportTestCaseTest
         tCase = new ReportTestCase();
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    protected void tearDown()
-        throws Exception
-    {
-        super.tearDown();
-
-        tCase = null;
-    }
-
     public void testSetName()
     {
         tCase.setName( "Test Case Name" );
@@ -67,10 +56,10 @@ public class ReportTestCaseTest
 
     public void testSetFailure()
     {
-        tCase.addFailure( "messageVal", "typeVal" );
+        tCase.setFailure( "messageVal", "typeVal" );
 
-        assertEquals( "messageVal", tCase.getFailure().get( "message" ) );
-        assertEquals( "typeVal", tCase.getFailure().get( "type" ) );
+        assertEquals( "messageVal", tCase.getFailureMessage() );
+        assertEquals( "typeVal", tCase.getFailureType() );
     }
 
     public void testSetFullName()

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java
 
b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java
index 63e6eac..b9940b2 100644
--- 
a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java
+++ 
b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/ReportTestSuiteTest.java
@@ -39,21 +39,9 @@ public class ReportTestSuiteTest
         throws Exception
     {
         super.setUp();
-
         tSuite = new ReportTestSuite();
     }
 
-    /**
-     * {@inheritDoc}
-     */
-    protected void tearDown()
-        throws Exception
-    {
-        super.tearDown();
-
-        tSuite = null;
-    }
-
     public void testSetTestCases()
     {
         ReportTestCase tCase = new ReportTestCase();
@@ -67,7 +55,7 @@ public class ReportTestSuiteTest
         assertEquals( tCase, tSuite.getTestCases().get( 0 ) );
     }
 
-    public void testSetNumberdOfErrors()
+    public void testSetNumberedOfErrors()
     {
         tSuite.setNumberOfErrors( 9 );
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
 
b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
index 2bd5248..de25c4d 100644
--- 
a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
+++ 
b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/SurefireReportParserTest.java
@@ -47,21 +47,7 @@ public class SurefireReportParserTest
         throws Exception
     {
         super.setUp();
-
-        report = new SurefireReportParser();
-
-        report.setLocale( Locale.ENGLISH );
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void tearDown()
-        throws Exception
-    {
-        super.tearDown();
-
-        report = null;
+        report = new SurefireReportParser( null, Locale.ENGLISH );
     }
 
     public void testParseXMLReportFiles()
@@ -107,51 +93,41 @@ public class SurefireReportParserTest
     public void testGetSummary()
         throws Exception
     {
-        ReportTestSuite tSuite1 = new ReportTestSuite();
-
-        ReportTestSuite tSuite2 = new ReportTestSuite();
-
-        tSuite1.setNumberOfErrors( 10 );
-
-        tSuite1.setNumberOfFailures( 20 );
-
-        tSuite1.setNumberOfSkipped( 2 );
-
-        tSuite1.setTimeElapsed( 1.0f );
-
-        tSuite1.setNumberOfTests( 100 );
-
-        tSuite2.setNumberOfErrors( 10 );
-
-        tSuite2.setNumberOfFailures( 20 );
-
-        tSuite2.setNumberOfSkipped( 2 );
-
-        tSuite2.setTimeElapsed( 1.0f );
+        ReportTestSuite tSuite1 = new ReportTestSuite()
+            .setNumberOfErrors( 10 )
+            .setNumberOfFailures( 20 )
+            .setNumberOfSkipped( 2 )
+            .setTimeElapsed( 1.0f )
+            .setNumberOfTests( 100 );
 
-        tSuite2.setNumberOfTests( 100 );
+        ReportTestSuite tSuite2 = new ReportTestSuite()
+            .setNumberOfErrors( 10 )
+            .setNumberOfFailures( 20 )
+            .setNumberOfSkipped( 2 )
+            .setTimeElapsed( 1.0f )
+            .setNumberOfTests( 100 );
 
-        List<ReportTestSuite> suiteList = new ArrayList<ReportTestSuite>();
+        List<ReportTestSuite> suites = new ArrayList<ReportTestSuite>();
 
-        suiteList.add( tSuite1 );
+        suites.add( tSuite1 );
 
-        suiteList.add( tSuite2 );
+        suites.add( tSuite2 );
 
-        Map<String, String> testMap = report.getSummary( suiteList );
+        Map<String, String> testMap = report.getSummary( suites );
 
-        assertEquals( 20, Integer.parseInt( testMap.get( "totalErrors" 
).toString() ) );
+        assertEquals( 20, Integer.parseInt( testMap.get( "totalErrors" ) ) );
 
-        assertEquals( 40, Integer.parseInt( testMap.get( "totalFailures" 
).toString() ) );
+        assertEquals( 40, Integer.parseInt( testMap.get( "totalFailures" ) ) );
 
-        assertEquals( 200, Integer.parseInt( testMap.get( "totalTests" 
).toString() ) );
+        assertEquals( 200, Integer.parseInt( testMap.get( "totalTests" ) ) );
 
-        assertEquals( 4, Integer.parseInt( testMap.get( "totalSkipped" 
).toString() ) );
+        assertEquals( 4, Integer.parseInt( testMap.get( "totalSkipped" ) ) );
 
         NumberFormat numberFormat = report.getNumberFormat();
 
-        assertEquals( 2.0f, numberFormat.parse( testMap.get( 
"totalElapsedTime" ).toString() ).floatValue(), 0.0f );
+        assertEquals( 2.0f, numberFormat.parse( testMap.get( 
"totalElapsedTime" ) ).floatValue(), 0.0f );
 
-        assertEquals( 68.00f, numberFormat.parse( (String) testMap.get( 
"totalPercentage" ) ).floatValue(), 0 );
+        assertEquals( 68.00f, numberFormat.parse( testMap.get( 
"totalPercentage" ) ).floatValue(), 0 );
     }
 
     public void testGetSuitesGroupByPackage()
@@ -168,15 +144,15 @@ public class SurefireReportParserTest
 
         tSuite3.setPackageName( "Package2" );
 
-        List<ReportTestSuite> suiteList = new ArrayList<ReportTestSuite>();
+        List<ReportTestSuite> suites = new ArrayList<ReportTestSuite>();
 
-        suiteList.add( tSuite1 );
+        suites.add( tSuite1 );
 
-        suiteList.add( tSuite2 );
+        suites.add( tSuite2 );
 
-        suiteList.add( tSuite3 );
+        suites.add( tSuite3 );
 
-        Map<String, List<ReportTestSuite>> groupMap = 
report.getSuitesGroupByPackage( suiteList );
+        Map<String, List<ReportTestSuite>> groupMap = 
report.getSuitesGroupByPackage( suites );
 
         assertEquals( 2, groupMap.size() );
 
@@ -207,36 +183,36 @@ public class SurefireReportParserTest
 
         ReportTestCase tCase3 = new ReportTestCase();
 
-        tCase1.addFailure( null, null );
+        tCase1.setFailure( null, IllegalArgumentException.class.getName() );
 
-        tCase3.addFailure( null, null );
+        tCase3.setFailure( "index: 0, size: 0", 
IndexOutOfBoundsException.class.getName() );
 
-        List<ReportTestCase> tCaseList = new ArrayList<ReportTestCase>();
+        List<ReportTestCase> tCases = new ArrayList<ReportTestCase>();
 
-        List<ReportTestCase> tCaseList2 = new ArrayList<ReportTestCase>();
+        List<ReportTestCase> tCases2 = new ArrayList<ReportTestCase>();
 
-        tCaseList.add( tCase1 );
+        tCases.add( tCase1 );
 
-        tCaseList.add( tCase2 );
+        tCases.add( tCase2 );
 
-        tCaseList2.add( tCase3 );
+        tCases2.add( tCase3 );
 
-        tSuite1.setTestCases( tCaseList );
+        tSuite1.setTestCases( tCases );
 
-        tSuite2.setTestCases( tCaseList2 );
+        tSuite2.setTestCases( tCases2 );
 
-        List<ReportTestSuite> suiteList = new ArrayList<ReportTestSuite>();
+        List<ReportTestSuite> suites = new ArrayList<ReportTestSuite>();
 
-        suiteList.add( tSuite1 );
+        suites.add( tSuite1 );
 
-        suiteList.add( tSuite2 );
+        suites.add( tSuite2 );
 
-        List<ReportTestCase> failList = report.getFailureDetails( suiteList );
+        List<ReportTestCase> failures = report.getFailureDetails( suites );
 
-        assertEquals( 2, failList.size() );
+        assertEquals( 2, failures.size() );
 
-        assertEquals( tCase1, failList.get( 0 ) );
+        assertEquals( tCase1, failures.get( 0 ) );
 
-        assertEquals( tCase3, failList.get( 1 ) );
+        assertEquals( tCase3, failures.get( 1 ) );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
 
b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
index beaf1b2..474423b 100644
--- 
a/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
+++ 
b/surefire-report-parser/src/test/java/org/apache/maven/plugins/surefire/report/TestSuiteXmlParserTest.java
@@ -21,22 +21,25 @@ package org.apache.maven.plugins.surefire.report;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.Collection;
+import java.util.List;
 
-import javax.xml.parsers.ParserConfigurationException;
+import org.junit.Test;
 
-import junit.framework.TestCase;
-import org.xml.sax.SAXException;
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+import static org.hamcrest.MatcherAssert.assertThat;
 
 /**
  * @author Kristian Rosenvold
  */
 public class TestSuiteXmlParserTest
-    extends TestCase
 {
+    private static final String[] linePatterns = { "at org.apache.Test.", "at 
org.apache.Test$" };
+
+    @Test
     public void testParse()
         throws Exception
     {
@@ -78,11 +81,77 @@ public class TestSuiteXmlParserTest
             "  </testcase>\n" +
             "</testsuite>";
         InputStream byteArrayIs = new ByteArrayInputStream( xml.getBytes() );
-        Collection<ReportTestSuite> parse = testSuiteXmlParser.parse( new 
InputStreamReader(byteArrayIs, "UTF-8") );
+        List<ReportTestSuite> parse = testSuiteXmlParser.parse( new 
InputStreamReader(byteArrayIs, "UTF-8") );
+        assertThat( parse.size(), is( 1 ) );
+        ReportTestSuite report = parse.get( 0 );
+        assertThat( report.getFullClassName(), is( 
"wellFormedXmlFailures.TestSurefire3" ) );
+        assertThat( report.getName(), is( "TestSurefire3" ) );
+        assertThat( report.getPackageName(), is( "wellFormedXmlFailures" ) );
+        assertThat( report.getNumberOfTests(), is( 4 ) );
+        assertThat( report.getNumberOfSkipped(), is( 0 ) );
+        assertThat( report.getNumberOfErrors(), is( 0 ) );
+        assertThat( report.getNumberOfFailures(), is( 4 ) );
+        assertThat( report.getNumberOfFlakes(), is( 0 ) );
+        assertThat( report.getTimeElapsed(), is( 0.005f ) );
+        assertThat( report.getTestCases().size(), is( 4 ) );
+
+        List<ReportTestCase> tests = report.getTestCases();
+        assertThat( tests.get( 0 ).getFullClassName(), is( 
"wellFormedXmlFailures.TestSurefire3" ) );
+        assertThat( tests.get( 0 ).getName(), is( "testLower" ) );
+        assertThat( tests.get( 0 ).getFailureDetail(),
+                    is( "junit.framework.AssertionFailedError: <\n"
+                            + "\tat 
junit.framework.Assert.fail(Assert.java:47)\n"
+                            + "\tat 
wellFormedXmlFailures.TestSurefire3.testLower(TestSurefire3.java:30)\n" ) );
+        assertThat( tests.get( 0 ).getClassName(), is( "TestSurefire3" ) );
+        assertThat( tests.get( 0 ).getTime(), is( 0.005f ) );
+        assertThat( tests.get( 0 ).getFailureErrorLine(), is( "30" ) );
+        assertThat( tests.get( 0 ).getFailureMessage(), is( "<" ) );
+        assertThat( tests.get( 0 ).getFullName(), is( 
"wellFormedXmlFailures.TestSurefire3.testLower" ) );
+        assertThat( tests.get( 0 ).getFailureType(), is( 
"junit.framework.AssertionFailedError" ) );
+
+        assertThat( tests.get( 1 ).getFullClassName(), is( 
"wellFormedXmlFailures.TestSurefire3" ) );
+        assertThat( tests.get( 1 ).getName(), is( "testU0000" ) );
+        assertThat( tests.get( 1 ).getFailureDetail(),
+                    is( "junit.framework.AssertionFailedError:  \n"
+                            + "\tat 
junit.framework.Assert.fail(Assert.java:47)\n"
+                            + "\tat 
wellFormedXmlFailures.TestSurefire3.testU0000(TestSurefire3.java:40)\n" ) );
+        assertThat( tests.get( 1 ).getClassName(), is( "TestSurefire3" ) );
+        assertThat( tests.get( 1 ).getTime(), is( 0f ) );
+        assertThat( tests.get( 1 ).getFailureErrorLine(), is( "40" ) );
+        assertThat( tests.get( 1 ).getFailureMessage(), is( "&0#;" ) );
+        assertThat( tests.get( 1 ).getFullName(), is( 
"wellFormedXmlFailures.TestSurefire3.testU0000" ) );
+        assertThat( tests.get( 1 ).getFailureType(), is( 
"junit.framework.AssertionFailedError" ) );
+
+        assertThat( tests.get( 2 ).getFullClassName(), is( 
"wellFormedXmlFailures.TestSurefire3" ) );
+        assertThat( tests.get( 2 ).getName(), is( "testGreater" ) );
+        assertThat( tests.get( 2 ).getFailureDetail(),
+                    is( "junit.framework.AssertionFailedError: >\n"
+                            + "\tat 
junit.framework.Assert.fail(Assert.java:47)\n"
+                            + "\tat 
wellFormedXmlFailures.TestSurefire3.testGreater(TestSurefire3.java:35)\n" ) );
+        assertThat( tests.get( 2 ).getClassName(), is( "TestSurefire3" ) );
+        assertThat( tests.get( 2 ).getTime(), is( 0f ) );
+        assertThat( tests.get( 2 ).getFailureErrorLine(), is( "35" ) );
+        assertThat( tests.get( 2 ).getFailureMessage(), is( ">" ) );
+        assertThat( tests.get( 2 ).getFullName(), is( 
"wellFormedXmlFailures.TestSurefire3.testGreater" ) );
+        assertThat( tests.get( 2 ).getFailureType(), is( 
"junit.framework.AssertionFailedError" ) );
+
+        assertThat( tests.get( 3 ).getFullClassName(), is( 
"wellFormedXmlFailures.TestSurefire3" ) );
+        assertThat( tests.get( 3 ).getName(), is( "testQuote" ) );
+        assertThat( tests.get( 3 ).getFailureDetail(),
+                    is( "junit.framework.AssertionFailedError: \"\n"
+                            + "\tat 
junit.framework.Assert.fail(Assert.java:47)\n"
+                            + "\tat 
wellFormedXmlFailures.TestSurefire3.testQuote(TestSurefire3.java:25)\n" ) );
+        assertThat( tests.get( 3 ).getClassName(), is( "TestSurefire3" ) );
+        assertThat( tests.get( 3 ).getTime(), is( 0f ) );
+        assertThat( tests.get( 3 ).getFailureErrorLine(), is( "25" ) );
+        assertThat( tests.get( 3 ).getFailureMessage(), is( "\"" ) );
+        assertThat( tests.get( 3 ).getFullName(), is( 
"wellFormedXmlFailures.TestSurefire3.testQuote" ) );
+        assertThat( tests.get( 3 ).getFailureType(), is( 
"junit.framework.AssertionFailedError" ) );
     }
 
+    @Test
     public void testParser()
-        throws IOException, SAXException, ParserConfigurationException
+        throws Exception
     {
         TestSuiteXmlParser parser = new TestSuiteXmlParser();
 
@@ -94,43 +163,430 @@ public class TestSuiteXmlParserTest
         assertEquals( 1, oldResult.size() );
         ReportTestSuite next = oldResult.iterator().next();
         assertEquals( 2, next.getNumberOfTests() );
+    }
 
-
+    @Test
+    public void successfulSurefireTestReport()
+        throws Exception
+    {
+        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        File surefireReport = new File( 
"src/test/resources/junit-pathWithÜmlaut/TEST-umlautTest.BasicTest.xml" );
+        assertTrue( surefireReport.isFile() );
+        Collection<ReportTestSuite> suites = parser.parse( 
surefireReport.getCanonicalPath() );
+        assertNotNull( suites );
+        assertEquals( 1, suites.size() );
+        ReportTestSuite suite = suites.iterator().next();
+        assertThat( suite.getNumberOfTests(), is( 1 ) );
+        assertEquals( 1, suite.getNumberOfTests() );
+        assertEquals( 0, suite.getNumberOfFlakes() );
+        assertEquals( 0, suite.getNumberOfFailures() );
+        assertEquals( 0, suite.getNumberOfErrors() );
+        assertEquals( 0, suite.getNumberOfSkipped() );
+        assertThat( suite.getTimeElapsed(), is( 0.002f ) );
+        assertThat( suite.getFullClassName(), is( "umlautTest.BasicTest" ) );
+        assertThat( suite.getPackageName(), is( "umlautTest" ) );
+        assertThat( suite.getName(), is( "BasicTest" ) );
+        ReportTestCase test = suite.getTestCases().iterator().next();
+        assertFalse( test.hasFailure() );
+        assertNull( test.getFailureDetail() );
+        assertNull( test.getFailureErrorLine() );
+        assertNull( test.getFailureType() );
+        assertThat( test.getTime(), is( 0.002f ) );
+        assertThat( test.getFullClassName(), is( "umlautTest.BasicTest" ) );
+        assertThat( test.getClassName(), is( "BasicTest" ) );
+        assertThat( test.getName(), is( "testSetUp" ) );
+        assertThat( test.getFullName(), is( "umlautTest.BasicTest.testSetUp" ) 
);
     }
 
-    public void noTestParserBadFile() // Determine problem with xml file.
-        throws IOException, SAXException, ParserConfigurationException
+    @Test
+    public void testParserHitsFailsafeSummary()
+        throws Exception
     {
         TestSuiteXmlParser parser = new TestSuiteXmlParser();
 
-        File file = new File( 
"../surefire-integration-tests/target/UmlautDirIT/junit-pathWith\u00DCmlaut/target/surefire-reports/TEST-umlautTest.BasicTest.xml"
  );
-        assertTrue(file.exists());
-        Collection<ReportTestSuite> oldResult = parser.parse(
-            
"..\\surefire-integration-tests\\target\\UmlautDirIT\\junit-pathWith\u00DCmlaut\\target\\surefire-reports\\TEST-umlautTest.BasicTest.xml"
 );
+        parser.parse( 
"src/test/resources/fixture/testsuitexmlparser/failsafe-summary.xml" );
 
-        assertNotNull( oldResult );
+        assertFalse( parser.isValid() );
 
-        assertEquals( 1, oldResult.size() );
-        ReportTestSuite next = oldResult.iterator().next();
-        assertEquals( 2, next.getNumberOfTests() );
+        parser.parse(
+            
"src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.FailingTest.xml"
 );
+
+        assertTrue( parser.isValid() );
+    }
 
+    @Test
+    public void lastIndexOfPatternOfOrdinalTest()
+    {
+        final StringBuilder stackTrace = new StringBuilder(
+            "\tat org.apache.Test.util(Test.java:60)\n"
+                + "\tat org.apache.Test.test(Test.java:30)\n"
+                + "\tat com.sun.Impl.xyz(Impl.java:258)\n" );
 
+        int[] result = TestSuiteXmlParser.lastIndexOf( stackTrace, 
linePatterns );
+        assertThat( result[0], is( 40 ) );
+        assertThat( result[1], is( 0 ) );
+        String errorLine = TestSuiteXmlParser.parseErrorLine( stackTrace, 
"org.apache.Test" );
+        assertThat( errorLine, is( "30" ) );
     }
 
-    public void testParserHitsFailsafeSummary()
-        throws IOException, SAXException, ParserConfigurationException
+    @Test
+    public void lastIndexOfPatternOfOrdinalTestWithCause()
+    {
+        final StringBuilder stackTrace = new StringBuilder(
+            "\tat org.apache.Test.util(Test.java:60)\n"
+                + "\tat org.apache.Test.test(Test.java:30)\n"
+                + "\tat com.sun.Impl.xyz(Impl.java:258)\n"
+                + "\tat Caused by: java.lang.IndexOutOfBoundsException\n"
+                + "\tat org.apache.Test.util(Test.java:70)\n" );
+
+        int[] result = TestSuiteXmlParser.lastIndexOf( stackTrace, 
linePatterns );
+        assertThat( result[0], is( 40 ) );
+        assertThat( result[1], is( 0 ) );
+        String errorLine = TestSuiteXmlParser.parseErrorLine( stackTrace, 
"org.apache.Test" );
+        assertThat( errorLine, is( "30" ) );
+    }
+
+    @Test
+    public void lastIndexOfPatternOfEnclosedTest()
+    {
+        final StringBuilder source = new StringBuilder(
+            "\tat org.apache.Test.util(Test.java:60)\n"
+                + "\tat org.apache.Test$Nested.test(Test.java:30)\n"
+                + "\tat com.sun.Impl.xyz(Impl.java:258)\n" );
+
+        int[] result = TestSuiteXmlParser.lastIndexOf( source, linePatterns );
+        assertThat( result[0], is( 40 ) );
+        assertThat( result[1], is( 1 ) );
+        String errorLine = TestSuiteXmlParser.parseErrorLine( source, 
"org.apache.Test$Nested" );
+        assertThat( errorLine, is( "30" ) );
+    }
+
+    @Test
+    public void lastIndexOfPatternOfEnclosedTestWithCause()
+    {
+        final StringBuilder source = new StringBuilder(
+            "\tat org.apache.Test.util(Test.java:60)\n"
+                + "\tat org.apache.Test$Nested.test(Test.java:30)\n"
+                + "\tat com.sun.Impl.xyz(Impl.java:258)\n"
+                + "\tat Caused by: java.lang.IndexOutOfBoundsException\n"
+                + "\tat org.apache.Test$Nested.util(Test.java:70)\n" );
+
+        int[] result = TestSuiteXmlParser.lastIndexOf( source, linePatterns );
+        assertThat( result[0], is( 40 ) );
+        assertThat( result[1], is( 1 ) );
+        String errorLine = TestSuiteXmlParser.parseErrorLine( source, 
"org.apache.Test$Nested" );
+        assertThat( errorLine, is( "30" ) );
+    }
+
+    @Test
+    public void shouldParserEverythingInOrdinalTest()
+        throws Exception
     {
         TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        List<ReportTestSuite> tests =
+            parser.parse( 
"src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest.xml" );
+        assertTrue( parser.isValid() );
+        assertThat( tests.size(), is( 1 ) );
+        assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest" ) 
);
+        assertThat( tests.get( 0 ).getNumberOfErrors(), is( 1 ) );
+        assertThat( tests.get( 0 ).getNumberOfFlakes(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfSkipped(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfFailures(), is( 0 ) );
+        assertThat( tests.get( 0 ).getPackageName(), is( "surefire" ) );
+        assertThat( tests.get( 0 ).getNumberOfTests(), is( 1 ) );
+        assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) );
+        assertTrue( tests.get( 0 ).getTestCases().get( 0 ).hasFailure() );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 
).getFailureErrorLine(), is( "13" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(), 
is( "java.lang.RuntimeException" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), 
is( "surefire.MyTest" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( 
"MyTest" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( 
"test" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullName(), is( 
"surefire.MyTest.test" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0.1f 
) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 
).getFailureMessage(), is( "this is different message" ) );
 
-        parser.parse( 
"src/test/resources/fixture/testsuitexmlparser/failsafe-summary.xml" );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(),
+                    is( "java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException\n"
+        + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n"
+        + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n"
+        + "\tat surefire.MyTest.test(MyTest.java:13)\n"
+        + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n"
+        + "\tat 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n"
+        + "\tat 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n"
+        + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n"
+        + "\tat 
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n"
+        + "\tat 
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n"
+        + "\tat 
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n"
+        + "\tat 
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n"
+        + "\tat 
org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n"
+        + "\tat 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n"
+        + "\tat 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n"
+        + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n"
+        + "\tat 
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n"
+        + "\tat 
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n"
+        + "\tat 
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n"
+        + "\tat 
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n"
+        + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n"
+        + "\tCaused by: java.lang.IndexOutOfBoundsException\n"
+        + "\tat surefire.MyTest.failure(MyTest.java:33)\n"
+        + "\tat surefire.MyTest.access$100(MyTest.java:9)\n"
+        + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n"
+        + "\tat surefire.MyTest.delegate(MyTest.java:29)\n"
+        + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) );
+    }
 
-        assertFalse( parser.isValid() );
+    @Test
+    public void shouldParserEverythingInEnclosedTest()
+        throws Exception
+    {
+        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        List<ReportTestSuite> tests =
+            parser.parse( 
"src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed.xml"
 );
+        assertTrue( parser.isValid() );
+        assertThat( tests.size(), is( 1 ) );
+        assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest$A" 
) );
+        assertThat( tests.get( 0 ).getNumberOfErrors(), is( 1 ) );
+        assertThat( tests.get( 0 ).getNumberOfFlakes(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfSkipped(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfFailures(), is( 0 ) );
+        assertThat( tests.get( 0 ).getPackageName(), is( "surefire" ) );
+        assertThat( tests.get( 0 ).getNumberOfTests(), is( 1 ) );
+        assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) );
+        assertTrue( tests.get( 0 ).getTestCases().get( 0 ).hasFailure() );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 
).getFailureErrorLine(), is( "45" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(),
+                    is( "java.lang.RuntimeException" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), 
is( "surefire.MyTest$A" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( 
"MyTest$A" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( "t" 
) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullName(), is( 
"surefire.MyTest$A.t" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0f ) 
);
 
-        parser.parse(
-            
"src/test/resources/fixture/testsuitexmlparser/TEST-org.apache.maven.surefire.test.FailingTest.xml"
 );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(),
+                    is( "java.lang.IndexOutOfBoundsException" ) );
+
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(),
+                    is( "java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException\n"
+        + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n"
+        + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n"
+        + "\tat surefire.MyTest.access$200(MyTest.java:9)\n"
+        + "\tat surefire.MyTest$A.t(MyTest.java:45)\n"
+        + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n"
+        + "\tat 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n"
+        + "\tat 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n"
+        + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n"
+        + "\tat 
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n"
+        + "\tat 
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n"
+        + "\tat 
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n"
+        + "\tat 
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n"
+        + "\tat 
org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n"
+        + "\tat 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n"
+        + "\tat 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n"
+        + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n"
+        + "\tat 
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n"
+        + "\tat 
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n"
+        + "\tat 
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n"
+        + "\tat 
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n"
+        + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n"
+        + "\tat org.junit.runners.Suite.runChild(Suite.java:128)\n"
+        + "\tat org.junit.runners.Suite.runChild(Suite.java:27)\n"
+        + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n"
+        + "\tat 
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n"
+        + "\tat 
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n"
+        + "\tat 
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n"
+        + "\tat 
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n"
+        + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n"
+        + "\tCaused by: java.lang.IndexOutOfBoundsException\n"
+        + "\tat surefire.MyTest.failure(MyTest.java:33)\n"
+        + "\tat surefire.MyTest.access$100(MyTest.java:9)\n"
+        + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n"
+        + "\tat surefire.MyTest.delegate(MyTest.java:29)\n"
+        + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)\n" ) );
+    }
+
+    @Test
+    public void shouldParserEverythingInEnclosedTrimStackTraceTest()
+        throws Exception
+    {
+        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        List<ReportTestSuite> tests = parser.parse( 
"src/test/resources/fixture/testsuitexmlparser/"
+                                                        + 
"TEST-surefire.MyTest-enclosed-trimStackTrace.xml" );
+        assertTrue( parser.isValid() );
+        assertThat( tests.size(), is( 1 ) );
+        assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest$A" 
) );
+        assertThat( tests.get( 0 ).getNumberOfErrors(), is( 1 ) );
+        assertThat( tests.get( 0 ).getNumberOfFlakes(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfSkipped(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfFailures(), is( 0 ) );
+        assertThat( tests.get( 0 ).getPackageName(), is( "surefire" ) );
+        assertThat( tests.get( 0 ).getNumberOfTests(), is( 1 ) );
+        assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) );
+        assertTrue( tests.get( 0 ).getTestCases().get( 0 ).hasFailure() );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 
).getFailureErrorLine(), is( "45" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(),
+                    is( "java.lang.RuntimeException" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), 
is( "surefire.MyTest$A" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( 
"MyTest$A" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( "t" 
) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullName(), is( 
"surefire.MyTest$A.t" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0f ) 
);
+
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(),
+                    is( "java.lang.IndexOutOfBoundsException" ) );
 
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(),
+                    is( "java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException\n"
+                            + "\tat surefire.MyTest.failure(MyTest.java:33)\n"
+                            + "\tat 
surefire.MyTest.access$100(MyTest.java:9)\n"
+                            + "\tat 
surefire.MyTest$Nested.run(MyTest.java:38)\n"
+                            + "\tat surefire.MyTest.delegate(MyTest.java:29)\n"
+                            + "\tat 
surefire.MyTest.rethrownDelegate(MyTest.java:22)\n"
+                            + "\tat 
surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n"
+                            + "\tat 
surefire.MyTest.access$200(MyTest.java:9)\n"
+                            + "\tat surefire.MyTest$A.t(MyTest.java:45)\n" ) );
+    }
+
+    @Test
+    public void shouldParserEverythingInNestedClassTest()
+        throws Exception
+    {
+        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        List<ReportTestSuite> tests = parser.parse( 
"src/test/resources/fixture/testsuitexmlparser/"
+                                                        + 
"TEST-surefire.MyTest-nestedClass.xml" );
         assertTrue( parser.isValid() );
+        assertThat( tests.size(), is( 1 ) );
+        assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest" ) 
);
+        assertThat( tests.get( 0 ).getNumberOfErrors(), is( 1 ) );
+        assertThat( tests.get( 0 ).getNumberOfFlakes(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfSkipped(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfFailures(), is( 0 ) );
+        assertThat( tests.get( 0 ).getPackageName(), is( "surefire" ) );
+        assertThat( tests.get( 0 ).getNumberOfTests(), is( 1 ) );
+        assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) );
+        assertTrue( tests.get( 0 ).getTestCases().get( 0 ).hasFailure() );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 
).getFailureErrorLine(), is( "13" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(),
+                    is( "java.lang.RuntimeException" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), 
is( "surefire.MyTest" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( 
"MyTest" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( 
"test" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullName(), is( 
"surefire.MyTest.test" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0f ) 
);
+
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(),
+                    is( "java.lang.IndexOutOfBoundsException" ) );
+
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(),
+                    is( "java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException\n"
+        + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:24)\n"
+        + "\tat surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n"
+        + "\tat surefire.MyTest.test(MyTest.java:13)\n"
+        + "\tat sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n"
+        + "\tat 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)\n"
+        + "\tat 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n"
+        + "\tat java.lang.reflect.Method.invoke(Method.java:606)\n"
+        + "\tat 
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)\n"
+        + "\tat 
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)\n"
+        + "\tat 
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)\n"
+        + "\tat 
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)\n"
+        + "\tat 
org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)\n"
+        + "\tat 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)\n"
+        + "\tat 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)\n"
+        + "\tat org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)\n"
+        + "\tat 
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)\n"
+        + "\tat 
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)\n"
+        + "\tat 
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)\n"
+        + "\tat 
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)\n"
+        + "\tat org.junit.runners.ParentRunner.run(ParentRunner.java:363)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)\n"
+        + "\tat 
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)\n"
+        + "\tat 
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)\n"
+        + "\tCaused by: java.lang.IndexOutOfBoundsException\n"
+        + "\tat surefire.MyTest.failure(MyTest.java:33)\n"
+        + "\tat surefire.MyTest.access$100(MyTest.java:9)\n"
+        + "\tat surefire.MyTest$Nested.run(MyTest.java:38)\n"
+        + "\tat surefire.MyTest.delegate(MyTest.java:29)\n"
+        + "\tat surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) );
     }
 
+    @Test
+    public void shouldParserEverythingInNestedClassTrimStackTraceTest()
+        throws Exception
+    {
+        TestSuiteXmlParser parser = new TestSuiteXmlParser();
+        List<ReportTestSuite> tests = parser.parse( 
"src/test/resources/fixture/testsuitexmlparser/"
+                                                        + 
"TEST-surefire.MyTest-nestedClass-trimStackTrace.xml" );
+        assertTrue( parser.isValid() );
+        assertThat( tests.size(), is( 1 ) );
+        assertThat( tests.get( 0 ).getFullClassName(), is( "surefire.MyTest" ) 
);
+        assertThat( tests.get( 0 ).getNumberOfErrors(), is( 1 ) );
+        assertThat( tests.get( 0 ).getNumberOfFlakes(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfSkipped(), is( 0 ) );
+        assertThat( tests.get( 0 ).getNumberOfFailures(), is( 0 ) );
+        assertThat( tests.get( 0 ).getPackageName(), is( "surefire" ) );
+        assertThat( tests.get( 0 ).getNumberOfTests(), is( 1 ) );
+        assertThat( tests.get( 0 ).getTestCases().size(), is( 1 ) );
+        assertTrue( tests.get( 0 ).getTestCases().get( 0 ).hasFailure() );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 
).getFailureErrorLine(), is( "13" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureType(),
+                    is( "java.lang.RuntimeException" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullClassName(), 
is( "surefire.MyTest" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getClassName(), is( 
"MyTest" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getName(), is( 
"test" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFullName(), is( 
"surefire.MyTest.test" ) );
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getTime(), is( 0f ) 
);
+
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureMessage(),
+                    is( "java.lang.IndexOutOfBoundsException" ) );
 
+        assertThat( tests.get( 0 ).getTestCases().get( 0 ).getFailureDetail(),
+                    is( "java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException\n"
+                            + "\tat 
surefire.MyTest.rethrownDelegate(MyTest.java:24)\n"
+                            + "\tat 
surefire.MyTest.newRethrownDelegate(MyTest.java:17)\n"
+                            + "\tat surefire.MyTest.test(MyTest.java:13)\n"
+                            + "\tCaused by: 
java.lang.IndexOutOfBoundsException\n"
+                            + "\tat surefire.MyTest.failure(MyTest.java:33)\n"
+                            + "\tat 
surefire.MyTest.access$100(MyTest.java:9)\n"
+                            + "\tat 
surefire.MyTest$Nested.run(MyTest.java:38)\n"
+                            + "\tat surefire.MyTest.delegate(MyTest.java:29)\n"
+                            + "\tat 
surefire.MyTest.rethrownDelegate(MyTest.java:22)" ) );
+    }
+
+    @Test
+    public void shouldTestNotBlank()
+    {
+        assertFalse( TestSuiteXmlParser.isNotBlank( 1, 2, ' ', ' ', ' ', '\n' 
) );
+        assertFalse( TestSuiteXmlParser.isNotBlank( 1, 2, ' ', '\t', ' ', '\n' 
) );
+        assertFalse( TestSuiteXmlParser.isNotBlank( 1, 2, ' ', ' ', '\r', '\n' 
) );
+        assertFalse( TestSuiteXmlParser.isNotBlank( 1, 2, ' ', ' ', '\f', '\n' 
) );
+        assertTrue( TestSuiteXmlParser.isNotBlank( 1, 2, ' ', 'a', ' ', '\n' ) 
);
+        assertTrue( TestSuiteXmlParser.isNotBlank( 1, 2, ' ', ' ', 'a', '\n' ) 
);
+        assertTrue( TestSuiteXmlParser.isNotBlank( 1, 2, ' ', 'a', 'b', '\n' ) 
);
+    }
+
+    @Test
+    public void shouldTestIsNumeric()
+    {
+        assertFalse( TestSuiteXmlParser.isNumeric( new StringBuilder( "0?5142" 
), 1, 3 ) );
+        assertTrue( TestSuiteXmlParser.isNumeric( new StringBuilder( "0?51M2" 
), 2, 4 ) );
+        assertFalse( TestSuiteXmlParser.isNumeric( new StringBuilder( "0?51M2" 
), 2, 5 ) );
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed-trimStackTrace.xml
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed-trimStackTrace.xml
 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed-trimStackTrace.xml
new file mode 100644
index 0000000..d5e68a2
--- /dev/null
+++ 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed-trimStackTrace.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuite name="surefire.MyTest" time="0" tests="1" errors="1" skipped="0" 
failures="0">
+  <properties>
+    <property name="java.runtime.name" value="Java(TM) SE Runtime 
Environment"/>
+  </properties>
+  <testcase name="t" classname="surefire.MyTest$A" time="0">
+    <error message="java.lang.IndexOutOfBoundsException" 
type="java.lang.RuntimeException">java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.failure(MyTest.java:33)
+       at surefire.MyTest.access$100(MyTest.java:9)
+       at surefire.MyTest$Nested.run(MyTest.java:38)
+       at surefire.MyTest.delegate(MyTest.java:29)
+       at surefire.MyTest.rethrownDelegate(MyTest.java:22)
+       at surefire.MyTest.newRethrownDelegate(MyTest.java:17)
+       at surefire.MyTest.access$200(MyTest.java:9)
+       at surefire.MyTest$A.t(MyTest.java:45)
+</error>
+  </testcase>
+</testsuite>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed.xml
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed.xml
 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed.xml
new file mode 100644
index 0000000..88402af
--- /dev/null
+++ 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-enclosed.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuite name="surefire.MyTest" time="0" tests="1" errors="1" skipped="0" 
failures="0">
+  <properties>
+    <property name="java.runtime.name" value="Java(TM) SE Runtime 
Environment"/>
+  </properties>
+  <testcase name="t" classname="surefire.MyTest$A" time="0">
+    <error message="java.lang.IndexOutOfBoundsException" 
type="java.lang.RuntimeException">java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.rethrownDelegate(MyTest.java:24)
+       at surefire.MyTest.newRethrownDelegate(MyTest.java:17)
+       at surefire.MyTest.access$200(MyTest.java:9)
+       at surefire.MyTest$A.t(MyTest.java:45)
+       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+       at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+       at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+       at java.lang.reflect.Method.invoke(Method.java:606)
+       at 
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
+       at 
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+       at 
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
+       at 
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+       at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
+       at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
+       at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+       at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
+       at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
+       at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
+       at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
+       at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
+       at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
+       at org.junit.runners.Suite.runChild(Suite.java:128)
+       at org.junit.runners.Suite.runChild(Suite.java:27)
+       at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
+       at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
+       at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
+       at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
+       at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
+       at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)
+       Caused by: java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.failure(MyTest.java:33)
+       at surefire.MyTest.access$100(MyTest.java:9)
+       at surefire.MyTest$Nested.run(MyTest.java:38)
+       at surefire.MyTest.delegate(MyTest.java:29)
+       at surefire.MyTest.rethrownDelegate(MyTest.java:22)
+</error>
+  </testcase>
+</testsuite>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass-trimStackTrace.xml
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass-trimStackTrace.xml
 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass-trimStackTrace.xml
new file mode 100644
index 0000000..5b5e9a6
--- /dev/null
+++ 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass-trimStackTrace.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuite name="surefire.MyTest" time="0" tests="1" errors="1" skipped="0" 
failures="0">
+  <properties>
+    <property name="java.runtime.name" value="Java(TM) SE Runtime 
Environment"/>
+  </properties>
+  <testcase name="test" classname="surefire.MyTest" time="0">
+    <error message="java.lang.IndexOutOfBoundsException" 
type="java.lang.RuntimeException">java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.rethrownDelegate(MyTest.java:24)
+       at surefire.MyTest.newRethrownDelegate(MyTest.java:17)
+       at surefire.MyTest.test(MyTest.java:13)
+       Caused by: java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.failure(MyTest.java:33)
+       at surefire.MyTest.access$100(MyTest.java:9)
+       at surefire.MyTest$Nested.run(MyTest.java:38)
+       at surefire.MyTest.delegate(MyTest.java:29)
+       at surefire.MyTest.rethrownDelegate(MyTest.java:22)
+</error>
+  </testcase>
+</testsuite>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass.xml
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass.xml
 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass.xml
new file mode 100644
index 0000000..e92f215
--- /dev/null
+++ 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest-nestedClass.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuite name="surefire.MyTest" time="0" tests="1" errors="1" skipped="0" 
failures="0">
+  <properties>
+    <property name="java.runtime.name" value="Java(TM) SE Runtime 
Environment"/>
+  </properties>
+  <testcase name="test" classname="surefire.MyTest" time="0">
+    <error message="java.lang.IndexOutOfBoundsException" 
type="java.lang.RuntimeException">java.lang.RuntimeException: 
java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.rethrownDelegate(MyTest.java:24)
+       at surefire.MyTest.newRethrownDelegate(MyTest.java:17)
+       at surefire.MyTest.test(MyTest.java:13)
+       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+       at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+       at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+       at java.lang.reflect.Method.invoke(Method.java:606)
+       at 
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
+       at 
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+       at 
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
+       at 
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+       at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
+       at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
+       at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+       at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
+       at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
+       at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
+       at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
+       at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
+       at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)
+       Caused by: java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.failure(MyTest.java:33)
+       at surefire.MyTest.access$100(MyTest.java:9)
+       at surefire.MyTest$Nested.run(MyTest.java:38)
+       at surefire.MyTest.delegate(MyTest.java:29)
+       at surefire.MyTest.rethrownDelegate(MyTest.java:22)
+</error>
+  </testcase>
+</testsuite>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest.xml
----------------------------------------------------------------------
diff --git 
a/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest.xml
 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest.xml
new file mode 100644
index 0000000..8183118
--- /dev/null
+++ 
b/surefire-report-parser/src/test/resources/fixture/testsuitexmlparser/TEST-surefire.MyTest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<testsuite name="surefire.MyTest" time="0" tests="1" errors="1" skipped="0" 
failures="0">
+  <properties>
+    <property name="java.runtime.name" value="Java(TM) SE Runtime 
Environment"/>
+  </properties>
+  <testcase name="test" classname="surefire.MyTest" time="0.1">
+    <error type="java.lang.RuntimeException" message="this is different 
message">java.lang.RuntimeException: java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.rethrownDelegate(MyTest.java:24)
+       at surefire.MyTest.newRethrownDelegate(MyTest.java:17)
+       at surefire.MyTest.test(MyTest.java:13)
+       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+       at 
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+       at 
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+       at java.lang.reflect.Method.invoke(Method.java:606)
+       at 
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
+       at 
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
+       at 
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
+       at 
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
+       at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
+       at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
+       at 
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
+       at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
+       at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
+       at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
+       at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
+       at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
+       at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:272)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:167)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:147)
+       at 
org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:130)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:211)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:163)
+       at 
org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:105)
+       Caused by: java.lang.IndexOutOfBoundsException
+       at surefire.MyTest.failure(MyTest.java:33)
+       at surefire.MyTest.access$100(MyTest.java:9)
+       at surefire.MyTest$Nested.run(MyTest.java:38)
+       at surefire.MyTest.delegate(MyTest.java:29)
+       at surefire.MyTest.rethrownDelegate(MyTest.java:22)
+</error>
+  </testcase>
+</testsuite>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/989479ea/"surefire-report-parser/src/test/resources/junit-pathWith\303\234mlaut/TEST-umlautTest.BasicTest.xml";
----------------------------------------------------------------------

Reply via email to