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/11/15 23:25:15 UTC

[1/2] maven-surefire git commit: [SUREFIRE-1185] single method test spews status of every single other test

Repository: maven-surefire
Updated Branches:
  refs/heads/master e29d4e979 -> 021b263ab


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-integration-tests/src/test/resources/surefire-1185/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1185/pom.xml b/surefire-integration-tests/src/test/resources/surefire-1185/pom.xml
new file mode 100644
index 0000000..c7fac09
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/surefire-1185/pom.xml
@@ -0,0 +1,73 @@
+<?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-1185</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>PMC</role>
+      </roles>
+      <timezone>Europe/Bratislava</timezone>
+    </developer>
+  </developers>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.0</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>
+		<dependencies>
+			<dependency>
+				<groupId>org.apache.maven.surefire</groupId>
+				<artifactId>surefire-junit4</artifactId>
+				<version>${surefire.version}</version>
+			</dependency>
+		</dependencies>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-integration-tests/src/test/resources/surefire-1185/src/test/java/pkg/RunningTest.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1185/src/test/java/pkg/RunningTest.java b/surefire-integration-tests/src/test/resources/surefire-1185/src/test/java/pkg/RunningTest.java
new file mode 100644
index 0000000..2469bd3
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/surefire-1185/src/test/java/pkg/RunningTest.java
@@ -0,0 +1,29 @@
+package pkg;
+
+/*
+ * 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.junit.Test;
+
+public class RunningTest {
+    @Test
+    public void test()
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-integration-tests/src/test/resources/surefire-1185/src/test/java/pkg/UnlistedTest.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/resources/surefire-1185/src/test/java/pkg/UnlistedTest.java b/surefire-integration-tests/src/test/resources/surefire-1185/src/test/java/pkg/UnlistedTest.java
new file mode 100644
index 0000000..8348673
--- /dev/null
+++ b/surefire-integration-tests/src/test/resources/surefire-1185/src/test/java/pkg/UnlistedTest.java
@@ -0,0 +1,29 @@
+package pkg;
+
+/*
+ * 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.junit.Test;
+
+public class UnlistedTest {
+    @Test
+    public void test()
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/CombinedCategoryFilter.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/CombinedCategoryFilter.java b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/CombinedCategoryFilter.java
index 9cd2131..aefc208 100644
--- a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/CombinedCategoryFilter.java
+++ b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/CombinedCategoryFilter.java
@@ -40,11 +40,11 @@ final class CombinedCategoryFilter
     @Override
     public boolean shouldRun( Description description )
     {
-        return ( includedFilters.isEmpty() || inOneOfFilters( includedFilters, description ) )
-            && ( excludedFilters.isEmpty() || !inOneOfFilters( excludedFilters, description ) );
+        return ( includedFilters.isEmpty() || anyFilterMatchesDescription( includedFilters, description ) )
+            && ( excludedFilters.isEmpty() || allFiltersMatchDescription( excludedFilters, description ) );
     }
 
-    private boolean inOneOfFilters( Collection<Filter> filters, Description description )
+    private boolean anyFilterMatchesDescription( Collection<Filter> filters, Description description )
     {
         for ( Filter f : filters )
         {
@@ -56,6 +56,18 @@ final class CombinedCategoryFilter
         return false;
     }
 
+    private boolean allFiltersMatchDescription( Collection<Filter> filters, Description description )
+    {
+        for ( Filter f : filters )
+        {
+            if ( !f.shouldRun( description ) )
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+
     @Override
     public String describe()
     {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/MethodFilter.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/MethodFilter.java b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/MethodFilter.java
index 1af5679..a275634 100644
--- a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/MethodFilter.java
+++ b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/MethodFilter.java
@@ -43,11 +43,11 @@ final class MethodFilter
         Collection<Filter> excludedFilters = new LinkedHashSet<Filter>();
         for ( ResolvedTest test : testResolver.getIncludedPatterns() )
         {
-            includedFilters.add( new RequestedTest( test ) );
+            includedFilters.add( new RequestedTest( test, true ) );
         }
         for ( ResolvedTest test : testResolver.getExcludedPatterns() )
         {
-            excludedFilters.add( new RequestedTest( test ) );
+            excludedFilters.add( new RequestedTest( test, false ) );
         }
         combinedFilter = new CombinedCategoryFilter( includedFilters, excludedFilters );
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/RequestedTest.java
----------------------------------------------------------------------
diff --git a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/RequestedTest.java b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/RequestedTest.java
index 567db26..505df6e 100644
--- a/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/RequestedTest.java
+++ b/surefire-providers/common-junit48/src/main/java/org/apache/maven/surefire/common/junit48/RequestedTest.java
@@ -29,10 +29,12 @@ final class RequestedTest
     private static final String CLASS_FILE_EXTENSION = ".class";
 
     private final ResolvedTest test;
+    private final boolean isPositiveFilter;
 
-    RequestedTest( ResolvedTest test )
+    RequestedTest( ResolvedTest test, boolean isPositiveFilter )
     {
         this.test = test;
+        this.isPositiveFilter = isPositiveFilter;
     }
 
     @Override
@@ -40,26 +42,35 @@ final class RequestedTest
     {
         Class<?> realTestClass = description.getTestClass();
         String methodName = description.getMethodName();
-        return realTestClass == null && methodName == null || test.shouldRun( classFile( realTestClass ), methodName );
+        if ( realTestClass == null && methodName == null )
+        {
+            return true;
+        }
+        else
+        {
+            String testClass = classFile( realTestClass );
+            return isPositiveFilter
+                ? test.matchAsInclusive( testClass, methodName )
+                : !test.matchAsExclusive( testClass, methodName );
+        }
     }
 
     @Override
     public String describe()
     {
-        final String classPattern = test.getTestClassPattern();
-        final String methodPattern = test.getTestMethodPattern();
-        String description = classPattern == null ? "" : classPattern;
-        if ( methodPattern != null )
-        {
-            description += "#" + methodPattern;
-        }
-        return description.length() == 0 ? "*" : description;
+        String description = test.toString();
+        return description == null || description.length() == 0 ? "*" : description;
     }
 
     @Override
     public boolean equals( Object o )
     {
-        return this == o || o != null && getClass() == o.getClass() && test.equals( ( (RequestedTest) o ).test );
+        return this == o || o != null && getClass() == o.getClass() && equals( (RequestedTest) o );
+    }
+
+    private boolean equals( RequestedTest o )
+    {
+        return isPositiveFilter == o.isPositiveFilter && test.equals( o.test );
     }
 
     @Override
@@ -70,6 +81,6 @@ final class RequestedTest
 
     private String classFile( Class<?> realTestClass )
     {
-        return realTestClass.getName().replace( '.', '/' ) + CLASS_FILE_EXTENSION;
+        return realTestClass == null ? null : realTestClass.getName().replace( '.', '/' ) + CLASS_FILE_EXTENSION;
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/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 f25f657..d3c280a 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
@@ -34,6 +34,7 @@ import org.junit.runner.manipulation.Filter;
 import java.io.File;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 
 import static org.junit.runner.Description.createSuiteDescription;
 import static org.junit.runner.Description.createTestDescription;
@@ -191,7 +192,7 @@ public class FilterFactoryTest
         assertTrue( resolver.getExcludedPatterns().isEmpty() );
         assertTrue( resolver.getIncludedPatterns().isEmpty() );
         assertTrue( resolver.isEmpty() );
-        assertNull( resolver.getPluginParameterTest() );
+        assertEquals( 0, resolver.getPluginParameterTest().length() );
         assertFalse( resolver.hasExcludedMethodPatterns() );
         assertFalse( resolver.hasIncludedMethodPatterns() );
         assertFalse( resolver.hasMethodPatterns() );
@@ -204,7 +205,7 @@ public class FilterFactoryTest
         assertTrue( resolver.getExcludedPatterns().isEmpty() );
         assertTrue( resolver.getIncludedPatterns().isEmpty() );
         assertTrue( resolver.isEmpty() );
-        assertNull( resolver.getPluginParameterTest() );
+        assertEquals( 0, resolver.getPluginParameterTest().length() );
         assertFalse( resolver.hasExcludedMethodPatterns() );
         assertFalse( resolver.hasIncludedMethodPatterns() );
         assertFalse( resolver.hasMethodPatterns() );
@@ -641,10 +642,10 @@ public class FilterFactoryTest
     }
 
     @Test
-    public void testShouldNotNonExistingMethod()
+    public void testShouldRunSuiteWithIncludedMethod()
     {
         String sourceFile = "pkg" + File.separator + "XMyTest.class";
-        assertFalse( new TestListResolver( "#testMethod" ).shouldRun( sourceFile, null ) );
+        assertTrue( new TestListResolver( "#testMethod" ).shouldRun( sourceFile, null ) );
     }
 
     @Test
@@ -825,9 +826,9 @@ public class FilterFactoryTest
         Filter filter = createMethodFilter( "#nonExisting" );
         JUnitCore core = new JUnitCore();
         Result result = core.run( Request.classes( Suite.class ).filterWith( filter ) );
-        assertFalse( result.wasSuccessful() );
-        assertEquals( 1, result.getRunCount() );//running the Suite
-        assertEquals( 1, result.getFailureCount() );
+        assertTrue( result.wasSuccessful() );
+        assertEquals( 0, result.getRunCount() );//running the Suite
+        assertEquals( 0, result.getFailureCount() );
         assertEquals( 0, result.getIgnoreCount() );
     }
 
@@ -884,7 +885,7 @@ public class FilterFactoryTest
     public void testShouldRunSuite()
     {
         TestListResolver filter = new TestListResolver( "Su?te" );
-        filter = filter.createMethodFilters();
+        filter = TestListResolver.optionallyWildcardFilter( filter );
         JUnitCore core = new JUnitCore();
         Result result = core.run( Request.classes( Suite.class ).filterWith( new MethodFilter( filter ) ) );
         assertTrue( result.wasSuccessful() );
@@ -901,7 +902,7 @@ public class FilterFactoryTest
                                       + "PT#testC*, "
                                       + "!PT.java#testCY[?],"
                                       + "%regex[.*.tests.pt.PT.class#w.*|x.*T.*]" );
-        filter = filter.createMethodFilters();
+        filter = TestListResolver.optionallyWildcardFilter( filter );
         JUnitCore core = new JUnitCore();
         Result result = core.run( Request.classes( PT.class ).filterWith( new MethodFilter( filter ) ) );
         assertTrue( result.wasSuccessful() );
@@ -920,7 +921,7 @@ public class FilterFactoryTest
         // x12T35[0], x12T35[1]
         TestListResolver filter =
             new TestListResolver( "%regex[.*.PT.* # w.*|x(\\d+)T(\\d+)\\[(\\d+)\\]]" );
-        filter = filter.createMethodFilters();
+        filter = TestListResolver.optionallyWildcardFilter( filter );
         JUnitCore core = new JUnitCore();
         Result result = core.run( Request.classes( PT.class ).filterWith( new MethodFilter( filter ) ) );
         assertTrue( result.wasSuccessful() );
@@ -998,7 +999,7 @@ public class FilterFactoryTest
     public void testIncludesExcludes()
     {
         Collection<String> inc = Arrays.asList( "**/NotIncludedByDefault.java", "**/*Test.java" );
-        Collection<String> exc = Arrays.asList( "**/DontRunTest.*" );
+        Collection<String> exc = Collections.singletonList( "**/DontRunTest.*" );
         TestListResolver resolver = new TestListResolver( inc, exc );
         assertFalse( resolver.shouldRun( "org/test/DontRunTest.class", null ) );
         assertTrue( resolver.shouldRun( "org/test/DefaultTest.class", null ) );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/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 5a3bdf6..948d514 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
@@ -62,6 +62,7 @@ import static org.apache.maven.surefire.common.junit4.JUnit4RunListener.rethrowA
 import static org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory.createCustomListeners;
 import static org.apache.maven.surefire.report.ConsoleOutputCapture.startCapture;
 import static org.apache.maven.surefire.report.SimpleReportEntry.withException;
+import static org.apache.maven.surefire.testset.TestListResolver.optionallyWildcardFilter;
 import static org.apache.maven.surefire.testset.TestListResolver.toClassFileName;
 import static org.apache.maven.surefire.util.TestsToRun.fromClass;
 import static org.junit.runner.Request.aClass;
@@ -421,7 +422,7 @@ public class JUnit4Provider
     private class TestResolverFilter
         extends Filter
     {
-        private final TestListResolver methodFilter = JUnit4Provider.this.testResolver.createMethodFilters();
+        private final TestListResolver methodFilter = optionallyWildcardFilter( JUnit4Provider.this.testResolver );
 
         @Override
         public boolean shouldRun( Description description )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
index 9d03a85..f2fa49f 100644
--- a/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
+++ b/surefire-providers/surefire-junit47/src/main/java/org/apache/maven/surefire/junitcore/JUnitCoreProvider.java
@@ -54,6 +54,7 @@ import static java.util.Collections.unmodifiableCollection;
 import static org.apache.maven.surefire.common.junit4.JUnit4ProviderUtil.generateFailingTests;
 import static org.apache.maven.surefire.common.junit4.JUnit4RunListenerFactory.createCustomListeners;
 import static org.apache.maven.surefire.junitcore.ConcurrentRunListener.createInstance;
+import static org.apache.maven.surefire.testset.TestListResolver.optionallyWildcardFilter;
 
 /**
  * @author Kristian Rosenvold
@@ -272,8 +273,8 @@ public class JUnitCoreProvider
     {
         final FilterFactory factory = new FilterFactory( testClassLoader );
         Filter groupFilter = factory.createGroupFilter( providerParameters.getProviderProperties() );
-        TestListResolver methodFilter = createMethodFilter();
-        boolean onlyGroups = methodFilter == null || methodFilter.isEmpty();
+        TestListResolver methodFilter = optionallyWildcardFilter( testResolver );
+        boolean onlyGroups = methodFilter.isEmpty() || methodFilter.isWildcard();
         return onlyGroups ? groupFilter : factory.and( groupFilter, factory.createMethodFilter( methodFilter ) );
     }
 
@@ -282,9 +283,4 @@ public class JUnitCoreProvider
         TestsToRun scanned = scanResult.applyFilter( scannerFilter, testClassLoader );
         return runOrderCalculator.orderTestClasses( scanned );
     }
-
-    private TestListResolver createMethodFilter()
-    {
-        return testResolver == null ? null : testResolver.createMethodFilters();
-    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/MethodSelector.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/MethodSelector.java b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/MethodSelector.java
index cdb53f0..9c601bb 100644
--- a/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/MethodSelector.java
+++ b/surefire-providers/surefire-testng-utils/src/main/java/org/apache/maven/surefire/testng/utils/MethodSelector.java
@@ -36,7 +36,7 @@ import org.testng.ITestNGMethod;
 public class MethodSelector
     implements IMethodSelector
 {
-    private static TestListResolver testListResolver = null;
+    private static volatile TestListResolver testListResolver = null;
 
     public void setTestMethods( List arg0 )
     {
@@ -59,7 +59,7 @@ public class MethodSelector
 
     private static boolean shouldRun( ITestNGMethod test )
     {
-        TestListResolver resolver = MethodSelector.testListResolver;
+        TestListResolver resolver = testListResolver;
         boolean hasTestResolver = resolver != null && !resolver.isEmpty();
         return hasTestResolver && resolver.shouldRun( test.getRealClass(), test.getMethodName() );
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
index 6faf033..75d8463 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGProvider.java
@@ -41,6 +41,8 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.maven.surefire.testset.TestListResolver.optionallyWildcardFilter;
+
 /**
  * @author Kristian Rosenvold
  * @noinspection UnusedDeclaration
@@ -203,7 +205,7 @@ public class TestNGProvider
     private TestNGDirectoryTestSuite newDirectorySuite()
     {
         return new TestNGDirectoryTestSuite( testRequest.getTestSourceDirectory().toString(), providerProperties,
-                                             reporterConfiguration.getReportsDirectory(), createMethodFilter(),
+                                             reporterConfiguration.getReportsDirectory(), getTestFilter(),
                                              runOrderCalculator, scanResult, mainCliOptions,
                                              getSkipAfterFailureCount() );
     }
@@ -245,13 +247,13 @@ public class TestNGProvider
 
     private boolean hasSpecificTests()
     {
-        TestListResolver tests = testRequest.getTestListResolver();
-        return tests != null && !tests.isEmpty();
+        TestListResolver specificTestPatterns = testRequest.getTestListResolver();
+        return !specificTestPatterns.isEmpty() && !specificTestPatterns.isWildcard();
     }
 
-    private TestListResolver createMethodFilter()
+    private TestListResolver getTestFilter()
     {
-        TestListResolver tests = testRequest.getTestListResolver();
-        return tests == null ? null : tests.createMethodFilters();
+        TestListResolver filter = optionallyWildcardFilter( testRequest.getTestListResolver() );
+        return filter.isWildcard() ? TestListResolver.getEmpty() : filter;
     }
 }


[2/2] maven-surefire git commit: [SUREFIRE-1185] single method test spews status of every single other test

Posted by ti...@apache.org.
[SUREFIRE-1185] single method test spews status of every single other 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/021b263a
Tree: http://git-wip-us.apache.org/repos/asf/maven-surefire/tree/021b263a
Diff: http://git-wip-us.apache.org/repos/asf/maven-surefire/diff/021b263a

Branch: refs/heads/master
Commit: 021b263ab29a11243c7c7a8aa1a4df2345d292ce
Parents: e29d4e9
Author: Tibor17 <ti...@lycos.com>
Authored: Sun Nov 15 23:22:10 2015 +0100
Committer: Tibor17 <ti...@lycos.com>
Committed: Sun Nov 15 23:22:10 2015 +0100

----------------------------------------------------------------------
 .../plugin/surefire/AbstractSurefireMojo.java   |  59 +-
 .../surefire/booterclient/BooterSerializer.java |   6 +-
 .../plugin/surefire/util/DependencyScanner.java |  12 +-
 .../plugin/surefire/util/DirectoryScanner.java  |  13 +-
 .../surefire/util/DependenciesScannerTest.java  |  45 +-
 .../surefire/util/DirectoryScannerTest.java     |  50 +-
 .../src/site/apt/examples/single-test.apt.vm    |   6 +
 .../surefire/testset/GenericTestPattern.java    |   9 +-
 .../maven/surefire/testset/ResolvedTest.java    |  71 ++-
 .../surefire/testset/TestListResolver.java      | 134 ++---
 .../maven/surefire/testset/TestRequest.java     |   2 +-
 .../java/org/apache/maven/JUnit4SuiteTest.java  |   4 +-
 .../surefire/testset/FundamentalFilterTest.java | 581 +++++++++++++++++++
 .../surefire/testset/TestListResolverTest.java  | 186 ++++--
 .../surefire/booter/BooterDeserializer.java     |   2 -
 .../its/AbstractTestMultipleMethodPatterns.java |  17 +-
 .../jiras/Surefire1185DoNotSpawnTestsIT.java    |  62 ++
 .../src/test/resources/surefire-1185/pom.xml    |  73 +++
 .../src/test/java/pkg/RunningTest.java          |  29 +
 .../src/test/java/pkg/UnlistedTest.java         |  29 +
 .../common/junit48/CombinedCategoryFilter.java  |  18 +-
 .../surefire/common/junit48/MethodFilter.java   |   4 +-
 .../surefire/common/junit48/RequestedTest.java  |  35 +-
 .../common/junit48/FilterFactoryTest.java       |  23 +-
 .../maven/surefire/junit4/JUnit4Provider.java   |   3 +-
 .../surefire/junitcore/JUnitCoreProvider.java   |  10 +-
 .../surefire/testng/utils/MethodSelector.java   |   4 +-
 .../maven/surefire/testng/TestNGProvider.java   |  14 +-
 28 files changed, 1222 insertions(+), 279 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
index 9c6a30e..ca3a4be 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/AbstractSurefireMojo.java
@@ -714,9 +714,14 @@ public abstract class AbstractSurefireMojo
     protected abstract void handleSummary( RunResult summary, Exception firstForkException )
         throws MojoExecutionException, MojoFailureException;
 
+    protected abstract boolean isSkipExecution();
+
     protected abstract String[] getDefaultIncludes();
 
-    protected abstract boolean isSkipExecution();
+    private String getDefaultExcludes()
+    {
+        return "**/*$*";
+    }
 
     private SurefireDependencyResolver dependencyResolver;
 
@@ -769,9 +774,7 @@ public abstract class AbstractSurefireMojo
     private DefaultScanResult scanDirectories()
         throws MojoFailureException
     {
-        DirectoryScanner scanner = new DirectoryScanner( getTestClassesDirectory(),
-                                                         getIncludedAndExcludedTests(),
-                                                         getSpecificTests() );
+        DirectoryScanner scanner = new DirectoryScanner( getTestClassesDirectory(), getIncludedAndExcludedTests() );
         return scanner.scan();
     }
 
@@ -789,9 +792,7 @@ public abstract class AbstractSurefireMojo
                 @SuppressWarnings( "unchecked" )
                 List<File> dependenciesToScan =
                     DependencyScanner.filter( project.getTestArtifacts(), Arrays.asList( getDependenciesToScan() ) );
-                DependencyScanner scanner = new DependencyScanner( dependenciesToScan,
-                                                                   getIncludedAndExcludedTests(),
-                                                                   getSpecificTests() );
+                DependencyScanner scanner = new DependencyScanner( dependenciesToScan, getIncludedAndExcludedTests() );
                 return scanner.scan();
             }
             catch ( Exception e )
@@ -1432,19 +1433,20 @@ public abstract class AbstractSurefireMojo
     private ProviderConfiguration createProviderConfiguration( RunOrderParameters runOrderParameters )
         throws MojoExecutionException, MojoFailureException
     {
-        ReporterConfiguration reporterConfiguration =
+        final ReporterConfiguration reporterConfiguration =
             new ReporterConfiguration( getReportsDirectory(), isTrimStackTrace() );
 
-        Artifact testNgArtifact = getTestNgArtifact();
-        DirectoryScannerParameters directoryScannerParameters = null;
+        final Artifact testNgArtifact = getTestNgArtifact();
         final boolean isTestNg = testNgArtifact != null;
-        TestArtifactInfo testNg =
+        final TestArtifactInfo testNg =
             isTestNg ? new TestArtifactInfo( testNgArtifact.getVersion(), testNgArtifact.getClassifier() ) : null;
-        TestRequest testSuiteDefinition = new TestRequest( suiteXmlFiles(), getTestSourceDirectory(),
-                                                           getSpecificTests(), getRerunFailingTestsCount() );
+        final TestRequest testSuiteDefinition = new TestRequest( suiteXmlFiles(),
+                                                                 getTestSourceDirectory(),
+                                                                 getSpecificTests(),
+                                                                 getRerunFailingTestsCount() );
 
         final boolean actualFailIfNoTests;
-
+        DirectoryScannerParameters directoryScannerParameters = null;
         if ( hasSuiteXmlFiles() && !isSpecificTestSpecified() )
         {
             actualFailIfNoTests = getFailIfNoTests() != null && getFailIfNoTests();
@@ -1472,7 +1474,7 @@ public abstract class AbstractSurefireMojo
             List<String> actualIncludes = getIncludeList(); // Collections.emptyList(); behaves same
             List<String> actualExcludes = getExcludeList(); // Collections.emptyList(); behaves same
             // Collections.emptyList(); behaves same
-            List<String> specificTests = new ArrayList<String>( getSpecificTests().getTestSpecificClasses() );
+            List<String> specificTests = Collections.emptyList();
 
             directoryScannerParameters =
                 new DirectoryScannerParameters( getTestClassesDirectory(), actualIncludes, actualExcludes,
@@ -1626,11 +1628,7 @@ public abstract class AbstractSurefireMojo
         List<String> actualExcludes = null;
         if ( isSpecificTestSpecified() )
         {
-            // Check to see if we are running a single test. The raw parameter will
-            // come through if it has not been set.
-            // FooTest -> **/FooTest.java
-
-            actualExcludes = new ArrayList<String>();
+            actualExcludes = Collections.emptyList();
         }
         else
         {
@@ -1639,7 +1637,6 @@ public abstract class AbstractSurefireMojo
                 actualExcludes = readListFromFile( getExcludesFile() );
             }
 
-            // If we have excludesFile, and we have excludes, then append excludes to excludesFile content
             if ( actualExcludes == null )
             {
                 actualExcludes = getExcludes();
@@ -1651,11 +1648,9 @@ public abstract class AbstractSurefireMojo
 
             checkMethodFilterInIncludesExcludes( actualExcludes );
 
-            // defaults here, qdox doesn't like the end javadoc value
-            // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason
             if ( actualExcludes == null || actualExcludes.isEmpty() )
             {
-                actualExcludes = Collections.singletonList( "**/*$*" );
+                actualExcludes = Collections.singletonList( getDefaultExcludes() );
             }
         }
         return filterNulls( actualExcludes );
@@ -1667,7 +1662,8 @@ public abstract class AbstractSurefireMojo
         List<String> includes = null;
         if ( isSpecificTestSpecified() )
         {
-            includes = Collections.singletonList( getTest() );
+            includes = new ArrayList<String>();
+            Collections.addAll( includes, StringUtils.split( getTest(), "," ) );
         }
         else
         {
@@ -1676,7 +1672,6 @@ public abstract class AbstractSurefireMojo
                 includes = readListFromFile( getIncludesFile() );
             }
 
-            // If we have includesFile, and we have includes, then append includes to includesFile content
             if ( includes == null )
             {
                 includes = getIncludes();
@@ -1688,8 +1683,6 @@ public abstract class AbstractSurefireMojo
 
             checkMethodFilterInIncludesExcludes( includes );
 
-            // defaults here, qdox doesn't like the end javadoc value
-            // Have to wrap in an ArrayList as surefire expects an ArrayList instead of a List for some reason
             if ( includes == null || includes.isEmpty() )
             {
                 includes = Arrays.asList( getDefaultIncludes() );
@@ -1743,7 +1736,11 @@ public abstract class AbstractSurefireMojo
         {
             if ( item != null )
             {
-                result.add( item );
+                item = item.trim();
+                if ( item.length() != 0 )
+                {
+                    result.add( item );
+                }
             }
         }
 
@@ -1807,7 +1804,7 @@ public abstract class AbstractSurefireMojo
         return getProjectArtifactMap().get( "junit:junit-dep" );
     }
 
-    protected ForkStarter createForkStarter( ProviderInfo provider, ForkConfiguration forkConfiguration,
+    private ForkStarter createForkStarter( ProviderInfo provider, ForkConfiguration forkConfiguration,
                                              ClassLoaderConfiguration classLoaderConfiguration,
                                              RunOrderParameters runOrderParameters, Log log )
         throws MojoExecutionException, MojoFailureException
@@ -1820,7 +1817,7 @@ public abstract class AbstractSurefireMojo
                                 getForkedProcessTimeoutInSeconds(), startupReportConfiguration, log );
     }
 
-    protected InPluginVMSurefireStarter createInprocessStarter( ProviderInfo provider,
+    private InPluginVMSurefireStarter createInprocessStarter( ProviderInfo provider,
                                                                 ClassLoaderConfiguration classLoaderConfiguration,
                                                                 RunOrderParameters runOrderParameters )
         throws MojoExecutionException, MojoFailureException

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
index 21807f5..e67efb0 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/booterclient/BooterSerializer.java
@@ -97,10 +97,8 @@ class BooterSerializer
         {
             properties.setProperty( SOURCE_DIRECTORY, testSuiteDefinition.getTestSourceDirectory() );
             properties.addList( testSuiteDefinition.getSuiteXmlFiles(), TEST_SUITE_XML_FILES );
-            TestListResolver methodFilter = testSuiteDefinition.getTestListResolver();
-            String requestedTest =
-                methodFilter == null || methodFilter.isEmpty() ? null : methodFilter.getPluginParameterTest();
-            properties.setNullableProperty( REQUESTEDTEST, requestedTest );
+            TestListResolver testFilter = testSuiteDefinition.getTestListResolver();
+            properties.setProperty( REQUESTEDTEST, testFilter == null ? "" : testFilter.getPluginParameterTest() );
             properties.setNullableProperty( RERUN_FAILING_TESTS_COUNT,
                                             String.valueOf( testSuiteDefinition.getRerunFailingTestsCount() ) );
         }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java
index 1fb14f5..9faf8e6 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DependencyScanner.java
@@ -46,16 +46,12 @@ public class DependencyScanner
 {
     private final List<File> dependenciesToScan;
 
-    private final TestListResolver includedAndExcludedTests;
+    private final TestListResolver filter;
 
-    private final TestListResolver specificTests;
-
-    public DependencyScanner( List<File> dependenciesToScan,
-                              TestListResolver includedAndExcludedTests, TestListResolver specificTests )
+    public DependencyScanner( List<File> dependenciesToScan, TestListResolver filter )
     {
         this.dependenciesToScan = dependenciesToScan;
-        this.includedAndExcludedTests = includedAndExcludedTests;
-        this.specificTests = specificTests;
+        this.filter = filter;
     }
 
     public DefaultScanResult scan()
@@ -66,7 +62,7 @@ public class DependencyScanner
         {
             try
             {
-                scanArtifact( artifact, includedAndExcludedTests.and( specificTests ), classes );
+                scanArtifact( artifact, filter, classes );
             }
             catch ( IOException e )
             {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java
index 8b4c434..6dc81f0 100644
--- a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java
+++ b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/util/DirectoryScanner.java
@@ -36,24 +36,19 @@ public class DirectoryScanner
 {
     private final File basedir;
 
-    private final TestListResolver includedAndExcludedTests;
+    private final TestListResolver filter;
 
-    private final TestListResolver specificTests;
-
-    public DirectoryScanner( File basedir, TestListResolver includedAndExcludedTests, TestListResolver specificTests )
+    public DirectoryScanner( File basedir, TestListResolver filter )
     {
         this.basedir = basedir;
-        this.includedAndExcludedTests = includedAndExcludedTests;
-        this.specificTests = specificTests;
+        this.filter = filter;
     }
 
     public DefaultScanResult scan()
     {
         FileScanner scanner = new FileScanner( basedir, "class" );
         List<String> result = new ArrayList<String>();
-        TestListResolver includedExcludedClasses = includedAndExcludedTests.createClassFilters();
-        TestListResolver specificClasses = specificTests.createClassFilters();
-        scanner.scanTo( result, includedExcludedClasses.and( specificClasses ) );
+        scanner.scanTo( result, filter );
         return new DefaultScanResult( result );
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java
index f4eb9e8..c8dd436 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DependenciesScannerTest.java
@@ -44,44 +44,49 @@ public class DependenciesScannerTest
         File testFile = writeTestFile();
 
         // use target as people can configure ide to compile in an other place than maven
-        Artifact artifact = new DefaultArtifact(
-                "org.surefire.dependency", "test-jar",
-                VersionRange.createFromVersion("1.0"), "test", "jar", "tests", null);
-        artifact.setFile(testFile);
+        Artifact artifact =
+            new DefaultArtifact( "org.surefire.dependency", "test-jar", VersionRange.createFromVersion( "1.0" ), "test",
+                                 "jar", "tests", null );
+        artifact.setFile( testFile );
 
         List<String> scanDependencies = new ArrayList<String>();
-        scanDependencies.add("org.surefire.dependency:test-jar");
+        scanDependencies.add( "org.surefire.dependency:test-jar" );
 
         List<String> include = new ArrayList<String>();
         include.add( "**/*A.java" );
         List<String> exclude = new ArrayList<String>();
 
-        DependencyScanner scanner = new DependencyScanner(
-                DependencyScanner.filter(Collections.singletonList(artifact), scanDependencies),
-                new TestListResolver( include, exclude ), new TestListResolver( "" ) );
+        DependencyScanner scanner =
+            new DependencyScanner( DependencyScanner.filter( Collections.singletonList( artifact ), scanDependencies ),
+                                   new TestListResolver( include, exclude ) );
 
         ScanResult classNames = scanner.scan();
         assertNotNull( classNames );
-        System.out.println( "classNames " + classNames.toString() );
         assertEquals( 1, classNames.size() );
-        System.out.println(classNames.getClassName(0));
 
         Map<String, String> props = new HashMap<String, String>();
         classNames.writeTo( props );
         assertEquals( 1, props.size() );
     }
 
-    private File writeTestFile() throws Exception {
-        File output = new File("target/DependenciesScannerTest-tests.jar");
+    private File writeTestFile()
+        throws Exception
+    {
+        File output = new File( "target/DependenciesScannerTest-tests.jar" );
         output.delete();
 
-        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(output));
-
-        out.putNextEntry(new ZipEntry("org/test/TestA.class"));
-        out.closeEntry();
-        out.putNextEntry(new ZipEntry("org/test/TestB.class"));
-        out.closeEntry();
-        out.close();
-        return output;
+        ZipOutputStream out = new ZipOutputStream( new FileOutputStream( output ) );
+        try
+        {
+            out.putNextEntry( new ZipEntry( "org/test/TestA.class" ) );
+            out.closeEntry();
+            out.putNextEntry( new ZipEntry( "org/test/TestB.class" ) );
+            out.closeEntry();
+            return output;
+        }
+        finally
+        {
+            out.close();
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java
----------------------------------------------------------------------
diff --git a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java
index db28917..20d9f19 100644
--- a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java
+++ b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/util/DirectoryScannerTest.java
@@ -19,38 +19,60 @@ package org.apache.maven.plugin.surefire.util;
  * under the License.
  */
 
-import junit.framework.TestCase;
 import org.apache.maven.surefire.testset.TestListResolver;
 import org.apache.maven.surefire.util.ScanResult;
+import org.hamcrest.Matcher;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 import java.io.File;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.junit.runners.Parameterized.*;
 
 /**
  * @author Kristian Rosenvold
  */
+@RunWith( Parameterized.class )
 public class DirectoryScannerTest
-    extends TestCase
 {
-    public void testLocateTestClasses()
+
+    @Parameters( name = "\"{0}\" should count {1} classes" )
+    public static Object[][] data() {
+        return new Object[][] {
+            { "**/*ZT*A.java", is( 3 ) },
+            { "**/*ZT*A.java#testMethod", is( 3 ) },
+            { "**/*ZT?A.java#testMethod, !*ZT2A", is( 2 ) },
+            { "**/*ZT?A.java#testMethod, !*ZT2A#testMethod", is( 3 ) },
+            { "#testMethod", is( greaterThanOrEqualTo( 3 ) ) },
+        };
+    }
+
+    @Parameter( 0 )
+    public String filter;
+
+    @Parameter( 1 )
+    public Matcher<? super Integer> expectedClassesCount;
+
+    @Test
+    public void locateTestClasses()
         throws Exception
     {
         // use target as people can configure ide to compile in an other place than maven
         File baseDir = new File( new File( "target/test-classes" ).getCanonicalPath() );
-        List<String> include = new ArrayList<String>();
-        include.add( "**/*ZT*A.java" );
-        List<String> exclude = new ArrayList<String>();
-
-        DirectoryScanner surefireDirectoryScanner =
-            new DirectoryScanner( baseDir, new TestListResolver( include, exclude ), new TestListResolver( "" ) );
+        TestListResolver resolver = new TestListResolver( filter );
+        DirectoryScanner surefireDirectoryScanner = new DirectoryScanner( baseDir, resolver );
 
         ScanResult classNames = surefireDirectoryScanner.scan();
-        assertNotNull( classNames );
-        System.out.println( "classNames " + Collections.singletonList(classNames));
-        assertEquals( 3, classNames.size() );
+        assertThat( classNames, is( notNullValue() ) );
+        assertThat( classNames.size(), is( expectedClassesCount ) );
 
         Map<String, String> props = new HashMap<String, String>();
         classNames.writeTo( props );
-        assertEquals( 3, props.size() );
+        assertThat( props.values(), hasSize( expectedClassesCount ) );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/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 6b44bde..af75e17 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
@@ -37,6 +37,12 @@ Running a Single Test
 mvn -Dtest=TestCircle test
 +---+
 
+If you have multiple executions configured in surefire plugin within your POM, you may want to execute the only default test phase:
+
++---+
+mvn surefire:test -Dtest=TestCircle
++---+
+
   The value for the <<<test>>> parameter is the name of the test class (without the extension; we'll strip off the extension if you accidentally provide one).
 #{else}
   During development, you may run a single test class repeatedly. To run this

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java
index 585351c..4db54a7 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/GenericTestPattern.java
@@ -24,12 +24,11 @@ import java.util.Set;
 /**
  * Resolves string test patterns in object oriented patterns {@code P}.
  *
- * @param <T>    itself
  * @param <P>    resolved atomic test, object oriented - not necessary to be a string
  * @param <C>    test class, or null if not mandatory
  * @param <M>    test method, or null if not mandatory
  */
-public interface GenericTestPattern<T extends GenericTestPattern, P, C, M>
+public interface GenericTestPattern<P, C, M>
     extends TestFilter<C, M>
 {
     boolean hasIncludedMethodPatterns();
@@ -38,10 +37,6 @@ public interface GenericTestPattern<T extends GenericTestPattern, P, C, M>
 
     boolean hasMethodPatterns();
 
-    T createMethodFilters();
-
-    T createClassFilters();
-
     boolean isEmpty();
 
     String getPluginParameterTest();
@@ -49,6 +44,4 @@ public interface GenericTestPattern<T extends GenericTestPattern, P, C, M>
     Set<P> getIncludedPatterns();
 
     Set<P> getExcludedPatterns();
-
-    Set<String> getTestSpecificClasses();
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java
index 635010e..558aaed 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java
@@ -107,7 +107,8 @@ public final class ResolvedTest
     }
 
     /**
-     * Test class file pattern, e.g. org&#47;**&#47;Cat*.class<br/>
+     * Test class file pattern, e.g. org&#47;**&#47;Cat*.class<br/>, or null if not any
+     * and {@link #hasTestClassPattern()} returns false.
      * Other examples: org&#47;animals&#47;Cat*, org&#47;animals&#47;Ca?.class, %regex[Cat.class|Dog.*]<br/>
      * <br/>
      * '*' means zero or more characters<br>
@@ -124,7 +125,7 @@ public final class ResolvedTest
     }
 
     /**
-     * Test method, e.g. "realTestMethod".<br/>
+     * Test method, e.g. "realTestMethod".<br/>, or null if not any and {@link #hasTestMethodPattern()} returns false.
      * Other examples: test* or testSomethin? or %regex[testOne|testTwo] or %ant[testOne|testTwo]<br/>
      * <br/>
      * '*' means zero or more characters<br>
@@ -155,35 +156,20 @@ public final class ResolvedTest
         return classPattern == null && methodPattern == null;
     }
 
-    public boolean shouldRun( String testClassFile, String methodName )
+    public boolean matchAsInclusive( String testClassFile, String methodName )
     {
-        if ( isEmpty() )
-        {
-            return true;
-        }
+        testClassFile = tryBlank( testClassFile );
+        methodName = tryBlank( methodName );
 
-        boolean matchedMethodPattern = false;
+        return isEmpty() || alwaysInclusiveQuietly( testClassFile ) || match( testClassFile, methodName );
+    }
 
-        if ( methodPattern != null && methodName != null )
-        {
-            if ( SelectorUtils.matchPath( methodPattern, methodName ) )
-            {
-                matchedMethodPattern = true;
-            }
-            else
-            {
-                return false;
-            }
-        }
+    public boolean matchAsExclusive( String testClassFile, String methodName )
+    {
+        testClassFile = tryBlank( testClassFile );
+        methodName = tryBlank( methodName );
 
-        if ( classPattern != null )
-        {
-            return isRegexTestClassPattern ? matchClassRegexPatter( testClassFile ) : matchClassPatter( testClassFile );
-        }
-        else
-        {
-            return matchedMethodPattern;
-        }
+        return !isEmpty() && canMatchExclusive( testClassFile, methodName ) && match( testClassFile, methodName );
     }
 
     @Override
@@ -240,6 +226,37 @@ public final class ResolvedTest
         return isRegex && description != null ? wrapRegex( description ) : description;
     }
 
+    private boolean canMatchExclusive( String testClassFile, String methodName )
+    {
+        return testClassFile == null && methodName != null && classPattern == null && methodPattern != null
+            || testClassFile != null && methodName == null && classPattern != null && methodPattern == null
+            || testClassFile != null && methodName != null && ( classPattern != null || methodPattern != null );
+    }
+
+    /**
+     * Prevents {@link #match(String, String)} from throwing NPE in situations when inclusive returns true.
+     */
+    private boolean alwaysInclusiveQuietly( String testClassFile )
+    {
+        return testClassFile == null && classPattern != null;
+    }
+
+    private boolean match( String testClassFile, String methodName )
+    {
+        return ( classPattern == null || matchTestClassFile( testClassFile ) )
+            && ( methodPattern == null || methodName == null || matchMethodName( methodName ) );
+    }
+
+    private boolean matchTestClassFile( String testClassFile )
+    {
+        return isRegexTestClassPattern ? matchClassRegexPatter( testClassFile ) : matchClassPatter( testClassFile );
+    }
+
+    private boolean matchMethodName( String methodName )
+    {
+        return SelectorUtils.matchPath( methodPattern, methodName );
+    }
+
     private boolean matchClassPatter( String testClassFile )
     {
         //@todo We have to use File.separator only because the MatchPatterns is using it internally - cannot override.

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/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 6bda2ad..c54bd97 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
@@ -19,17 +19,18 @@ package org.apache.maven.surefire.testset;
  * under the License.
  */
 
-import org.apache.maven.shared.utils.StringUtils;
-import org.apache.maven.shared.utils.io.SelectorUtils;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.Set;
 
+import static org.apache.maven.shared.utils.StringUtils.isBlank;
+import static org.apache.maven.shared.utils.StringUtils.isNotBlank;
+import static org.apache.maven.shared.utils.StringUtils.split;
+import static org.apache.maven.shared.utils.io.SelectorUtils.PATTERN_HANDLER_SUFFIX;
+import static org.apache.maven.shared.utils.io.SelectorUtils.REGEX_HANDLER_PREFIX;
 import static java.util.Collections.singleton;
-import static java.util.Collections.emptySet;
 
 /**
  * Resolved multi pattern filter e.g. -Dtest=MyTest#test,!AnotherTest#otherTest into an object model
@@ -40,20 +41,18 @@ import static java.util.Collections.emptySet;
  * using specific ClassLoader.
  */
 public class TestListResolver
-    implements GenericTestPattern<TestListResolver, ResolvedTest, String, String>
+    implements GenericTestPattern<ResolvedTest, String, String>
 {
     private static final String JAVA_CLASS_FILE_EXTENSION = ".class";
 
-    private static final Set<ResolvedTest> EMPTY_TEST_PATTERNS = emptySet();
+    private static final TestListResolver WILDCARD = new TestListResolver( "*" + JAVA_CLASS_FILE_EXTENSION );
 
-    private static final Set<String> EMPTY_SPECIFIC_TESTS = emptySet();
+    private static final TestListResolver EMPTY = new TestListResolver( "" );
 
     private final Set<ResolvedTest> includedPatterns;
 
     private final Set<ResolvedTest> excludedPatterns;
 
-    private final Set<String> specificClasses;
-
     private final boolean hasIncludedMethodPatterns;
 
     private final boolean hasExcludedMethodPatterns;
@@ -63,13 +62,12 @@ public class TestListResolver
         final IncludedExcludedPatterns patterns = new IncludedExcludedPatterns();
         final Set<ResolvedTest> includedFilters = new LinkedHashSet<ResolvedTest>( 0 );
         final Set<ResolvedTest> excludedFilters = new LinkedHashSet<ResolvedTest>( 0 );
-        final Set<String> specificClasses = new LinkedHashSet<String>( 0 );
 
         for ( final String csvTests : tests )
         {
-            if ( StringUtils.isNotBlank( csvTests ) )
+            if ( isNotBlank( csvTests ) )
             {
-                for ( String request : StringUtils.split( csvTests, "," ) )
+                for ( String request : split( csvTests, "," ) )
                 {
                     request = request.trim();
                     if ( request.length() != 0 && !request.equals( "!" ) )
@@ -80,17 +78,6 @@ public class TestListResolver
             }
         }
 
-        for ( ResolvedTest test : includedFilters )
-        {
-            populateSpecificClasses( specificClasses, test );
-        }
-
-        for ( ResolvedTest test : excludedFilters )
-        {
-            populateSpecificClasses( specificClasses, test );
-        }
-
-        this.specificClasses = Collections.unmodifiableSet( specificClasses );
         this.includedPatterns = Collections.unmodifiableSet( includedFilters );
         this.excludedPatterns = Collections.unmodifiableSet( excludedFilters );
         this.hasIncludedMethodPatterns = patterns.hasIncludedMethodPatterns;
@@ -111,16 +98,21 @@ public class TestListResolver
      * Used only in method filter.
      */
     private TestListResolver( boolean hasIncludedMethodPatterns, boolean hasExcludedMethodPatterns,
-                              Set<String> specificClasses, Set<ResolvedTest> includedPatterns,
-                              Set<ResolvedTest> excludedPatterns )
+                              Set<ResolvedTest> includedPatterns, Set<ResolvedTest> excludedPatterns )
     {
         this.includedPatterns = includedPatterns;
         this.excludedPatterns = excludedPatterns;
-        this.specificClasses = specificClasses;
         this.hasIncludedMethodPatterns = hasIncludedMethodPatterns;
         this.hasExcludedMethodPatterns = hasExcludedMethodPatterns;
     }
 
+    public static TestListResolver newTestListResolver( Set<ResolvedTest> includedPatterns,
+                                                        Set<ResolvedTest> excludedPatterns )
+    {
+        return new TestListResolver( haveMethodPatterns( includedPatterns ), haveMethodPatterns( excludedPatterns ),
+                                     includedPatterns, excludedPatterns );
+    }
+
     public boolean hasIncludedMethodPatterns()
     {
         return hasIncludedMethodPatterns;
@@ -137,21 +129,29 @@ public class TestListResolver
     }
 
     /**
-     * Method filter.
+     *
+     * @param resolver    filter possibly having method patterns
+     * @return {@code resolver} if {@link TestListResolver#hasMethodPatterns() resolver.hasMethodPatterns()}
+     * returns <tt>true</tt>; Otherwise wildcard filter <em>*.class</em> is returned.
      */
-    public TestListResolver createMethodFilters()
+    public static TestListResolver optionallyWildcardFilter( TestListResolver resolver )
     {
-        boolean hasMethodPatterns = hasMethodPatterns();
-        Set<ResolvedTest> inc = hasMethodPatterns ? getIncludedPatterns() : EMPTY_TEST_PATTERNS;
-        Set<ResolvedTest> exc = hasMethodPatterns ? getExcludedPatterns() : EMPTY_TEST_PATTERNS;
-        Set<String> specificClasses = hasMethodPatterns ? getTestSpecificClasses() : EMPTY_SPECIFIC_TESTS;
-        return new TestListResolver( hasIncludedMethodPatterns(), hasExcludedMethodPatterns(), specificClasses,
-                                     inc, exc );
+        return resolver.hasMethodPatterns() ? resolver : WILDCARD;
     }
 
-    public TestListResolver createClassFilters()
+    public static TestListResolver getWildcard()
     {
-        return hasMethodPatterns() ? new TestListResolver( "" ) : this;
+        return WILDCARD;
+    }
+
+    public static TestListResolver getEmpty()
+    {
+        return EMPTY;
+    }
+
+    public final boolean isWildcard()
+    {
+        return equals( WILDCARD );
     }
 
     public TestFilter<String, String> and( final TestListResolver another )
@@ -185,7 +185,7 @@ public class TestListResolver
 
     public boolean shouldRun( String testClassFile, String methodName )
     {
-        if ( isEmpty() || StringUtils.isBlank( testClassFile ) && StringUtils.isBlank( methodName ) )
+        if ( isEmpty() || isBlank( testClassFile ) && isBlank( methodName ) )
         {
             return true;
         }
@@ -201,7 +201,7 @@ public class TestListResolver
             {
                 for ( ResolvedTest filter : getIncludedPatterns() )
                 {
-                    if ( filter.shouldRun( testClassFile, methodName ) )
+                    if ( filter.matchAsInclusive( testClassFile, methodName ) )
                     {
                         shouldRun = true;
                         break;
@@ -213,7 +213,7 @@ public class TestListResolver
             {
                 for ( ResolvedTest filter : getExcludedPatterns() )
                 {
-                    if ( filter.shouldRun( testClassFile, methodName ) )
+                    if ( filter.matchAsExclusive( testClassFile, methodName ) )
                     {
                         shouldRun = false;
                         break;
@@ -226,14 +226,20 @@ public class TestListResolver
 
     public boolean isEmpty()
     {
-        return getIncludedPatterns().isEmpty() && getExcludedPatterns().isEmpty();
+        return equals( EMPTY );
     }
 
     public String getPluginParameterTest()
     {
         String aggregatedTest = aggregatedTest( "", getIncludedPatterns() );
+
+        if ( isNotBlank( aggregatedTest ) && !getExcludedPatterns().isEmpty() )
+        {
+            aggregatedTest += ", ";
+        }
+
         aggregatedTest += aggregatedTest( "!", getExcludedPatterns() );
-        return aggregatedTest.length() == 0 ? null : aggregatedTest;
+        return aggregatedTest.length() == 0 ? "" : aggregatedTest;
     }
 
     public Set<ResolvedTest> getIncludedPatterns()
@@ -246,11 +252,6 @@ public class TestListResolver
         return excludedPatterns;
     }
 
-    public Set<String> getTestSpecificClasses()
-    {
-        return specificClasses;
-    }
-
     @Override
     public boolean equals( Object o )
     {
@@ -317,19 +318,6 @@ public class TestListResolver
         }
     }
 
-    private static void populateSpecificClasses( Set<String> specificClasses, ResolvedTest test )
-    {
-        String pattern = test.getTestClassPattern();
-        if ( pattern != null )
-        {
-            if ( !test.isRegexTestClassPattern() && pattern.endsWith( JAVA_CLASS_FILE_EXTENSION ) )
-            {
-                pattern = pattern.substring( 0, pattern.length() - JAVA_CLASS_FILE_EXTENSION.length() );
-            }
-            specificClasses.add( pattern );
-        }
-    }
-
     private static String aggregatedTest( String testPrefix, Set<ResolvedTest> tests )
     {
         String aggregatedTest = "";
@@ -338,7 +326,7 @@ public class TestListResolver
             String readableTest = test.toString();
             if ( aggregatedTest.length() != 0 && readableTest != null )
             {
-                aggregatedTest += ",";
+                aggregatedTest += ", ";
             }
             aggregatedTest += testPrefix + readableTest;
         }
@@ -375,13 +363,13 @@ public class TestListResolver
 
     static boolean isRegexPrefixedPattern( String pattern )
     {
-        int indexOfRegex = pattern.indexOf( SelectorUtils.REGEX_HANDLER_PREFIX );
-        int prefixLength = SelectorUtils.REGEX_HANDLER_PREFIX.length();
+        int indexOfRegex = pattern.indexOf( REGEX_HANDLER_PREFIX );
+        int prefixLength = REGEX_HANDLER_PREFIX.length();
         if ( indexOfRegex != -1 )
         {
             if ( indexOfRegex != 0
-                || !pattern.endsWith( SelectorUtils.PATTERN_HANDLER_SUFFIX )
-                || pattern.indexOf( SelectorUtils.REGEX_HANDLER_PREFIX, prefixLength ) != -1 )
+                || !pattern.endsWith( PATTERN_HANDLER_SUFFIX )
+                || pattern.indexOf( REGEX_HANDLER_PREFIX, prefixLength ) != -1 )
             {
                 String msg = "Illegal test|includes|excludes regex '%s'. Expected %%regex[class#method] "
                     + "or !%%regex[class#method] " + "with optional class or #method.";
@@ -398,8 +386,8 @@ public class TestListResolver
     static String[] unwrapRegex( String regex )
     {
         regex = regex.trim();
-        int from = SelectorUtils.REGEX_HANDLER_PREFIX.length();
-        int to = regex.length() - SelectorUtils.PATTERN_HANDLER_SUFFIX.length();
+        int from = REGEX_HANDLER_PREFIX.length();
+        int to = regex.length() - PATTERN_HANDLER_SUFFIX.length();
         return unwrap( regex.substring( from, to ) );
     }
 
@@ -423,7 +411,7 @@ public class TestListResolver
                          IncludedExcludedPatterns patterns,
                          Collection<ResolvedTest> includedFilters, Collection<ResolvedTest> excludedFilters )
     {
-        for ( String method : StringUtils.split( methods, "+" ) )
+        for ( String method : split( methods, "+" ) )
         {
             method = method.trim();
             ResolvedTest test = new ResolvedTest( clazz, method, false );
@@ -481,4 +469,16 @@ public class TestListResolver
             updatedFilters( isExcluded, test, patterns, includedFilters, excludedFilters );
         }
     }
+
+    private static boolean haveMethodPatterns( Set<ResolvedTest> patterns )
+    {
+        for ( ResolvedTest pattern : patterns )
+        {
+            if ( pattern.hasTestMethodPattern() )
+            {
+                return true;
+            }
+        }
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestRequest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestRequest.java b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestRequest.java
index 3a489fc..a1c9315 100644
--- a/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestRequest.java
+++ b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestRequest.java
@@ -87,7 +87,7 @@ public class TestRequest
      */
     public int getRerunFailingTestsCount()
     {
-        return this.rerunFailingTestsCount;
+        return rerunFailingTestsCount;
     }
 
     private static List<File> createFiles( List suiteXmlFiles )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
index c2ec153..c43a3a6 100644
--- a/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/JUnit4SuiteTest.java
@@ -28,6 +28,7 @@ import org.apache.maven.surefire.booter.MasterProcessCommandTest;
 import org.apache.maven.surefire.booter.SurefireReflectorTest;
 import org.apache.maven.surefire.report.LegacyPojoStackTraceWriterTest;
 import org.apache.maven.surefire.suite.RunResultTest;
+import org.apache.maven.surefire.testset.FundamentalFilterTest;
 import org.apache.maven.surefire.testset.ResolvedTestTest;
 import org.apache.maven.surefire.testset.TestListResolverTest;
 import org.apache.maven.surefire.util.DefaultDirectoryScannerTest;
@@ -66,7 +67,8 @@ import org.junit.runners.Suite;
     ScanResultTest.class,
     TestsToRunTest.class,
     UrlUtilsTest.class,
-    SpecificTestClassFilterTest.class
+    SpecificTestClassFilterTest.class,
+    FundamentalFilterTest.class
 } )
 @RunWith( Suite.class )
 public class JUnit4SuiteTest

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-api/src/test/java/org/apache/maven/surefire/testset/FundamentalFilterTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/testset/FundamentalFilterTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/testset/FundamentalFilterTest.java
new file mode 100644
index 0000000..9118448
--- /dev/null
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/testset/FundamentalFilterTest.java
@@ -0,0 +1,581 @@
+package org.apache.maven.surefire.testset;
+/*
+ * 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.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+
+/**
+ * Inclusive test patters:<p>
+ *
+ * <table cellspacing=0 border=1>
+ * <tr>
+ * <td style=min-width:50px> test</td>
+ * <td style=min-width:50px></td>
+ * <td style=min-width:50px> pattern</td>
+ * <td style=min-width:50px></td>
+ * <td style=min-width:50px></td>
+ * <td style=min-width:50px></td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>class</td>
+ * <td style=min-width:50px>method</td>
+ * <td style=min-width:50px>class</td>
+ * <td style=min-width:50px>method</td>
+ * <td style=min-width:50px>shouldRunAsInclusive</td>
+ * <td style=min-width:50px></td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y (wildcard pattern)</td>
+ * <td style=min-width:50px>testIncludes1</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y (suppose suite and custome filter)</td>
+ * <td style=min-width:50px>testIncludes2</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y (suppose Suite)</td>
+ * <td style=min-width:50px>testIncludes3</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y (suppose Suite)</td>
+ * <td style=min-width:50px>testIncludes4</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y (wildcard pattern)</td>
+ * <td style=min-width:50px>testIncludes5</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>match methods</td>
+ * <td style=min-width:50px>testIncludes6</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y (due to Cucumber)</td>
+ * <td style=min-width:50px>testIncludes7</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y (due to Cucumber)</td>
+ * <td style=min-width:50px>testIncludes8</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y (wildcard pattern)</td>
+ * <td style=min-width:50px>testIncludes9</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y (suppose suite and custome filter)</td>
+ * <td style=min-width:50px>testIncludes10</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>match classes</td>
+ * <td style=min-width:50px>testIncludes11</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>match classes</td>
+ * <td style=min-width:50px>testIncludes12</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y (wildcard pattern)</td>
+ * <td style=min-width:50px>testIncludes13</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>match methods</td>
+ * <td style=min-width:50px>testIncludes14</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>match classes</td>
+ * <td style=min-width:50px>testIncludes15</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>match all</td>
+ * <td style=min-width:50px>testIncludes16</td>
+ * </tr>
+ * </table>
+ * <p>
+ * <p>
+ * Exclusive test patters:<p>
+ *
+ * <table cellspacing=0 border=1>
+ * <tr>
+ * <td style=min-width:50px> test</td>
+ * <td style=min-width:50px></td>
+ * <td style=min-width:50px> pattern</td>
+ * <td style=min-width:50px></td>
+ * <td style=min-width:50px></td>
+ * <td style=min-width:50px></td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>class</td>
+ * <td style=min-width:50px>method</td>
+ * <td style=min-width:50px>class</td>
+ * <td style=min-width:50px>method</td>
+ * <td style=min-width:50px>shouldRunAsExclusive</td>
+ * <td style=min-width:50px></td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n (wildcard pattern)</td>
+ * <td style=min-width:50px>testExcludes1</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n (suppose suite and custome filter)</td>
+ * <td style=min-width:50px>testExcludes2</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n (suppose Suite)</td>
+ * <td style=min-width:50px>testExcludes3</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n (suppose Suite)</td>
+ * <td style=min-width:50px>testExcludes4</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n (wildcard pattern)</td>
+ * <td style=min-width:50px>testExcludes5</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>match methods</td>
+ * <td style=min-width:50px>testExcludes6</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n (due to Cucumber)</td>
+ * <td style=min-width:50px>testExcludes7</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n (due to Cucumber)</td>
+ * <td style=min-width:50px>testExcludes8</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n (wildcard pattern)</td>
+ * <td style=min-width:50px>testExcludes9</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n (suppose suite and custome filter)</td>
+ * <td style=min-width:50px>testExcludes10</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>match classes</td>
+ * <td style=min-width:50px>testExcludes11</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n (cannot exclude in dir.scanner)</td>
+ * <td style=min-width:50px>testExcludes12</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>n (wildcard pattern)</td>
+ * <td style=min-width:50px>testExcludes13</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>match methods</td>
+ * <td style=min-width:50px>testExcludes14</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>n</td>
+ * <td style=min-width:50px>match classes</td>
+ * <td style=min-width:50px>testExcludes15</td>
+ * </tr>
+ * <tr>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>y</td>
+ * <td style=min-width:50px>match all</td>
+ * <td style=min-width:50px>testExcludes16</td>
+ * </tr>
+ * </table>
+ */
+public class FundamentalFilterTest
+{
+    @Test
+    public void testIncludes1()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, null, false );
+        assertThat( pattern.matchAsInclusive( null, null ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes2()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, "method", false );
+        assertThat( pattern.matchAsInclusive( null, null ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes3()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", null, false );
+        assertThat( pattern.matchAsInclusive( null, null ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes4()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", "method", false );
+        assertThat( pattern.matchAsInclusive( null, null ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes5()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, null, false );
+        assertThat( pattern.matchAsInclusive( null, "method" ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes6()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, "method", false );
+        assertThat( pattern.matchAsInclusive( null, "method" ), is( true ) );
+        assertThat( pattern.matchAsInclusive( null, "otherMethod" ), is( false ) );
+    }
+
+    /**
+     * Does not throw NPE due to Cucumber has test class NULL and test method NOT NULL.
+     */
+    @Test
+    public void testIncludes7()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", null, false );
+        assertThat( pattern.matchAsInclusive( null, "method" ), is( true ) );
+    }
+
+    /**
+     * Does not throw NPE due to Cucumber has test class NULL and test method NOT NULL.
+     */
+    @Test
+    public void testIncludes8()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", "method", false );
+        assertThat( pattern.matchAsInclusive( null, "method" ), is( true ) );
+        assertThat( pattern.matchAsInclusive( null, "otherMethod" ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes9()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, null, false );
+        assertThat( pattern.matchAsInclusive( "Test.class", null ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes10()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, "method", false );
+        assertThat( pattern.matchAsInclusive( "Test.class", null ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes11()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", null, false );
+        assertThat( pattern.matchAsInclusive( "Test.class", null ), is( true ) );
+        assertThat( pattern.matchAsInclusive( "Other.class", null ), is( false ) );
+    }
+
+    @Test
+    public void testIncludes12()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", "method", false );
+        assertThat( pattern.matchAsInclusive( "Test.class", null ), is( true ) );
+        assertThat( pattern.matchAsInclusive( "Other.class", null ), is( false ) );
+    }
+
+    @Test
+    public void testIncludes13()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, null, false );
+        assertThat( pattern.matchAsInclusive( "Test.class", "method" ), is( true ) );
+    }
+
+    @Test
+    public void testIncludes14()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, "method", false );
+        assertThat( pattern.matchAsInclusive( "Test.class", "method" ), is( true ) );
+        assertThat( pattern.matchAsInclusive( "Test.class", "otherMethod" ), is( false ) );
+    }
+
+    @Test
+    public void testIncludes15()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", null, false );
+        assertThat( pattern.matchAsInclusive( "Test.class", "method" ), is( true ) );
+        assertThat( pattern.matchAsInclusive( "Other.class", "method" ), is( false ) );
+    }
+
+    @Test
+    public void testIncludes16()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", "method", false );
+        assertThat( pattern.matchAsInclusive( "Test.class", "method" ), is( true ) );
+        assertThat( pattern.matchAsInclusive( "Test.class", "otherMethod" ), is( false ) );
+        assertThat( pattern.matchAsInclusive( "Other.class", "method" ), is( false ) );
+        assertThat( pattern.matchAsInclusive( "Other.class", "otherMethod" ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes1()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, null, false );
+        assertThat( pattern.matchAsExclusive( null, null ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes2()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, "method", false );
+        assertThat( pattern.matchAsExclusive( null, null ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes3()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", null, false );
+        assertThat( pattern.matchAsExclusive( null, null ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes4()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", "method", false );
+        assertThat( pattern.matchAsExclusive( null, null ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes5()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, null, false );
+        assertThat( pattern.matchAsExclusive( null, "method" ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes6()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, "method", false );
+        assertThat( pattern.matchAsExclusive( null, "method" ), is( true ) );
+        assertThat( pattern.matchAsExclusive( null, "otherMethod" ), is( false ) );
+    }
+
+    /**
+     * Does not throw NPE due to Cucumber has test class NULL and test method NOT NULL.
+     */
+    @Test
+    public void testExcludes7()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", null, false );
+        assertThat( pattern.matchAsExclusive( null, "method" ), is( false ) );
+    }
+
+    /**
+     * Does not throw NPE due to Cucumber has test class NULL and test method NOT NULL.
+     */
+    @Test
+    public void testExcludes8()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", "method", false );
+        assertThat( pattern.matchAsExclusive( null, "method" ), is( false ) );
+        assertThat( pattern.matchAsExclusive( null, "otherMethod" ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes9()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, null, false );
+        assertThat( pattern.matchAsExclusive( "Test.class", null ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes10()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, "method", false );
+        assertThat( pattern.matchAsExclusive( "Test.class", null ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes11()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", null, false );
+        assertThat( pattern.matchAsExclusive( "Test.class", null ), is( true ) );
+        assertThat( pattern.matchAsExclusive( "Other.class", null ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes12()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", "method", false );
+        assertThat( pattern.matchAsExclusive( "Test.class", null ), is( false ) );
+        assertThat( pattern.matchAsExclusive( "Other.class", null ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes13()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, null, false );
+        assertThat( pattern.matchAsExclusive( "Test.class", "method" ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes14()
+    {
+        ResolvedTest pattern = new ResolvedTest( (String) null, "method", false );
+        assertThat( pattern.matchAsExclusive( "Test.class", "method" ), is( true ) );
+        assertThat( pattern.matchAsExclusive( "Test.class", "otherMethod" ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes15()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", null, false );
+        assertThat( pattern.matchAsExclusive( "Test.class", "method" ), is( true ) );
+        assertThat( pattern.matchAsExclusive( "Other.class", "method" ), is( false ) );
+    }
+
+    @Test
+    public void testExcludes16()
+    {
+        ResolvedTest pattern = new ResolvedTest( "Test", "method", false );
+        assertThat( pattern.matchAsExclusive( "Test.class", "method" ), is( true ) );
+        assertThat( pattern.matchAsExclusive( "Test.class", "otherMethod" ), is( false ) );
+        assertThat( pattern.matchAsExclusive( "Other.class", "method" ), is( false ) );
+        assertThat( pattern.matchAsExclusive( "Other.class", "otherMethod" ), is( false ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java
----------------------------------------------------------------------
diff --git a/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java b/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java
index e34e080..8fb1729 100644
--- a/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java
+++ b/surefire-api/src/test/java/org/apache/maven/surefire/testset/TestListResolverTest.java
@@ -21,14 +21,30 @@ package org.apache.maven.surefire.testset;
 import junit.framework.TestCase;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.util.Collections.addAll;
+import static org.apache.maven.surefire.testset.TestListResolver.newTestListResolver;
+import static org.apache.maven.surefire.testset.ResolvedTest.Type.CLASS;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptySet;
+import static java.util.Collections.singleton;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
 
 public class TestListResolverTest
     extends TestCase
 {
+    private static final String DEFAULT_SUREFIRE_INCLUDED_TEST_PATTERNS =
+        "**/Test*.java, **/*Test.java, **/*TestCase.java";
+
+    private static final String DEFAULT_SUREFIRE_EXCLUDED_TEST_PATTERNS = "**/*$*";
+
     public void testRegexSanity1()
     {
         try
@@ -128,8 +144,8 @@ public class TestListResolverTest
         assertTrue( test.hasTestMethodPattern() );
         assertEquals( "**/MyTest", test.getTestClassPattern() );
         assertEquals( "myTest", test.getTestMethodPattern() );
-        assertTrue( test.shouldRun( "MyTest", "myTest" ) );
-        assertFalse( test.shouldRun( "MyTest", "otherTest" ) );
+        assertTrue( test.matchAsInclusive( "MyTest", "myTest" ) );
+        assertFalse( test.matchAsInclusive( "MyTest", "otherTest" ) );
     }
 
     public void testNonRegexClassAndMethods()
@@ -153,7 +169,7 @@ public class TestListResolverTest
         assertTrue( first.hasTestMethodPattern() );
         assertEquals( "**/MyTest.class", first.getTestClassPattern() );
         assertEquals( "first*", first.getTestMethodPattern() );
-        assertTrue( first.shouldRun( "your/pkg/MyTest.class", "firstTest" ) );
+        assertTrue( first.matchAsInclusive( "your/pkg/MyTest.class", "firstTest" ) );
         ResolvedTest second = tests.next();
         assertFalse( second.isEmpty() );
         assertFalse( second.isRegexTestClassPattern() );
@@ -162,8 +178,8 @@ public class TestListResolverTest
         assertTrue( second.hasTestMethodPattern() );
         assertEquals( "**/MyTest.class", second.getTestClassPattern() );
         assertEquals( "second*", second.getTestMethodPattern() );
-        assertTrue( second.shouldRun( "your/pkg/MyTest.class", "secondTest" ) );
-        assertFalse( second.shouldRun( "your/pkg/MyTest.class", "thirdTest" ) );
+        assertTrue( second.matchAsInclusive( "your/pkg/MyTest.class", "secondTest" ) );
+        assertFalse( second.matchAsInclusive( "your/pkg/MyTest.class", "thirdTest" ) );
     }
 
     public void testNegativeNonRegexClassAndMethod()
@@ -186,9 +202,9 @@ public class TestListResolverTest
         assertEquals( "**/MyTest", test.getTestClassPattern() );
         assertEquals( "myTest", test.getTestMethodPattern() );
         // ResolvedTest should not care about isExcluded. This attribute is handled by TestListResolver.
-        assertTrue( test.shouldRun( "MyTest", "myTest" ) );
-        assertFalse( test.shouldRun( "MyTest", "otherTest" ) );
-        assertFalse( test.shouldRun( "pkg/OtherTest.class", "myTest" ) );
+        assertTrue( test.matchAsInclusive( "MyTest", "myTest" ) );
+        assertFalse( test.matchAsInclusive( "MyTest", "otherTest" ) );
+        assertFalse( test.matchAsInclusive( "pkg/OtherTest.class", "myTest" ) );
     }
 
     public void testResolveTestRequest()
@@ -205,9 +221,14 @@ public class TestListResolverTest
         assertEquals( 1, excludedFilters.size() );
         ResolvedTest test = excludedFilters.iterator().next();
         // ResolvedTest should not care about isExcluded. This attribute is handled by TestListResolver.
-        assertTrue( test.shouldRun( "pkg/MyTest.class", "myTest" ) );
-        assertFalse( test.shouldRun( "pkg/MyTest.class", "otherTest" ) );
-        assertFalse( test.shouldRun( "pkg/OtherTest.class", "myTest" ) );
+        assertTrue( test.matchAsInclusive( "pkg/MyTest.class", "myTest" ) );
+        assertFalse( test.matchAsInclusive( "pkg/MyTest.class", "otherTest" ) );
+        assertFalse( test.matchAsInclusive( "pkg/OtherTest.class", "myTest" ) );
+    }
+
+    public void testShouldRunTestWithoutMethod()
+    {
+        new TestListResolver("**/*Test.class, !%regex[.*.MyTest.class#myTest]").shouldRun( "pkg/MyTest.class", null );
     }
 
     public void testShouldNotRunExcludedMethods()
@@ -216,15 +237,15 @@ public class TestListResolverTest
         assertTrue( resolver.shouldRun( "pkg/MyTest.class", null ) );
     }
 
-    public void testShouldNotRunIncludedMethods()
+    public void testShouldRunSuiteWithIncludedMethods()
     {
         TestListResolver resolver = new TestListResolver( "#*Fail*, %regex[#.*One], #testSuccessThree" );
-        assertFalse( resolver.shouldRun( "pkg/MyTest.class", null ) );
+        assertTrue( resolver.shouldRun( "pkg/MyTest.class", null ) );
     }
 
     public void testShouldRunAny()
     {
-        TestListResolver resolver = new TestListResolver( "" );
+        TestListResolver resolver = TestListResolver.getEmpty();
         assertTrue( resolver.shouldRun( "pkg/MyTest.class", null ) );
 
         resolver = new TestListResolver( Collections.<String>emptySet() );
@@ -234,24 +255,25 @@ public class TestListResolverTest
     public void testClassFilter()
     {
         TestListResolver resolver = new TestListResolver( "#test" );
-        assertTrue( resolver.createClassFilters().shouldRun( "pkg/MyTest.class", null ) );
+        assertTrue( resolver.shouldRun( "pkg/MyTest.class", null ) );
 
         resolver = new TestListResolver( "!#test" );
-        assertTrue( resolver.createClassFilters().shouldRun( "pkg/MyTest.class", null ) );
+        assertTrue( resolver.shouldRun( "pkg/MyTest.class", null ) );
 
         resolver = new TestListResolver( "SomeOtherClass" );
-        assertFalse( resolver.createClassFilters().shouldRun( "pkg/MyTest.class", null ) );
+        assertFalse( resolver.shouldRun( "pkg/MyTest.class", null ) );
     }
 
     public void testBrokenPatternThrowsException()
     {
-        Collection<String> included = Collections.emptySet();
-        Collection<String> excluded = Arrays.asList( "BasicTest, !**/TestTwo, **/TestThree.java" );
+        Collection<String> included = emptySet();
+        Collection<String> excluded = asList( "BasicTest, !**/TestTwo, **/TestThree.java" );
         try
         {
             new TestListResolver( included, excluded );
             fail( "Expected: IllegalArgumentException" );
-        } catch ( IllegalArgumentException e )
+        }
+        catch ( IllegalArgumentException e )
         {
             // JUnit 3.x style
             assertEquals( "Exclamation mark not expected in 'exclusion': BasicTest, !**/TestTwo, **/TestThree.java",
@@ -261,8 +283,8 @@ public class TestListResolverTest
 
     public void testMultipleExcludedClassesOnly()
     {
-        Collection<String> included = Collections.emptySet();
-        Collection<String> excluded = Arrays.asList( "BasicTest, **/TestTwo, **/TestThree.java" );
+        Collection<String> included = emptySet();
+        Collection<String> excluded = asList( "BasicTest, **/TestTwo, **/TestThree.java" );
         TestListResolver resolver = new TestListResolver( included, excluded );
         assertFalse( resolver.shouldRun( "jiras/surefire745/BasicTest.class", null ) );
         assertFalse( resolver.shouldRun( "jiras/surefire745/TestTwo.class", null ) );
@@ -272,8 +294,8 @@ public class TestListResolverTest
 
     public void testMultipleExcludedClasses()
     {
-        Collection<String> included = Arrays.asList( "**/Test*.java, **/*Test.java, **/*TestCase.java" );
-        Collection<String> excluded = Arrays.asList( "BasicTest, **/TestTwo, **/TestThree.java" );
+        Collection<String> included = singleton( DEFAULT_SUREFIRE_INCLUDED_TEST_PATTERNS );
+        Collection<String> excluded = asList( "BasicTest, **/TestTwo, **/TestThree.java" );
         TestListResolver resolver = new TestListResolver( included, excluded );
         assertFalse( resolver.shouldRun( "jiras/surefire745/BasicTest.class", null ) );
         assertFalse( resolver.shouldRun( "jiras/surefire745/TestTwo.class", null ) );
@@ -281,22 +303,112 @@ public class TestListResolverTest
         assertTrue( resolver.shouldRun( "jiras/surefire745/TestFour.class", null ) );
     }
 
-    public void testMultipleExcludedClassesWithNoSpecificTests()
+    public void testAndFilters()
     {
-        Collection<String> included = Arrays.asList( "**/Test*.java, **/*Test.java, **/*TestCase.java" );
-        Collection<String> excluded = Arrays.asList( "BasicTest, **/TestTwo, **/TestThree.java" );
+        TestListResolver firstFilter = new TestListResolver( "BasicTest, **/TestTwo, **/TestThree.java" );
+        TestListResolver secondFilter = new TestListResolver( "*icTest, Test???*" );
+        TestFilter<String, String> filter = firstFilter.and( secondFilter );
 
-        TestListResolver includedAndExcludedTests = new TestListResolver( included, excluded );
-        TestListResolver includedExcludedClasses = includedAndExcludedTests.createClassFilters();
+        assertTrue( filter.shouldRun( "jiras/surefire745/BasicTest.class", null ) );
+        assertTrue( filter.shouldRun( "jiras/surefire745/TestTwo.class", null ) );
+        assertTrue( filter.shouldRun( "jiras/surefire745/TestThree.class", null ) );
+        assertFalse( filter.shouldRun( "jiras/surefire745/TestFour.class", null ) );
+    }
 
-        TestListResolver specificTests = new TestListResolver( "" );
-        TestListResolver specificClasses = specificTests.createClassFilters();
+    public void testTestListResolverWithoutMethods()
+    {
+        ResolvedTest inc1 = new ResolvedTest( "A?Test.java", null, false );
+        ResolvedTest inc2 = new ResolvedTest( "**/?Test", null, false );
+        ResolvedTest exc1 = new ResolvedTest( "AATest", null, false );
+        ResolvedTest exc2 = new ResolvedTest( "**/BTest.java", null, false );
+        TestListResolver resolver = newTestListResolver( $( inc1, inc2 ), $( exc1, exc2 ) );
+        assertThat( resolver.getPluginParameterTest(), is( "A?Test.java, **/?Test, !AATest, !**/BTest.java" ) );
+        assertFalse( resolver.isEmpty() );
+        assertFalse( resolver.hasIncludedMethodPatterns() );
+        assertFalse( resolver.hasExcludedMethodPatterns() );
+        assertFalse( resolver.hasMethodPatterns() );
+        assertTrue( resolver.shouldRun( "ATest.class", null ) );
+        assertFalse( resolver.shouldRun( "AATest.class", null ) );
+        assertTrue( resolver.shouldRun( "ABTest.class", null ) );
+        assertFalse( resolver.shouldRun( "BTest.class", null ) );
+        assertTrue( resolver.shouldRun( "CTest.class", null ) );
+        assertFalse( resolver.hasMethodPatterns() );
+    }
 
-        TestFilter<String, String> filter = includedExcludedClasses.and( specificClasses );
+    public void testTestListResolverWithMethods()
+    {
+        ResolvedTest inc1 = new ResolvedTest( "A?Test.java", null, false );
+        ResolvedTest inc2 = new ResolvedTest( "*?Test", null, false );
+        ResolvedTest exc1 = new ResolvedTest( "AATest", null, false );
+        ResolvedTest exc2 = new ResolvedTest( "*BTest.java", "failedTest", false );
+        TestListResolver resolver = newTestListResolver( $( inc1, inc2 ), $( exc1, exc2 ) );
+        assertThat( resolver.getPluginParameterTest(), is( "A?Test.java, *?Test, !AATest, !*BTest.java#failedTest" ) );
+        assertFalse( resolver.isEmpty() );
+        assertFalse( resolver.hasIncludedMethodPatterns() );
+        assertTrue( resolver.hasExcludedMethodPatterns() );
+        assertTrue( resolver.hasMethodPatterns() );
+        assertTrue( resolver.shouldRun( "ATest.class", null ) );
+        assertFalse( resolver.shouldRun( "AATest.class", null ) );
+        assertTrue( resolver.shouldRun( "ABTest.class", null ) );
+        assertTrue( resolver.shouldRun( "BTest.class", null ) );
+        assertFalse( resolver.shouldRun( "BTest.class", "failedTest" ) );
+        assertTrue( resolver.shouldRun( "CTest.class", null ) );
+        assertFalse( TestListResolver.optionallyWildcardFilter( resolver ).isEmpty() );
+    }
 
-        assertFalse( filter.shouldRun( "jiras/surefire745/BasicTest.class", null ) );
-        assertFalse( filter.shouldRun( "jiras/surefire745/TestTwo.class", null ) );
-        assertFalse( filter.shouldRun( "jiras/surefire745/TestThree.class", null ) );
-        assertTrue( filter.shouldRun( "jiras/surefire745/TestFour.class", null ) );
+    private static Set<ResolvedTest> $( ResolvedTest... patterns )
+    {
+        Set<ResolvedTest> set = new LinkedHashSet<ResolvedTest>();
+        addAll( set, patterns );
+        return set;
+    }
+
+    public void testDefaultPatternsMatching()
+    {
+        Set<ResolvedTest> inclusions = resolveClass( DEFAULT_SUREFIRE_INCLUDED_TEST_PATTERNS );
+        Set<ResolvedTest> exclusions = resolveClass( DEFAULT_SUREFIRE_EXCLUDED_TEST_PATTERNS );
+        TestListResolver tlr = newTestListResolver( inclusions, exclusions );
+        boolean shouldRun = tlr.shouldRun( "org/apache/maven/surefire/SomeTest.class", null );
+        assertTrue( shouldRun );
+    }
+
+    public void testDefaultPatternsNotMatching()
+    {
+        Set<ResolvedTest> inclusions = resolveClass( DEFAULT_SUREFIRE_INCLUDED_TEST_PATTERNS );
+        Set<ResolvedTest> exclusions = resolveClass( DEFAULT_SUREFIRE_EXCLUDED_TEST_PATTERNS );
+        TestListResolver tlr = newTestListResolver( inclusions, exclusions );
+        boolean shouldRun = tlr.shouldRun( "org/apache/maven/surefire/SomeTestNotRunning.class", null );
+        assertFalse( shouldRun );
+    }
+
+    public void testInclusiveWithDefaultExclusivePattern()
+    {
+        Set<ResolvedTest> defaultExclusions = resolveClass( DEFAULT_SUREFIRE_EXCLUDED_TEST_PATTERNS );
+        boolean runnable = newTestListResolver( resolveClass( "A*Test" ), defaultExclusions )
+            .shouldRun( "org/apache/maven/surefire/ARunnableTest.class", null );
+        assertTrue( runnable );
+    }
+
+    public void testWildcard()
+    {
+        TestListResolver tlr = TestListResolver.optionallyWildcardFilter( new TestListResolver( (String) null ) );
+        assertThat( tlr, is( new TestListResolver( "**/*.class" ) ) );
+        assertThat( tlr.isWildcard(), is( true ) );
+        assertThat( tlr.isEmpty(), is( false ) );
+
+        tlr = TestListResolver.optionallyWildcardFilter( new TestListResolver( "**/**/MethodLessPattern.class" ) );
+        assertThat( tlr, is( new TestListResolver( "**/*.class" ) ) );
+        assertThat( tlr.isWildcard(), is( true ) );
+        assertThat( tlr.isEmpty(), is( false ) );
+    }
+
+    private static Set<ResolvedTest> resolveClass( String patterns )
+    {
+        Set<ResolvedTest> resolved = new HashSet<ResolvedTest>();
+        for ( String pattern : patterns.split( "," ) )
+        {
+            resolved.add( new ResolvedTest( CLASS, pattern, false ) );
+        }
+        return resolved;
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
----------------------------------------------------------------------
diff --git a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
index 2540a7f..02fde8f 100644
--- a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
+++ b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/BooterDeserializer.java
@@ -50,8 +50,6 @@ import static org.apache.maven.surefire.cli.CommandLineOption.*;
  */
 public class BooterDeserializer
 {
-
-
     private final PropertiesWrapper properties;
 
     public BooterDeserializer( InputStream inputStream )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java
index 9c7b4b4..a4b5367 100644
--- a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/AbstractTestMultipleMethodPatterns.java
@@ -36,6 +36,10 @@ import static org.junit.Assume.assumeThat;
 public abstract class AbstractTestMultipleMethodPatterns
     extends SurefireJUnit4IntegrationTestCase
 {
+    private static final String CSV_DELIMITER_SHORT = ",";
+    private static final String CSV_DELIMITER_LONG = ", ";
+    private static final String NOT_DELIMITER = "!";
+
     protected abstract Settings getSettings();
 
     protected abstract SurefireLauncher unpack();
@@ -65,18 +69,18 @@ public abstract class AbstractTestMultipleMethodPatterns
     {
         String included = "";
         String excluded = "";
-        for ( String pattern : patterns.split( "," ) )
+        for ( String pattern : patterns.split( CSV_DELIMITER_SHORT ) )
         {
             pattern = pattern.trim();
-            if ( pattern.startsWith( "!" ) )
+            if ( pattern.startsWith( NOT_DELIMITER ) )
             {
-                excluded += pattern.substring( 1 );
-                excluded += ", ";
+                excluded += pattern.substring( NOT_DELIMITER.length() ).trim();
+                excluded += CSV_DELIMITER_LONG;
             }
             else
             {
                 included += pattern;
-                included += ", ";
+                included += CSV_DELIMITER_LONG;
             }
         }
         return new String[]{ trimEndComma( included ), trimEndComma( excluded ) };
@@ -85,7 +89,8 @@ public abstract class AbstractTestMultipleMethodPatterns
     private static String trimEndComma( String pattern )
     {
         pattern = pattern.trim();
-        return pattern.endsWith( "," ) ? pattern.substring( 0, pattern.length() - 1 ) : pattern;
+        return pattern.endsWith( CSV_DELIMITER_LONG )
+            ? pattern.substring( 0, pattern.length() - CSV_DELIMITER_LONG.length() ) : pattern;
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/021b263a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1185DoNotSpawnTestsIT.java
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1185DoNotSpawnTestsIT.java b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1185DoNotSpawnTestsIT.java
new file mode 100644
index 0000000..16e27cf
--- /dev/null
+++ b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/jiras/Surefire1185DoNotSpawnTestsIT.java
@@ -0,0 +1,62 @@
+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.it.VerificationException;
+import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.apache.maven.surefire.its.fixture.SurefireLauncher;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Surefire 2.19 spawns unnecessary tests in surefire-junit4 provider.
+ * https://issues.apache.org/jira/browse/SUREFIRE-1185
+ * Example, UnlistedTest is the problem here because it runs with filtered out methods:
+ *
+ * Running pkg.UnlistedTest
+ * Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec - in pkg.UnlistedTest
+ * Running pkg.RunningTest
+ * Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec - in pkg.RunningTest
+ *
+ * Results :
+ *
+ * Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+ */
+public class Surefire1185DoNotSpawnTestsIT
+    extends SurefireJUnit4IntegrationTestCase
+{
+    @Test
+    public void doNotSpawnUnwantedTests()
+        throws VerificationException
+    {
+        unpack().setTestToRun( "RunningTest#test" )
+            .executeTest()
+            .assertTestSuiteResults( 1 )
+            .assertThatLogLine( containsString( "in pkg.RunningTest" ), is( 1 ) )
+            .assertThatLogLine( containsString( "in pkg.UnlistedTest" ), is( 0 ) );
+    }
+
+    private SurefireLauncher unpack()
+    {
+        return unpack( "surefire-1185" );
+    }
+}