You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by ti...@apache.org on 2015/03/29 17:49:50 UTC

maven-surefire git commit: [SUREFIRE-1146] rerunFailingTestsCount not working with Parameterized test

Repository: maven-surefire
Updated Branches:
  refs/heads/master 46202284d -> be9d92342


[SUREFIRE-1146] rerunFailingTestsCount not working with Parameterized test


Project: http://git-wip-us.apache.org/repos/asf/maven-surefire/repo
Commit: http://git-wip-us.apache.org/repos/asf/maven-surefire/commit/be9d9234
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/be9d9234
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/be9d9234

Branch: refs/heads/master
Commit: be9d92342aa8647c458cc926c6503380095548b2
Parents: 4620228
Author: Tibor17 <ti...@lycos.com>
Authored: Sun Mar 29 17:47:51 2015 +0200
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Mar 29 17:47:51 2015 +0200

----------------------------------------------------------------------
 .../plugin/failsafe/IntegrationTestMojo.java    |   3 +-
 .../maven/plugin/surefire/SurefirePlugin.java   |   3 +-
 .../src/site/apt/examples/single-test.apt.vm    |   4 +-
 .../surefire/testset/TestListResolver.java      |   6 +
 ...Surefire1146RerunFailedAndParameterized.java |  75 +++++++++
 .../pom.xml                                     |  69 ++++++++
 .../CustomDescriptionParameterizedTest.java     |  62 +++++++
 ...omDescriptionWithCommaParameterizedTest.java |  63 +++++++
 .../surefire1146/SimpleParameterizedTest.java   |  62 +++++++
 .../java/jiras/surefire1146/StandardTest.java   |  40 +++++
 .../surefire/common/junit4/ClassMethod.java     |  53 ++++++
 .../common/junit4/JUnit4ProviderUtil.java       | 102 +++++++----
 .../common/junit4/JUnit4RunListener.java        |   8 +-
 .../common/junit4/JUnit4ProviderUtilTest.java   |  28 +++-
 .../common/junit48/FailingMethodFilter.java     |  24 ++-
 .../common/junit48/FilterFactoryTest.java       |  10 ++
 .../apache/maven/surefire/junit4/Filter.java    |  27 ---
 .../maven/surefire/junit4/JUnit4Provider.java   | 167 ++++++++++++-------
 18 files changed, 678 insertions(+), 128 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
----------------------------------------------------------------------
diff --git a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
index 93f8121..baa8a98 100644
--- a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
+++ b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
@@ -93,7 +93,8 @@ public class IntegrationTestMojo
      * "-Dit.test=Basic*, !%regex[.*.Unstable.*], !%regex[.*.MyIT.class#one.*|two.*], %regex[#fast.*|slow.*]"<br/>
      * <br/>
      * The Parameterized JUnit runner <em>describes</em> test methods using an index in brackets, so the non-regex
-     * method pattern would become: <em>#testMethod[*]</em>.
+     * method pattern would become: <em>#testMethod[*]</em>. If using <em>@Parameters(name="{index}: fib({0})={1}")</em>
+     * and selecting the index e.g. 5 in pattern, the non-regex method pattern would become <em>#testMethod[5:*]</em>.
      * <br/>
      */
     @Parameter( property = "it.test" )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
index aa94918..63441e1 100644
--- a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
+++ b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
@@ -78,7 +78,8 @@ public class SurefirePlugin
      * "-Dtest=Basic*, !%regex[.*.Unstable.*], !%regex[.*.MyTest.class#one.*|two.*], %regex[#fast.*|slow.*]"<br/>
      * <br/>
      * The Parameterized JUnit runner <em>describes</em> test methods using an index in brackets, so the non-regex
-     * method pattern would become: <em>#testMethod[*]</em>.
+     * method pattern would become: <em>#testMethod[*]</em>. If using <em>@Parameters(name="{index}: fib({0})={1}")</em>
+     * and selecting the index e.g. 5 in pattern, the non-regex method pattern would become <em>#testMethod[5:*]</em>.
      * <br/>
      */
     @Parameter( property = "test" )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm
----------------------------------------------------------------------
diff --git a/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm b/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm
index 44448bd..6b44bde 100644
--- a/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm
+++ b/maven-surefire-plugin/src/site/apt/examples/single-test.apt.vm
@@ -142,4 +142,6 @@ mvn "-Dit.test=Basic*, !%regex[.*.Unstable.*], !%regex[.*.MyIT.class#one.*|two.*
   The regex validates fully qualified class file, and validates test methods separately after (#) however class
   is optional. The regex supports '.class' file extension only. Note the regex comments, marked by (#)
   character, are unsupported. The Parameterized JUnit runner describes test methods using an index in brackets, so the
-  non-regex method pattern would become <<<#testMethod[*]>>>.
+  non-regex method pattern would become <<<#testMethod[*]>>>. If using the JUnit annotation
+  <<<@Parameters(name="\{index\}: fib(\{0\})=\{1\}")>>> and selecting the index e.g. 5 in pattern, the non-regex
+  method pattern would become <<<#testMethod[5:*]>>>.

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java
index cd38118..b233147 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java
@@ -279,6 +279,12 @@ public class TestListResolver
         return result;
     }
 
+    @Override
+    public String toString()
+    {
+        return getPluginParameterTest();
+    }
+
     static String removeExclamationMark( String s )
     {
         return s.length() != 0 && s.charAt( 0 ) == '!' ? s.substring( 1 ) : s;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1146RerunFailedAndParameterized.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1146RerunFailedAndParameterized.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1146RerunFailedAndParameterized.java
new file mode 100644
index 0000000..24d39bc
--- /dev/null
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1146RerunFailedAndParameterized.java
@@ -0,0 +1,75 @@
+package org.apache.maven.surefire.its.jiras;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.surefire.its.fixture.OutputValidator;
+import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.junit.Test;
+
+/**
+ * @see {@linkplain https://jira.codehaus.org/browse/SUREFIRE-1146}
+ */
+public class Surefire1146RerunFailedAndParameterized
+    extends SurefireJUnit4IntegrationTestCase
+{
+    
+    @Test
+    public void testsAreRerun()
+    {
+        OutputValidator outputValidator = unpack( "surefire-1146-rerunFailingTests-with-Parameterized" ).executeTest();
+        verify(outputValidator, 8, 0, 0, 0, 5);
+    }
+
+    private void verify( OutputValidator outputValidator, int run, int failures, int errors, int skipped, int flakes )
+    {
+        outputValidator.verifyTextInLog( "Flaked tests:" );
+        outputValidator.verifyTextInLog( "jiras.surefire1146.CustomDescriptionParameterizedTest.flakyTest[0: (Test11); Test12; Test13;](jiras.surefire1146.CustomDescriptionParameterizedTest)" );
+        outputValidator.verifyTextInLog( "Run 1: CustomDescriptionParameterizedTest.flakyTest:" );
+        outputValidator.verifyTextInLog( "Run 2: CustomDescriptionParameterizedTest.flakyTest:" );
+        outputValidator.verifyTextInLog( "Run 3: PASS" );
+
+        outputValidator.verifyTextInLog( "jiras.surefire1146.CustomDescriptionWithCommaParameterizedTest.flakyTest[0: (Test11), Test12, Test13;](jiras.surefire1146.CustomDescriptionWithCommaParameterizedTest)" );
+        outputValidator.verifyTextInLog( "Run 1: CustomDescriptionWithCommaParameterizedTest.flakyTest:" );
+        outputValidator.verifyTextInLog( "Run 2: CustomDescriptionWithCommaParameterizedTest.flakyTest:" );
+        outputValidator.verifyTextInLog( "Run 3: PASS" );
+        
+        outputValidator.verifyTextInLog( "jiras.surefire1146.CustomDescriptionWithCommaParameterizedTest.flakyTest[2: (Test31), Test32, Test33;](jiras.surefire1146.CustomDescriptionWithCommaParameterizedTest)" );
+        outputValidator.verifyTextInLog( "Run 1: CustomDescriptionWithCommaParameterizedTest.flakyTest:" );
+        outputValidator.verifyTextInLog( "Run 2: PASS" );
+        
+        outputValidator.verifyTextInLog( "jiras.surefire1146.SimpleParameterizedTest.flakyTest[0](jiras.surefire1146.SimpleParameterizedTest)" );
+        outputValidator.verifyTextInLog( "Run 1: SimpleParameterizedTest.flakyTest:" );
+        outputValidator.verifyTextInLog( "Run 2: SimpleParameterizedTest.flakyTest:" );
+        outputValidator.verifyTextInLog( "Run 3: PASS" );
+        
+        outputValidator.verifyTextInLog( "jiras.surefire1146.StandardTest.flakyTest(jiras.surefire1146.StandardTest)" );
+        outputValidator.verifyTextInLog( "Run 1: StandardTest.flakyTest:" );
+        outputValidator.verifyTextInLog( "Run 2: PASS" );
+
+        verifyStatistics( outputValidator, run, failures, errors, skipped, flakes );
+    }
+    
+    private void verifyStatistics( OutputValidator outputValidator, int run, int failures, int errors, int skipped,
+                                   int flakes )
+    {
+        outputValidator.verifyTextInLog( "Tests run: " + run + ", Failures: " + failures + ", Errors: " + errors
+                                             + ", Skipped: " + skipped + ", Flakes: " + flakes );
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/pom.xml b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/pom.xml
new file mode 100644
index 0000000..28d0420
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied.  See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.maven.surefire</groupId>
+    <artifactId>it-parent</artifactId>
+    <version>1.0</version>
+    <relativePath>../pom.xml</relativePath>
+  </parent>
+  <groupId>org.apache.maven.plugins.surefire</groupId>
+  <artifactId>jiras-surefire-1146</artifactId>
+  <version>1.0</version>
+  <url>http://maven.apache.org</url>
+  <developers>
+    <developer>
+      <id>tibordigana</id>
+      <name>Tibor Digaňa (tibor17)</name>
+      <email>tibordigana@apache.org</email>
+      <roles>
+        <role>Committer</role>
+      </roles>
+      <timezone>Europe/Bratislava</timezone>
+    </developer>
+  </developers>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <rerunFailingTestsCount>2</rerunFailingTestsCount>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/CustomDescriptionParameterizedTest.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/CustomDescriptionParameterizedTest.java b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/CustomDescriptionParameterizedTest.java
new file mode 100644
index 0000000..ffdfa87
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/CustomDescriptionParameterizedTest.java
@@ -0,0 +1,62 @@
+package jiras.surefire1146;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.runner.Version;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static org.junit.Assert.*;
+
+@RunWith( Parameterized.class )
+public class CustomDescriptionParameterizedTest
+{
+
+    private static boolean success;
+
+    public CustomDescriptionParameterizedTest( String test1, String test2, String test3 )
+    {
+
+    }
+
+    @Parameters( name = "{index}: ({0}); {1}; {2};" )
+    public static List getParameters()
+    {
+        List parameters = new ArrayList();
+        parameters.add( new String[]{ "Test11", "Test12", "Test13" } );
+        parameters.add( new String[]{ "Test21", "Test22", "Test23" } );
+        return parameters;
+    }
+
+    @Test
+    public void flakyTest()
+    {
+        System.out.println( "Running JUnit " + Version.id() );
+        boolean current = success;
+        success = !success;
+        assertTrue( current );
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/CustomDescriptionWithCommaParameterizedTest.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/CustomDescriptionWithCommaParameterizedTest.java b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/CustomDescriptionWithCommaParameterizedTest.java
new file mode 100644
index 0000000..39563df
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/CustomDescriptionWithCommaParameterizedTest.java
@@ -0,0 +1,63 @@
+package jiras.surefire1146;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.runner.Version;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static org.junit.Assert.*;
+
+@RunWith( Parameterized.class )
+public class CustomDescriptionWithCommaParameterizedTest
+{
+
+    private static boolean success;
+
+    public CustomDescriptionWithCommaParameterizedTest( String test1, String test2, String test3 )
+    {
+
+    }
+
+    @Parameters( name = "{index}: ({0}), {1}, {2};" )
+    public static List getParameters()
+    {
+        List parameters = new ArrayList();
+        parameters.add( new String[]{ "Test11", "Test12", "Test13" } );
+        parameters.add( new String[]{ "Test21", "Test22", "Test23" } );
+        parameters.add( new String[]{ "Test31", "Test32", "Test33" } );
+        return parameters;
+    }
+
+    @Test
+    public void flakyTest()
+    {
+        System.out.println( "Running JUnit " + Version.id() );
+        boolean current = success;
+        success = !success;
+        assertTrue( current );
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/SimpleParameterizedTest.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/SimpleParameterizedTest.java b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/SimpleParameterizedTest.java
new file mode 100644
index 0000000..f278c34
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/SimpleParameterizedTest.java
@@ -0,0 +1,62 @@
+package jiras.surefire1146;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.runner.Version;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static org.junit.Assert.*;
+
+@RunWith( Parameterized.class )
+public class SimpleParameterizedTest
+{
+
+    private static boolean success;
+
+    public SimpleParameterizedTest( String test )
+    {
+
+    }
+
+    @Parameters
+    public static List getParameters()
+    {
+        List parameters = new ArrayList();
+        parameters.add( new String[]{ "Test1" } );
+        parameters.add( new String[]{ "Test2" } );
+        return parameters;
+    }
+
+    @Test
+    public void flakyTest()
+    {
+        System.out.println( "Running JUnit " + Version.id() );
+        boolean current = success;
+        success = !success;
+        assertTrue( current );
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/StandardTest.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/StandardTest.java b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/StandardTest.java
new file mode 100644
index 0000000..f96cdd8
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/surefire-1146-rerunFailingTests-with-Parameterized/src/test/java/jiras/surefire1146/StandardTest.java
@@ -0,0 +1,40 @@
+package jiras.surefire1146;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import junit.runner.Version;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class StandardTest
+{
+    private static boolean success;
+
+    @Test
+    public void flakyTest()
+    {
+        System.out.println( "Running JUnit " + Version.id() );
+        boolean current = success;
+        success = !success;
+        assertTrue( current );
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/ClassMethod.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/ClassMethod.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/ClassMethod.java
new file mode 100644
index 0000000..a3cccca
--- /dev/null
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/ClassMethod.java
@@ -0,0 +1,53 @@
+package org.apache.maven.surefire.common.junit4;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.apache.maven.surefire.util.internal.StringUtils;
+
+/**
+ * Data transfer object of class and method literals.
+ */
+public final class ClassMethod
+{
+    private final String clazz;
+
+    private final String method;
+
+    public ClassMethod( String clazz, String method )
+    {
+        this.clazz = clazz;
+        this.method = method;
+    }
+
+    public boolean isValid()
+    {
+        return !StringUtils.isBlank( clazz ) && !StringUtils.isBlank( method );
+    }
+
+    public String getClazz()
+    {
+        return clazz;
+    }
+
+    public String getMethod()
+    {
+        return method;
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java
index 1e3852a..610ac2c 100644
--- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtil.java
@@ -20,7 +20,6 @@ package org.apache.maven.surefire.common.junit4;
  */
 
 import org.apache.maven.surefire.util.TestsToRun;
-import org.apache.maven.surefire.util.internal.StringUtils;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -29,11 +28,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.maven.surefire.util.internal.StringUtils;
+
 import org.junit.runner.Description;
 import org.junit.runner.notification.Failure;
 
-import static org.apache.maven.surefire.common.junit4.JUnit4RunListener.isFailureInsideJUnitItself;
-
 /**
  *
  * Utility method used among all JUnit4 providers
@@ -41,8 +40,14 @@ import static org.apache.maven.surefire.common.junit4.JUnit4RunListener.isFailur
  * @author Qingzhou Luo
  *
  */
-public class JUnit4ProviderUtil
+public final class JUnit4ProviderUtil
 {
+
+    private JUnit4ProviderUtil()
+    {
+        throw new IllegalStateException( "Cannot instantiate." );
+    }
+
     /**
      * Organize all the failures in previous run into a map between test classes and corresponding failing test methods
      *
@@ -56,29 +61,28 @@ public class JUnit4ProviderUtil
 
         for ( Failure failure : allFailures )
         {
-            if ( !isFailureInsideJUnitItself( failure ) )
+            Description description = failure.getDescription();
+            if ( description.isTest() && !isFailureInsideJUnitItself( description ) )
             {
-                // failure.getTestHeader() is in the format: method(class)
-                String[] testMethodClass = StringUtils.split( failure.getTestHeader(), "(" );
-                String testMethod = testMethodClass[0];
-                String testClass = StringUtils.split( testMethodClass[1], ")" )[0];
-                Class testClassObj = testsToRun.getClassByName( testClass );
-
-                if ( testClassObj == null )
+                ClassMethod classMethod = cutTestClassAndMethod( description );
+                if ( classMethod.isValid() )
                 {
-                    continue;
-                }
+                    Class testClassObj = testsToRun.getClassByName( classMethod.getClazz() );
 
-                Set<String> failingMethods = testClassMethods.get( testClassObj );
-                if ( failingMethods == null )
-                {
-                    failingMethods = new HashSet<String>();
-                    failingMethods.add( testMethod );
-                    testClassMethods.put( testClassObj, failingMethods );
-                }
-                else
-                {
-                    failingMethods.add( testMethod );
+                    if ( testClassObj != null )
+                    {
+                        Set<String> failingMethods = testClassMethods.get( testClassObj );
+                        if ( failingMethods == null )
+                        {
+                            failingMethods = new HashSet<String>();
+                            failingMethods.add( classMethod.getMethod() );
+                            testClassMethods.put( testClassObj, failingMethods );
+                        }
+                        else
+                        {
+                            failingMethods.add( classMethod.getMethod() );
+                        }
+                    }
                 }
             }
         }
@@ -97,11 +101,14 @@ public class JUnit4ProviderUtil
 
         for ( Failure failure : allFailures )
         {
-            if ( !isFailureInsideJUnitItself( failure ) )
+            Description description = failure.getDescription();
+            if ( description.isTest() && !isFailureInsideJUnitItself( description ) )
             {
-                // failure.getTestHeader() is in the format: method(class)
-                String testMethod = StringUtils.split( failure.getTestHeader(), "(" )[0];
-                failingMethods.add( testMethod );
+                ClassMethod classMethod = cutTestClassAndMethod( description );
+                if ( classMethod.isValid() )
+                {
+                    failingMethods.add( classMethod.getMethod() );
+                }
             }
         }
         return failingMethods;
@@ -115,4 +122,43 @@ public class JUnit4ProviderUtil
                 .getDescription();
     }
 
+    public static boolean isFailureInsideJUnitItself( Description failure )
+    {
+        return Description.TEST_MECHANISM.equals( failure );
+    }
+
+    /**
+     * Java Patterns of regex is slower than cutting a substring.
+     * @param description method(class) or method[#](class) or method[#whatever-literals](class)
+     * @return method JUnit test method
+     */
+    public static ClassMethod cutTestClassAndMethod( Description description )
+    {
+        String name = description.getDisplayName();
+        String clazz = null;
+        String method = null;
+        if ( name != null )
+        {
+            // The order is : 1.method and then 2.class
+            // method(class)
+            name = name.trim();
+            if ( name.endsWith( ")" ) )
+            {
+                int classBracket = name.lastIndexOf( '(' );
+                if ( classBracket != -1 )
+                {
+                    clazz = tryBlank( name.substring( classBracket + 1, name.length() - 1 ) );
+                    method = tryBlank( name.substring( 0, classBracket ) );
+                }
+            }
+        }
+        return new ClassMethod( clazz, method );
+    }
+
+    private static String tryBlank( String s )
+    {
+        s = s.trim();
+        return StringUtils.isBlank( s ) ? null : s;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java
index fb625a2..cacc691 100644
--- a/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java
+++ b/surefire-providers/common-junit4/src/main/java/org/apache/maven/surefire/common/junit4/JUnit4RunListener.java
@@ -207,7 +207,8 @@ public class JUnit4RunListener
         {
             for ( Failure failure : run.getFailures() )
             {
-                if ( isFailureInsideJUnitItself( failure ) )
+                Description description = failure.getDescription();
+                if ( JUnit4ProviderUtil.isFailureInsideJUnitItself( description ) )
                 {
                     final Throwable exception = failure.getException();
                     throw new TestSetFailedException( exception );
@@ -215,9 +216,4 @@ public class JUnit4RunListener
             }
         }
     }
-
-    public static boolean isFailureInsideJUnitItself( Failure failure )
-    {
-        return Description.TEST_MECHANISM.equals( failure.getDescription() );
-    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java
index d21393a..f4fdc95 100644
--- a/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java
+++ b/surefire-providers/common-junit4/src/test/java/org/apache/maven/surefire/common/junit4/JUnit4ProviderUtilTest.java
@@ -31,7 +31,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.generateFailingTests;
+import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.*;
 
 /**
  * @author Qingzhou Luo
@@ -73,6 +73,32 @@ public class JUnit4ProviderUtilTest
         assertEquals( expectedResultForT2, resultForT2 );
     }
 
+    public void testIllegalTestDescription$NegativeTest()
+    {
+        Description test = Description.createSuiteDescription( "someTestMethod" );
+        ClassMethod classMethod = cutTestClassAndMethod( test );
+        assertFalse( classMethod.isValid() );
+    }
+
+    public void testOldJUnitParameterizedDescriptionParser()
+    {
+        Description test = Description.createTestDescription( T1.class, " \n testMethod[5] " );
+        assertEquals( " \n testMethod[5] (" + T1.class.getName() + ")", test.getDisplayName() );
+        ClassMethod classMethod = cutTestClassAndMethod( test );
+        assertTrue( classMethod.isValid() );
+        assertEquals( "testMethod[5]", classMethod.getMethod() );
+        assertEquals( T1.class.getName(), classMethod.getClazz() );
+    }
+
+    public void testNewJUnitParameterizedDescriptionParser()
+    {
+        Description test = Description.createTestDescription( T1.class, "flakyTest[3: (Test11); Test12; Test13;]" );
+        ClassMethod classMethod = cutTestClassAndMethod( test );
+        assertTrue( classMethod.isValid() );
+        assertEquals( "flakyTest[3: (Test11); Test12; Test13;]", classMethod.getMethod() );
+        assertEquals( T1.class.getName(), classMethod.getClazz() );
+    }
+
     class T1
     {
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/FailingMethodFilter.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/FailingMethodFilter.java b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/FailingMethodFilter.java
index da9cfd6..e69e7d0 100644
--- a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/FailingMethodFilter.java
+++ b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/FailingMethodFilter.java
@@ -19,6 +19,7 @@ package org.apache.maven.surefire.common.junit48;
  * under the License.
  */
 
+import org.apache.maven.shared.utils.io.SelectorUtils;
 import org.junit.runner.Description;
 import org.junit.runner.manipulation.Filter;
 
@@ -32,11 +33,11 @@ final class FailingMethodFilter
     extends Filter
 {
     // Map from Class -> List of method names. Are the method names hashed to include the signature?
-    private final Map<Class<?>, Set<String>> failingClassMethodMap;
+    private final Map<Class<?>, Set<String>> failingClassMethodPatterns;
 
-    public FailingMethodFilter( Map<Class<?>, Set<String>> failingClassMethodMap )
+    public FailingMethodFilter( Map<Class<?>, Set<String>> failingClassMethodPatterns )
     {
-        this.failingClassMethodMap = failingClassMethodMap;
+        this.failingClassMethodPatterns = failingClassMethodPatterns;
     }
 
     @Override
@@ -59,8 +60,21 @@ final class FailingMethodFilter
             return false;
         }
 
-        Set<String> testMethods = failingClassMethodMap.get( description.getTestClass() );
-        return testMethods != null && testMethods.contains( description.getMethodName() );
+        Set<String> testMethodPatterns = failingClassMethodPatterns.get( description.getTestClass() );
+        String testMethod = description.getMethodName();
+        return testMethodPatterns != null && matchMethod( testMethodPatterns, testMethod );
+    }
+
+    private static boolean matchMethod( Set<String> patterns, String methodName )
+    {
+        for ( String pattern : patterns )
+        {
+            if ( SelectorUtils.match( pattern, methodName ) )
+            {
+                return true;
+            }
+        }
+        return false;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java
index 07280af..f25f657 100644
--- a/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java
+++ b/surefire-providers/common-junit48/src/test/java/org/apache/maven/surefire/common/junit48/FilterFactoryTest.java
@@ -947,6 +947,16 @@ public class FilterFactoryTest
     }
 
     @Test
+    public void testShouldRunClassOnly()
+    {
+        Class<?> testsATest = org.apache.maven.surefire.common.junit48.tests.ATest.class;
+        TestListResolver resolver = new TestListResolver( "**/ATest.java#testSuccessTwo" );
+        assertTrue( resolver.shouldRun( testsATest, null ) );
+        resolver = new TestListResolver( "**/BTest.java#testSuccessTwo" );
+        assertFalse( resolver.shouldRun( testsATest, null ) );
+    }
+
+    @Test
     public void testMatchPatterns()
     {
         String sourceFile = "pkg" + File.separator + "MyTest.class";

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/Filter.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/Filter.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/Filter.java
deleted file mode 100644
index 2dae870..0000000
--- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/Filter.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package org.apache.maven.surefire.junit4;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import java.lang.reflect.Method;
-
-interface Filter
-{
-    boolean shouldRun( Class<?> clazz, Method method );
-}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/be9d9234/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
index a9cab65..12c3983 100644
--- a/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
+++ b/surefire-providers/surefire-junit4/src/main/java/org/apache/maven/surefire/junit4/JUnit4Provider.java
@@ -19,16 +19,14 @@ package org.apache.maven.surefire.junit4;
  * under the License.
  */
 
-import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
-import org.apache.maven.shared.utils.io.SelectorUtils;
+import org.apache.maven.surefire.common.junit4.ClassMethod;
 import org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil;
 import org.apache.maven.surefire.common.junit4.JUnit4RunListener;
 import org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory;
@@ -52,6 +50,8 @@ import org.apache.maven.surefire.util.TestsToRun;
 import org.junit.runner.Description;
 import org.junit.runner.Request;
 import org.junit.runner.Result;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
 import org.junit.runner.notification.RunNotifier;
 
 /**
@@ -60,8 +60,6 @@ import org.junit.runner.notification.RunNotifier;
 public class JUnit4Provider
     extends AbstractProvider
 {
-    private static final Collection<Method> JAVA_LANG_OBJECT_METHODS = Arrays.asList( Object.class.getMethods() );
-
     private final ClassLoader testClassLoader;
 
     private final List<org.junit.runner.notification.RunListener> customRunListeners;
@@ -150,9 +148,10 @@ public class JUnit4Provider
         }
         catch ( Throwable e )
         {
-            reporter.testError( SimpleReportEntry.withException( report.getSourceName(), report.getName(),
-                                                                 new PojoStackTraceWriter( report.getSourceName(),
-                                                                                           report.getName(), e ) ) );
+            String reportName = report.getName();
+            String reportSourceName = report.getSourceName();
+            PojoStackTraceWriter stackWriter = new PojoStackTraceWriter( reportSourceName, reportName, e );
+            reporter.testError( SimpleReportEntry.withException( reportSourceName, reportName, stackWriter ) );
         }
         finally
         {
@@ -165,47 +164,46 @@ public class JUnit4Provider
         JUnitTestFailureListener failureListener = new JUnitTestFailureListener();
         listeners.addListener( failureListener );
         boolean hasMethodFilter = testResolver != null && testResolver.hasMethodPatterns();
-        execute( clazz, listeners, hasMethodFilter ? new TestResolverFilter() : null );
+        execute( clazz, listeners, hasMethodFilter ? new TestResolverFilter() : new NullFilter() );
 
         // Rerun failing tests if rerunFailingTestsCount is larger than 0
         if ( rerunFailingTestsCount > 0 )
         {
             for ( int i = 0; i < rerunFailingTestsCount && !failureListener.getAllFailures().isEmpty(); i++ )
             {
-                Set<String> methodsSet = JUnit4ProviderUtil.generateFailingTests( failureListener.getAllFailures() );
-                String[] methods = methodsSet.toArray( new String[ methodsSet.size() ] );
+                Set<String> failedTests = JUnit4ProviderUtil.generateFailingTests( failureListener.getAllFailures() );
                 failureListener.reset();
-                if ( methods.length != 0 )
+                if ( !failedTests.isEmpty() )
                 {
-                    execute( clazz, listeners, new FailedMethodFilter( methods ) );
+                    executeFailedMethod( clazz, listeners, failedTests );
                 }
             }
         }
     }
 
-    private RunNotifier getRunNotifier( org.junit.runner.notification.RunListener main, Result result,
+    private static RunNotifier getRunNotifier( org.junit.runner.notification.RunListener main, Result result,
                                         List<org.junit.runner.notification.RunListener> others )
     {
-        RunNotifier fNotifier = new RunNotifier();
-        fNotifier.addListener( main );
-        fNotifier.addListener( result.createListener() );
+        RunNotifier notifier = new RunNotifier();
+        notifier.addListener( main );
+        notifier.addListener( result.createListener() );
         for ( org.junit.runner.notification.RunListener listener : others )
         {
-            fNotifier.addListener( listener );
+            notifier.addListener( listener );
         }
-        return fNotifier;
+        return notifier;
     }
 
     // I am not entirely sure as to why we do this explicit freeing, it's one of those
     // pieces of code that just seem to linger on in here ;)
-    private void closeRunNotifier( org.junit.runner.notification.RunListener main,
+    private static void closeRunNotifier( org.junit.runner.notification.RunListener main,
                                    List<org.junit.runner.notification.RunListener> others )
     {
-        RunNotifier fNotifier = new RunNotifier();
-        fNotifier.removeListener( main );
+        RunNotifier notifier = new RunNotifier();
+        notifier.removeListener( main );
         for ( org.junit.runner.notification.RunListener listener : others )
         {
-            fNotifier.removeListener( listener );
+            notifier.removeListener( listener );
         }
     }
 
@@ -260,63 +258,116 @@ public class JUnit4Provider
         return System.getProperty( "surefire.junit4.upgradecheck" ) != null;
     }
 
-    private void execute( Class<?> testClass, RunNotifier fNotifier, Filter filter )
+    private static void execute( Class<?> testClass, RunNotifier notifier, Filter filter )
     {
-        if ( !Modifier.isInterface( testClass.getModifiers() ) )
+        final int classModifiers = testClass.getModifiers();
+
+        // filter.shouldRunClass( testClass )
+        if ( !Modifier.isAbstract( classModifiers ) && !Modifier.isInterface( classModifiers ) )
         {
-            if ( filter != null )
+            Runner runner = Request.aClass( testClass ).filterWith( filter ).getRunner();
+            if ( countTestsInRunner( runner.getDescription() ) != 0 )
             {
-                for ( Method testMethod : testClass.getMethods() )
-                {
-                    if ( !JAVA_LANG_OBJECT_METHODS.contains( testMethod ) )
-                    {
-                        String methodName = testMethod.getName();
-                        boolean accessible = !Modifier.isStatic( testMethod.getModifiers() );
-                        if ( accessible && filter.shouldRun( testClass, testMethod ) )
-                        {
-                            Request.method( testClass, methodName ).getRunner().run( fNotifier );
-                        }
-                    }
-                }
+                runner.run( notifier );
             }
-            else
+        }
+    }
+
+    private static void executeFailedMethod( Class<?> testClass, RunNotifier notifier, Set<String> failedMethods )
+    {
+        for ( String failedMethod : failedMethods )
+        {
+            Request.method( testClass, failedMethod ).getRunner().run( notifier );
+        }
+    }
+
+    /**
+     * JUnit error: test count includes one test-class as a suite which has filtered out all children.
+     * Then the child test has a description "initializationError0(org.junit.runner.manipulation.Filter)"
+     * for JUnit 4.0 or "initializationError(org.junit.runner.manipulation.Filter)" for JUnit 4.12
+     * and Description#isTest() returns true, but this description is not a real test
+     * and therefore it should not be included in the entire test count.
+     */
+    private static int countTestsInRunner( Description description )
+    {
+        if ( description.isSuite() )
+        {
+            int count = 0;
+            for ( Description child : description.getChildren() )
             {
-                Request.aClass( testClass ).getRunner().run( fNotifier );
+                if ( !hasFilteredOutAllChildren( child ) )
+                {
+                    count += countTestsInRunner( child );
+                }
             }
+            return count;
+        }
+        else if ( description.isTest() )
+        {
+            return hasFilteredOutAllChildren( description ) ? 0 : 1;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+
+    private static boolean hasFilteredOutAllChildren( Description description )
+    {
+        String name = description.getDisplayName();
+        // JUnit 4.0: initializationError0; JUnit 4.12: initializationError.
+        if ( name == null )
+        {
+            return true;
+        }
+        else
+        {
+            name = name.trim();
+            return name.startsWith( "initializationError0(org.junit.runner.manipulation.Filter)" )
+                || name.startsWith( "initializationError(org.junit.runner.manipulation.Filter)" );
         }
     }
 
-    private final class TestResolverFilter
-        implements Filter
+    private class TestResolverFilter
+        extends Filter
     {
         private final TestListResolver methodFilter = JUnit4Provider.this.testResolver.createMethodFilters();
 
-        public boolean shouldRun( Class<?> testClass, Method testMethod )
+        private final TestsToRun testsToRun = JUnit4Provider.this.testsToRun;
+
+        @Override
+        public boolean shouldRun( Description description )
+        {
+            // class: Java class name; method: 1. "testMethod" or 2. "testMethod[5+whatever]" in @Parameterized
+            final ClassMethod cm = JUnit4ProviderUtil.cutTestClassAndMethod( description );
+            final boolean isSuite = description.isSuite();
+            final boolean isValidTest = description.isTest() && cm.isValid();
+            final String clazz = cm.getClazz();
+            final String method = cm.getMethod();
+            return isSuite || isValidTest && methodFilter.shouldRun( testsToRun.getClassByName( clazz ), method );
+        }
+
+        @Override
+        public String describe()
         {
-            return methodFilter.shouldRun( testClass, testMethod.getName() );
+            return methodFilter.toString();
         }
     }
 
-    private static class FailedMethodFilter
-        implements Filter
+    private final class NullFilter
+        extends TestResolverFilter
     {
-        private final String[] methodPatterns;
 
-        private FailedMethodFilter( String[] methodPatterns )
+        @Override
+        public boolean shouldRun( Description description )
         {
-            this.methodPatterns = methodPatterns;
+            return true;
         }
 
-        public boolean shouldRun( Class<?> clazz, Method method )
+        @Override
+        public String describe()
         {
-            for ( String methodPattern : methodPatterns )
-            {
-                if ( SelectorUtils.match( methodPattern, method.getName() ) )
-                {
-                    return true;
-                }
-            }
-            return false;
+            return "";
         }
     }
 }