improved filters

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

Branch: refs/heads/master
Commit: 889caca8e5b6e77cccbeed0a3b2762048789188e
Parents: 870d229
Author: Tibor17 <tibo...@lycos.com>
Authored: Tue Jan 27 00:12:20 2015 +0100
Committer: Tibor17 <tibo...@lycos.com>
Committed: Tue Jan 27 00:12:20 2015 +0100

----------------------------------------------------------------------
 .../plugin/failsafe/IntegrationTestMojo.java    |  34 +-
 .../plugin/surefire/AbstractSurefireMojo.java   | 154 +++--
 .../surefire/SurefireExecutionParameters.java   |   5 +-
 .../surefire/booterclient/BooterSerializer.java |   5 +-
 .../plugin/surefire/util/DependencyScanner.java |   2 +-
 ...erDeserializerProviderConfigurationTest.java |  35 +-
 ...terDeserializerStartupConfigurationTest.java |   7 +-
 .../maven/plugin/surefire/SurefirePlugin.java   |  59 +-
 .../surefire/booter/SurefireReflector.java      |  31 +-
 .../maven/surefire/testset/ResolvedTest.java    | 261 ++++++++
 .../surefire/testset/TestListResolver.java      | 261 ++++++++
 .../maven/surefire/testset/TestRequest.java     |  41 +-
 .../surefire/booter/BooterDeserializer.java     |   4 +-
 .../maven/surefire/booter/ForkedBooter.java     |   6 +-
 .../maven/surefire/booter/ProviderFactory.java  |  24 +-
 .../surefire/booter/SurefireReflectorTest.java  |   3 +-
 surefire-integration-tests/pom.xml              |   4 +-
 .../its/TestMultipleMethodPatternsIT.java       | 129 +++-
 .../junit48-multiple-method-patterns/pom.xml    |  24 +-
 .../test/java/jiras/surefire745/BasicTest.java  |  53 ++
 .../test/java/jiras/surefire745/TestFive.java   |  49 ++
 .../test/java/jiras/surefire745/TestFour.java   |  49 ++
 .../test/java/jiras/surefire745/TestThree.java  |  51 ++
 .../test/java/jiras/surefire745/TestTwo.java    |  42 ++
 .../src/test/java/junit4/BasicTest.java         |  46 --
 .../src/test/java/junit4/TestFive.java          |  43 --
 .../src/test/java/junit4/TestFour.java          |  43 --
 .../src/test/java/junit4/TestThree.java         |  45 --
 .../src/test/java/junit4/TestTwo.java           |  41 --
 .../common/junit4/JUnit4RunListener.java        |   2 +-
 .../surefire/common/junit48/AndFilter.java      |  62 ++
 .../common/junit48/CombinedCategoryFilter.java  |  99 +++
 .../common/junit48/FailingMethodFilter.java     |  71 ++
 .../surefire/common/junit48/FilterFactory.java  | 417 +-----------
 .../junit48/GroupMatcherCategoryFilter.java     | 160 +++++
 .../surefire/common/junit48/InvertedFilter.java |  46 ++
 .../surefire/common/junit48/MethodFilter.java   |  89 +++
 .../maven/surefire/common/junit48/OrFilter.java |  62 ++
 .../surefire/common/junit48/RequestedTest.java  |  68 ++
 .../common/junit48/FilterFactoryTest.java       | 669 +++++++++++++++++--
 .../apache/maven/surefire/junit4/Filter.java    |  27 +
 .../maven/surefire/junit4/JUnit4Provider.java   | 102 +--
 .../surefire/junit4/JUnit4ProviderTest.java     |   2 +-
 .../surefire/junitcore/JUnitCoreProvider.java   |  33 +-
 .../utils/GroupMatcherMethodSelector.java       |   8 +-
 .../surefire/testng/utils/MethodSelector.java   |  32 +-
 .../testng/TestNGDirectoryTestSuite.java        |  15 +-
 .../maven/surefire/testng/TestNGExecutor.java   |  95 +--
 .../maven/surefire/testng/TestNGProvider.java   |   4 +-
 49 files changed, 2517 insertions(+), 1097 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
----------------------------------------------------------------------
diff --git 
a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
 
b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
index b507e47..0900e81 100644
--- 
a/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
+++ 
b/maven-failsafe-plugin/src/main/java/org/apache/maven/plugin/failsafe/IntegrationTestMojo.java
@@ -36,6 +36,7 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.shared.utils.ReaderFactory;
 import org.apache.maven.shared.utils.StringUtils;
 import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.testset.TestListResolver;
 
 import static org.apache.maven.shared.utils.io.IOUtil.close;
 
@@ -260,6 +261,8 @@ public class IntegrationTestMojo
     @Parameter( property = "failsafe.runOrder", defaultValue = "filesystem" )
     protected String runOrder;
 
+    private TestListResolver testListResolver;
+
     protected int getRerunFailingTestsCount()
     {
         return rerunFailingTestsCount;
@@ -417,18 +420,13 @@ public class IntegrationTestMojo
         this.reportsDirectory = reportsDirectory;
     }
 
-    public String getTest()
+    public TestListResolver getTest()
     {
-        if ( StringUtils.isBlank( test ) )
-        {
-            return null;
-        }
-        int index = test.indexOf( '#' );
-        if ( index >= 0 )
+        if ( testListResolver == null && test != null )
         {
-            return test.substring( 0, index );
+            testListResolver = new TestListResolver( test );
         }
-        return test;
+        return testListResolver;
     }
 
     public void setTest( String test )
@@ -436,24 +434,6 @@ public class IntegrationTestMojo
         this.test = test;
     }
 
-    /**
-     * @since 2.7.3
-     */
-    public String getTestMethod()
-    {
-        if ( StringUtils.isBlank( test ) )
-        {
-            return null;
-        }
-        int index = this.test.indexOf( '#' );
-        if ( index >= 0 )
-        {
-            return this.test.substring( index + 1, this.test.length() );
-        }
-        return null;
-    }
-
-
     public File getSummaryFile()
     {
         return summaryFile;

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/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 bdfb553..dfca11a 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
@@ -686,6 +686,8 @@ public abstract class AbstractSurefireMojo
      */
     public static final String FORK_NUMBER_PLACEHOLDER = 
"${surefire.forkNumber}";
 
+    private static final String JAVA_EXTENSION = ".java";
+
     protected abstract String getPluginName();
 
     protected abstract int getRerunFailingTestsCount();
@@ -700,10 +702,10 @@ public abstract class AbstractSurefireMojo
 
         if ( verifyParameters() && !hasExecutedBefore() )
         {
-            DefaultScanResult scan = scanForTestClasses();
+            DefaultScanResult scan = scanForTestClasses();//!
             if ( !isValidSuiteXmlFileConfig() && scan.isEmpty() )
             {
-                if ( getEffectiveFailIfNoTests() )
+                if ( getEffectiveFailIfNoTests() )//! isSpecificTestSpecified
                 {
                     throw new MojoFailureException(
                         "No tests were executed!  (Set -DfailIfNoTests=false 
to ignore this error.)" );
@@ -712,7 +714,7 @@ public abstract class AbstractSurefireMojo
                 return;
             }
             logReportsDirectory();
-            executeAfterPreconditionsChecked( scan );
+            executeAfterPreconditionsChecked( scan );//! getTest providers
         }
     }
 
@@ -723,17 +725,18 @@ public abstract class AbstractSurefireMojo
         toolchain = getToolchain();
     }
 
-    private DefaultScanResult scanForTestClasses()
+    private DefaultScanResult scanForTestClasses()//! execute()
     {
-        DefaultScanResult scan = scanDirectories();
-        DefaultScanResult scanDeps = scanDependencies();
+        DefaultScanResult scan = scanDirectories();//! 1
+        DefaultScanResult scanDeps = scanDependencies();//!
         return scan.append( scanDeps );
     }
 
-    private DefaultScanResult scanDirectories()
+    private DefaultScanResult scanDirectories()//!
     {
-        return new DirectoryScanner( getTestClassesDirectory(), 
getIncludeList(), getExcludeList(),
-                                     getSpecificTests() ).scan();
+        DirectoryScanner scanner =
+            new DirectoryScanner( getTestClassesDirectory(), getIncludeList(), 
getExcludeList(), getSpecificTests() );//!
+        return scanner.scan();
     }
 
     private DefaultScanResult scanDependencies()
@@ -749,7 +752,7 @@ public abstract class AbstractSurefireMojo
                 // noinspection unchecked
                 return new DependencyScanner( DependencyScanner.filter( 
project.getTestArtifacts(),
                                                                         
Arrays.asList( getDependenciesToScan() ) ),
-                                              getIncludeList(), 
getExcludeList(), getSpecificTests() ).scan();
+                                              getIncludeList(), 
getExcludeList(), getSpecificTests() ).scan();//!
             }
             catch ( Exception e )
             {
@@ -801,7 +804,7 @@ public abstract class AbstractSurefireMojo
 
     protected abstract boolean isSkipExecution();
 
-    protected void executeAfterPreconditionsChecked( DefaultScanResult 
scanResult )
+    private void executeAfterPreconditionsChecked( DefaultScanResult 
scanResult )
         throws MojoExecutionException, MojoFailureException
     {
 
@@ -814,7 +817,7 @@ public abstract class AbstractSurefireMojo
         {
             try
             {
-                current = current.aggregate( executeProvider( provider, 
scanResult ) );
+                current = current.aggregate( executeProvider( provider, 
scanResult ) );//! getTest
             }
             catch ( SurefireBooterForkException e )
             {
@@ -963,7 +966,7 @@ public abstract class AbstractSurefireMojo
             createCopyAndReplaceForkNumPlaceholder( effectiveProperties, 1 
).copyToSystemProperties();
 
             InPluginVMSurefireStarter surefireStarter =
-                createInprocessStarter( provider, classLoaderConfiguration, 
runOrderParameters );
+                createInprocessStarter( provider, classLoaderConfiguration, 
runOrderParameters );//! getTest
             return surefireStarter.runSuitesInProcess( scanResult );
         }
         else
@@ -978,7 +981,7 @@ public abstract class AbstractSurefireMojo
             try
             {
                 ForkStarter forkStarter =
-                    createForkStarter( provider, forkConfiguration, 
classLoaderConfiguration, runOrderParameters,
+                    createForkStarter( provider, forkConfiguration, 
classLoaderConfiguration, runOrderParameters,//! getTest
                                        getLog() );
                 return forkStarter.run( effectiveProperties, scanResult );
             }
@@ -1021,7 +1024,7 @@ public abstract class AbstractSurefireMojo
             }
             catch ( IOException ioe )
             {
-                getLog().warn( "Could not delete temp direcotry " + 
tempDirectory + " because " + ioe.getMessage() );
+                getLog().warn( "Could not delete temp directory " + 
tempDirectory + " because " + ioe.getMessage() );
             }
         }
     }
@@ -1368,7 +1371,7 @@ public abstract class AbstractSurefireMojo
 
     private boolean getEffectiveFailIfNoTests()
     {
-        if ( isSpecificTestSpecified() )
+        if ( isSpecificTestSpecified() )//!
         {
             if ( getFailIfNoSpecifiedTests() != null )
             {
@@ -1395,21 +1398,19 @@ public abstract class AbstractSurefireMojo
         ReporterConfiguration reporterConfiguration =
             new ReporterConfiguration( getReportsDirectory(), 
isTrimStackTrace() );
 
-        Artifact testNgArtifact;
-        testNgArtifact = getTestNgArtifact();
-
+        Artifact testNgArtifact = getTestNgArtifact();
         DirectoryScannerParameters directoryScannerParameters = null;
         final boolean isTestNg = testNgArtifact != null;
         TestArtifactInfo testNg =
             isTestNg ? new TestArtifactInfo( testNgArtifact.getVersion(), 
testNgArtifact.getClassifier() ) : null;
         List<File> testXml = getSuiteXmlFiles() != null ? Arrays.asList( 
getSuiteXmlFiles() ) : null;
         TestRequest testSuiteDefinition =
-            new TestRequest( testXml, getTestSourceDirectory(), getTest(), 
getTestMethod(),
-                             getRerunFailingTestsCount() );
+            new TestRequest( testXml, getTestSourceDirectory(), 
getTest().onlyMethodFilters(),
+                             getRerunFailingTestsCount() );//!
 
         final boolean actualFailIfNoTests;
 
-        if ( isValidSuiteXmlFileConfig() && getTest() == null )
+        if ( isValidSuiteXmlFileConfig() && !isSpecificTestSpecified() )
         {
             actualFailIfNoTests = getFailIfNoTests() != null && 
getFailIfNoTests();
             if ( !isTestNg )
@@ -1419,9 +1420,9 @@ public abstract class AbstractSurefireMojo
         }
         else
         {
-            if ( isSpecificTestSpecified() )
+            if ( isSpecificTestSpecified() )//!
             {
-                actualFailIfNoTests = getEffectiveFailIfNoTests();
+                actualFailIfNoTests = getEffectiveFailIfNoTests();//! 
isSpecificTestSpecified
                 setFailIfNoTests( actualFailIfNoTests );
             }
             else
@@ -1429,9 +1430,9 @@ public abstract class AbstractSurefireMojo
                 actualFailIfNoTests = getFailIfNoTests() != null && 
getFailIfNoTests();
             }
 
-            List<String> actualIncludes = getIncludeList();
-            List<String> actualExcludes = getExcludeList();
-            List<String> specificTests = getSpecificTests();
+            List<String> actualIncludes = getIncludeList();//!
+            List<String> actualExcludes = getExcludeList();//!
+            List<String> specificTests = getSpecificTests();//!
             directoryScannerParameters =
                 new DirectoryScannerParameters( getTestClassesDirectory(), 
actualIncludes, actualExcludes,
                                                 specificTests, 
actualFailIfNoTests, getRunOrder() );
@@ -1522,19 +1523,17 @@ public abstract class AbstractSurefireMojo
 
     private boolean isSpecificTestSpecified()
     {
-        return getTest() != null;
+        return getTest() != null;//!
     }
 
     private boolean isValidSuiteXmlFileConfig()
     {
-        return getSuiteXmlFiles() != null && getSuiteXmlFiles().length > 0;
+        return getSuiteXmlFiles() != null && getSuiteXmlFiles().length != 0;
     }
 
     @SuppressWarnings( "checkstyle:modifierorder" )
     private @Nonnull List<String> readListFromFile( @Nonnull final File file )
     {
-        List<String> list;
-
         getLog().debug( "Reading list from: " + file );
 
         if ( !file.exists() )
@@ -1544,25 +1543,25 @@ public abstract class AbstractSurefireMojo
 
         try
         {
-            list = FileUtils.loadFile( file );
+            List<String> list = FileUtils.loadFile( file );
+
+            if ( getLog().isDebugEnabled() )
+            {
+                getLog().debug( "List contents:" );
+                for ( String entry : list )
+                {
+                    getLog().debug( "  " + entry );
+                }
+            }
+            return list;
         }
         catch ( IOException e )
         {
             throw new RuntimeException( "Failed to load list from file: " + 
file, e );
         }
-
-        if ( getLog().isDebugEnabled() )
-        {
-            getLog().debug( "List contents:" );
-            for ( String entry : list )
-            {
-                getLog().debug( "  " + entry );
-            }
-        }
-        return list;
     }
 
-    private void maybeAppendList( final List<String> base, final List<String> 
list )
+    private void maybeAppendList( List<String> base, List<String> list )
     {
         if ( list != null )
         {
@@ -1574,7 +1573,7 @@ public abstract class AbstractSurefireMojo
     private @Nonnull List<String> getExcludeList()
     {
         List<String> actualExcludes = null;
-        if ( isSpecificTestSpecified() )
+        if ( isSpecificTestSpecified() )//!
         {
             // Check to see if we are running a single test. The raw parameter 
will
             // come through if it has not been set.
@@ -1584,24 +1583,24 @@ public abstract class AbstractSurefireMojo
         }
         else
         {
-            if ( getExcludesFile() != null )
+            if ( getExcludesFile() != null )//!
             {
-                actualExcludes = readListFromFile( getExcludesFile() );
+                actualExcludes = readListFromFile( getExcludesFile() );//!
             }
 
             // If we have excludesFile, and we have excludes, then append 
excludes to excludesFile content
             if ( actualExcludes == null )
             {
-                actualExcludes = this.getExcludes();
+                actualExcludes = getExcludes();//!
             }
             else
             {
-                maybeAppendList( actualExcludes, this.getExcludes() );
+                maybeAppendList( actualExcludes, getExcludes() );//!
             }
 
             // 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.size() == 0 )
+            if ( actualExcludes == null || actualExcludes.isEmpty() )
             {
                 actualExcludes = Arrays.asList( "**/*$*" );
             }
@@ -1612,33 +1611,33 @@ public abstract class AbstractSurefireMojo
     private List<String> getIncludeList()
     {
         List<String> includes = null;
-        if ( isSpecificTestSpecified() && !isMultipleExecutionBlocksDetected() 
)
+        if ( isSpecificTestSpecified() && !isMultipleExecutionBlocksDetected() 
)//!
         {
-            includes = getSpecificTests();
+            includes = getSpecificTests();//!
         }
         else
         {
-            if ( getIncludesFile() != null )
+            if ( getIncludesFile() != null )//!
             {
-                includes = readListFromFile( getIncludesFile() );
+                includes = readListFromFile( getIncludesFile() );//!
             }
 
             // If we have includesFile, and we have includes, then append 
includes to includesFile content
             if ( includes == null )
             {
-                includes = this.getIncludes();
+                includes = getIncludes();//!
             }
             else
             {
-                maybeAppendList( includes, this.getIncludes() );
+                maybeAppendList( includes, getIncludes() );//!
             }
         }
 
         // 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.size() == 0 )
+        if ( includes == null || includes.isEmpty() )
         {
-            includes = Arrays.asList( getDefaultIncludes() );
+            includes = Arrays.asList( getDefaultIncludes() );//!
         }
 
         return filterNulls( includes );
@@ -1679,27 +1678,24 @@ public abstract class AbstractSurefireMojo
 
     private List<String> getSpecificTests()
     {
-        if ( !isSpecificTestSpecified() )
-        {
-            return Collections.emptyList();
-        }
-
-        List<String> specificTests = new ArrayList<String>();
-        String[] testRegexes = StringUtils.split( getTest(), "," );
-
-        for ( String testRegexe : testRegexes )
+        if ( isSpecificTestSpecified() )//!
         {
-            String testRegex = testRegexe;
-            if ( testRegex.endsWith( ".java" ) )
+            List<String> specificTests = new ArrayList<String>();
+            for ( String testRegex : getTest().getTestSpecificClasses() )//!
             {
-                testRegex = testRegex.substring( 0, testRegex.length() - 5 );
+                if ( testRegex.endsWith( JAVA_EXTENSION ) )
+                {
+                    testRegex = testRegex.substring( 0, testRegex.length() - 
JAVA_EXTENSION.length() );
+                }
+                testRegex = testRegex.replace( '.', '/' );
+                specificTests.add( "**/" + testRegex + JAVA_EXTENSION );
             }
-            // Allow paths delimited by '.' or '/'
-            testRegex = testRegex.replace( '.', '/' );
-            specificTests.add( "**/" + testRegex + ".java" );
+            return specificTests;
+        }
+        else
+        {
+            return Collections.emptyList();
         }
-
-        return specificTests;
     }
 
     private Artifact getTestNgArtifact()
@@ -1751,7 +1747,7 @@ public abstract class AbstractSurefireMojo
         StartupConfiguration startupConfiguration = 
createStartupConfiguration( provider, classLoaderConfiguration );
         String configChecksum = getConfigChecksum();
         StartupReportConfiguration startupReportConfiguration = 
getStartupReportConfiguration( configChecksum );
-        ProviderConfiguration providerConfiguration = 
createProviderConfiguration( runOrderParameters );
+        ProviderConfiguration providerConfiguration = 
createProviderConfiguration( runOrderParameters );//! getTest
         return new ForkStarter( providerConfiguration, startupConfiguration, 
forkConfiguration,
                                 getForkedProcessTimeoutInSeconds(), 
startupReportConfiguration, log );
     }
@@ -1764,7 +1760,7 @@ public abstract class AbstractSurefireMojo
         StartupConfiguration startupConfiguration = 
createStartupConfiguration( provider, classLoaderConfiguration );
         String configChecksum = getConfigChecksum();
         StartupReportConfiguration startupReportConfiguration = 
getStartupReportConfiguration( configChecksum );
-        ProviderConfiguration providerConfiguration = 
createProviderConfiguration( runOrderParameters );
+        ProviderConfiguration providerConfiguration = 
createProviderConfiguration( runOrderParameters );//! getTest
         return new InPluginVMSurefireStarter( startupConfiguration, 
providerConfiguration, startupReportConfiguration );
 
     }
@@ -1921,9 +1917,9 @@ public abstract class AbstractSurefireMojo
         checksum.add( getAdditionalClasspathElements() );
         checksum.add( getReportsDirectory() );
         checksum.add( getTestSourceDirectory() );
-        checksum.add( getTest() );
-        checksum.add( getIncludes() );
-        checksum.add( getExcludes() );
+        checksum.add( isSpecificTestSpecified() ? 
getTest().getPluginParameterTest() : null );//!
+        checksum.add( getIncludes() );//!
+        checksum.add( getExcludes() );//!
         checksum.add( getLocalRepository() );
         checksum.add( getSystemProperties() );
         checksum.add( getSystemPropertyVariables() );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
index 22152f0..566c91f 100644
--- 
a/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
+++ 
b/maven-surefire-common/src/main/java/org/apache/maven/plugin/surefire/SurefireExecutionParameters.java
@@ -22,6 +22,7 @@ package org.apache.maven.plugin.surefire;
 import java.io.File;
 import java.util.List;
 import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.surefire.testset.TestListResolver;
 
 /**
  * This interface contains all the common parameters that have different 
implementations in Surefire vs IntegrationTest
@@ -63,9 +64,7 @@ public interface SurefireExecutionParameters
 
     void setTestSourceDirectory( File testSourceDirectory );
 
-    String getTest();
-
-    String getTestMethod();
+    TestListResolver getTest();
 
     void setTest( String test );
 

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/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 57581ad..bfdce4e 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
@@ -93,9 +93,8 @@ class BooterSerializer
         {
             properties.setProperty( BooterConstants.SOURCE_DIRECTORY, 
testSuiteDefinition.getTestSourceDirectory() );
             properties.addList( testSuiteDefinition.getSuiteXmlFiles(), 
BooterConstants.TEST_SUITE_XML_FILES );
-            properties.setNullableProperty( BooterConstants.REQUESTEDTEST, 
testSuiteDefinition.getRequestedTest() );
-            properties.setNullableProperty( 
BooterConstants.REQUESTEDTESTMETHOD,
-                                            
testSuiteDefinition.getRequestedTestMethod() );
+            properties.setNullableProperty( BooterConstants.REQUESTEDTEST,
+                                            
testSuiteDefinition.getTestListResolver().getPluginParameterTest() );
             properties.setNullableProperty( 
BooterConstants.RERUN_FAILING_TESTS_COUNT,
                                             String.valueOf( 
testSuiteDefinition.getRerunFailingTestsCount() ) );
         }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/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 60c1d49..356640e 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
@@ -161,7 +161,7 @@ public class DependencyScanner
             String[] specific = specificTests == null ? new String[0] : 
processIncludesExcludes( specificTests );
             specificTestFilter = new SpecificFileFilter( specific );
 
-            if ( includes != null && includes.size() > 0 )
+            if ( includes != null && !includes.isEmpty() )
             {
                 this.includes = MatchPatterns.from( processIncludesExcludes( 
includes ) );
             }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
index f72d4cd..94d89df 100644
--- 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
+++ 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerProviderConfigurationTest.java
@@ -36,8 +36,10 @@ import org.apache.maven.surefire.booter.StartupConfiguration;
 import org.apache.maven.surefire.booter.TypeEncodedValue;
 import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
+import org.apache.maven.surefire.testset.ResolvedTest;
 import org.apache.maven.surefire.testset.RunOrderParameters;
 import org.apache.maven.surefire.testset.TestArtifactInfo;
+import org.apache.maven.surefire.testset.TestListResolver;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.RunOrder;
 
@@ -55,9 +57,11 @@ public class BooterDeserializerProviderConfigurationTest
 
     public static final TypeEncodedValue aTestTyped = new TypeEncodedValue( 
String.class.getName(), "aTest" );
 
-    private final String aUserRequestedTest = "aUserRequestedTest";
+    private static final String aUserRequestedTest = "aUserRequestedTest";
 
-    private final int rerunFailingTestsCount = 3;
+    private static final String aUserRequestedTestMethod = 
"aUserRequestedTestMethod";
+
+    private static final int rerunFailingTestsCount = 3;
 
     private static ClassLoaderConfiguration getForkConfiguration()
     {
@@ -101,7 +105,7 @@ public class BooterDeserializerProviderConfigurationTest
         final StartupConfiguration testProviderConfiguration = 
getTestStartupConfiguration( forkConfiguration );
         ProviderConfiguration reloaded = saveAndReload( providerConfiguration, 
testProviderConfiguration, false );
 
-        assertTrue( 
reloaded.getReporterConfiguration().isTrimStackTrace().booleanValue() );
+        assertTrue( reloaded.getReporterConfiguration().isTrimStackTrace() );
         assertNotNull( 
reloaded.getReporterConfiguration().getReportsDirectory() );
     }
 
@@ -125,7 +129,17 @@ public class BooterDeserializerProviderConfigurationTest
         Assert.assertEquals( expected[0], suiteXmlFiles.get( 0 ) );
         Assert.assertEquals( expected[1], suiteXmlFiles.get( 1 ) );
         Assert.assertEquals( getTestSourceDirectory(), 
testSuiteDefinition.getTestSourceDirectory() );
-        Assert.assertEquals( aUserRequestedTest, 
testSuiteDefinition.getRequestedTest() );
+        TestListResolver resolver = testSuiteDefinition.getTestListResolver();
+        Assert.assertNotNull( resolver );
+        Assert.assertFalse( resolver.isEmpty() );
+        Assert.assertEquals( aUserRequestedTest + "#" + 
aUserRequestedTestMethod, resolver.getPluginParameterTest() );
+        Assert.assertFalse( resolver.getIncludedFilters().isEmpty() );
+        Assert.assertTrue( resolver.getExcludedFilters().isEmpty() );
+        Assert.assertEquals( 1, resolver.getIncludedFilters().size() );
+        ResolvedTest filter = resolver.getIncludedFilters().iterator().next();
+        Assert.assertNotNull( filter );
+        Assert.assertEquals( aUserRequestedTest + ".class", 
filter.getTestClassPattern() );
+        Assert.assertEquals( aUserRequestedTestMethod, 
filter.getTestMethodPattern() );
         Assert.assertEquals( rerunFailingTestsCount, 
testSuiteDefinition.getRerunFailingTestsCount() );
     }
 
@@ -150,7 +164,7 @@ public class BooterDeserializerProviderConfigurationTest
         throws IOException
     {
         ProviderConfiguration reloaded = getReloadedProviderConfiguration();
-        assertTrue( reloaded.isFailIfNoTests().booleanValue() );
+        assertTrue( reloaded.isFailIfNoTests() );
 
     }
 
@@ -217,13 +231,12 @@ public class BooterDeserializerProviderConfigurationTest
     private ProviderConfiguration getTestProviderConfiguration( 
DirectoryScannerParameters directoryScannerParameters,
                                                                 boolean 
readTestsFromInStream )
     {
-
         File cwd = new File( "." );
-        ReporterConfiguration reporterConfiguration = new 
ReporterConfiguration( cwd, Boolean.TRUE );
-        String aUserRequestedTestMethod = "aUserRequestedTestMethod";
+        ReporterConfiguration reporterConfiguration = new 
ReporterConfiguration( cwd, true );
         TestRequest testSuiteDefinition =
-            new TestRequest( getSuiteXmlFileStrings(), 
getTestSourceDirectory(), aUserRequestedTest,
-                             aUserRequestedTestMethod, rerunFailingTestsCount 
);
+            new TestRequest( getSuiteXmlFileStrings(), 
getTestSourceDirectory(),
+                             new TestListResolver( aUserRequestedTest + 
"#aUserRequestedTestMethod" ),
+                             rerunFailingTestsCount );
         RunOrderParameters runOrderParameters = new RunOrderParameters( 
RunOrder.DEFAULT, null );
         return new ProviderConfiguration( directoryScannerParameters, 
runOrderParameters, true, reporterConfiguration,
                                           new TestArtifactInfo( "5.0", "ABC" 
), testSuiteDefinition, new Properties(),
@@ -250,6 +263,6 @@ public class BooterDeserializerProviderConfigurationTest
 
     private List<String> getSuiteXmlFileStrings()
     {
-        return Arrays.asList( new String[]{ "A1", "A2" } );
+        return Arrays.asList( "A1", "A2" );
     }
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
index 7c11370..90af606 100644
--- 
a/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
+++ 
b/maven-surefire-common/src/test/java/org/apache/maven/plugin/surefire/booterclient/BooterDeserializerStartupConfigurationTest.java
@@ -36,6 +36,7 @@ import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
 import org.apache.maven.surefire.testset.RunOrderParameters;
 import org.apache.maven.surefire.testset.TestArtifactInfo;
+import org.apache.maven.surefire.testset.TestListResolver;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.RunOrder;
 
@@ -137,11 +138,9 @@ public class BooterDeserializerStartupConfigurationTest
             new DirectoryScannerParameters( cwd, new ArrayList<String>(), new 
ArrayList<String>(),
                                             new ArrayList<String>(), 
Boolean.TRUE, "hourly" );
         ReporterConfiguration reporterConfiguration = new 
ReporterConfiguration( cwd, Boolean.TRUE );
-        String aUserRequestedTest = "aUserRequestedTest";
-        String aUserRequestedTestMethod = "aUserRequestedTestMethod";
         TestRequest testSuiteDefinition =
-            new TestRequest( Arrays.asList( getSuiteXmlFileStrings() ), 
getTestSourceDirectory(), aUserRequestedTest,
-                             aUserRequestedTestMethod );
+            new TestRequest( Arrays.asList( getSuiteXmlFileStrings() ), 
getTestSourceDirectory(),
+                             new TestListResolver( 
"aUserRequestedTest#aUserRequestedTestMethod" ));
 
         RunOrderParameters runOrderParameters = new RunOrderParameters( 
RunOrder.DEFAULT, null );
         return new ProviderConfiguration( directoryScannerParameters, 
runOrderParameters, true, reporterConfiguration,

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
----------------------------------------------------------------------
diff --git 
a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
 
b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
index e13661d..988cddc 100644
--- 
a/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
+++ 
b/maven-surefire-plugin/src/main/java/org/apache/maven/plugin/surefire/SurefirePlugin.java
@@ -28,7 +28,7 @@ import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.surefire.suite.RunResult;
-import org.apache.maven.surefire.util.internal.StringUtils;
+import org.apache.maven.surefire.testset.TestListResolver;
 
 /**
  * Run tests using Surefire.
@@ -236,6 +236,8 @@ public class SurefirePlugin
     @Parameter( property = "surefire.runOrder", defaultValue = "filesystem" )
     protected String runOrder;
 
+    private TestListResolver testListResolver;
+
     protected int getRerunFailingTestsCount()
     {
         return rerunFailingTestsCount;
@@ -370,60 +372,13 @@ public class SurefirePlugin
         this.reportsDirectory = reportsDirectory;
     }
 
-    public String getTest()
-    {
-        if ( StringUtils.isBlank( test ) )
-        {
-            return null;
-        }
-        String[] testArray = StringUtils.split( test, "," );
-        StringBuilder tests = new StringBuilder();
-        for ( String aTestArray : testArray )
-        {
-            String singleTest = aTestArray;
-            int index = singleTest.indexOf( '#' );
-            if ( index >= 0 )
-            { // the way version 2.7.3. support single test method
-                singleTest = singleTest.substring( 0, index );
-            }
-            tests.append( singleTest );
-            tests.append( "," );
-        }
-        return tests.toString();
-    }
-
-    /**
-     * @since 2.7.3
-     */
-    public String getTestMethod()
+    public TestListResolver getTest()
     {
-        if ( StringUtils.isBlank( test ) )
-        {
-            return null;
-        }
-        //modified by rainLee, see http://jira.codehaus.org/browse/SUREFIRE-745
-        int index = this.test.indexOf( '#' );
-        int index2 = this.test.indexOf( "," );
-        if ( index >= 0 )
+        if ( testListResolver == null && test != null )
         {
-            if ( index2 < 0 )
-            {
-                String testStrAfterFirstSharp = this.test.substring( index + 
1, this.test.length() );
-                if ( !testStrAfterFirstSharp.contains( "+" ) )
-                { //the original way
-                    return testStrAfterFirstSharp;
-                }
-                else
-                {
-                    return this.test;
-                }
-            }
-            else
-            {
-                return this.test;
-            }
+            testListResolver = new TestListResolver( test );
         }
-        return null;
+        return testListResolver;
     }
 
     public boolean isUseSystemClassLoader()

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
----------------------------------------------------------------------
diff --git 
a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
 
b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
index da7cbc3..08ff094 100644
--- 
a/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
+++ 
b/surefire-api/src/main/java/org/apache/maven/surefire/booter/SurefireReflector.java
@@ -33,6 +33,7 @@ import org.apache.maven.surefire.suite.RunResult;
 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
 import org.apache.maven.surefire.testset.RunOrderParameters;
 import org.apache.maven.surefire.testset.TestArtifactInfo;
+import org.apache.maven.surefire.testset.TestListResolver;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.ReflectionUtils;
 import org.apache.maven.surefire.util.RunOrder;
@@ -77,6 +78,8 @@ public class SurefireReflector
 
     private final Class reporterFactory;
 
+    private final Class testListResolver;
+
 
     public SurefireReflector( ClassLoader surefireClassLoader )
     {
@@ -98,6 +101,7 @@ public class SurefireReflector
             reporterFactory = surefireClassLoader.loadClass( 
ReporterFactory.class.getName() );
             runResult = surefireClassLoader.loadClass( 
RunResult.class.getName() );
             booterParameters = surefireClassLoader.loadClass( 
ProviderParameters.class.getName() );
+            testListResolver = surefireClassLoader.loadClass( 
TestListResolver.class.getName() );
         }
         catch ( ClassNotFoundException e )
         {
@@ -152,13 +156,28 @@ public class SurefireReflector
         {
             return null;
         }
-        Class[] arguments = { List.class, File.class, String.class, 
String.class, int.class };
-        Constructor constructor = ReflectionUtils.getConstructor( 
this.testRequest, arguments );
-        return ReflectionUtils.newInstance( constructor, new Object[]{ 
suiteDefinition.getSuiteXmlFiles(),
-            suiteDefinition.getTestSourceDirectory(), 
suiteDefinition.getRequestedTest(),
-            suiteDefinition.getRequestedTestMethod(), 
suiteDefinition.getRerunFailingTestsCount() } );
+        else
+        {
+            Object resolver = createTestListResolver( 
suiteDefinition.getTestListResolver() );
+            Class[] arguments = { List.class, File.class, testListResolver, 
int.class };
+            Constructor constructor = ReflectionUtils.getConstructor( 
testRequest, arguments );
+            return ReflectionUtils.newInstance( constructor, new Object[]{ 
suiteDefinition.getSuiteXmlFiles(),
+                suiteDefinition.getTestSourceDirectory(), resolver, 
suiteDefinition.getRerunFailingTestsCount() } );
+        }
     }
 
+    Object createTestListResolver( TestListResolver resolver )
+    {
+        if ( resolver == null )
+        {
+            return null;
+        }
+        else
+        {
+            Constructor constructor = ReflectionUtils.getConstructor( 
testListResolver, new Class[] { String.class } );
+            return ReflectionUtils.newInstance( constructor, new Object[] { 
resolver.getPluginParameterTest() } );
+        }
+    }
 
     Object createDirectoryScannerParameters( DirectoryScannerParameters 
directoryScannerParameters )
     {
@@ -269,7 +288,7 @@ public class SurefireReflector
     void setTestSuiteDefinition( Object o, TestRequest testSuiteDefinition1 )
     {
         final Object param = createTestRequest( testSuiteDefinition1 );
-        ReflectionUtils.invokeSetter( o, "setTestRequest", this.testRequest, 
param );
+        ReflectionUtils.invokeSetter( o, "setTestRequest", testRequest, param 
);
     }
 
     public void setProviderPropertiesAware( Object o, Properties properties )

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/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
new file mode 100644
index 0000000..79f4174
--- /dev/null
+++ 
b/surefire-api/src/main/java/org/apache/maven/surefire/testset/ResolvedTest.java
@@ -0,0 +1,261 @@
+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.apache.maven.shared.utils.io.SelectorUtils;
+
+import java.util.Map;
+
+/**
+ * Single pattern test filter resolved from multi pattern filter 
-Dtest=MyTest#test,AnotherTest#otherTest.
+ */
+public final class ResolvedTest
+{
+    private static final String CLASS_FILE_EXTENSION = ".class";
+
+    private static final String JAVA_FILE_EXTENSION = ".java";
+
+    private final String classPattern;
+
+    private final String methodPattern;
+
+    private final Map<Class<?>, String> classConversion;
+
+    private final boolean isRegexTestClassPattern;
+
+    private final boolean isRegexTestMethodPattern;
+
+    /**
+     * '*' means zero or more characters<br>
+     * '?' means one and only one character
+     * The %ant[] expression is substituted by %regex[].
+     *
+     * @param classPattern     test class file pattern
+     * @param methodPattern    test method
+     * @throws IllegalArgumentException if regex not finished with ']'
+     */
+    ResolvedTest( String classPattern, String methodPattern, Map<Class<?>, 
String> classConversion )
+    {
+        this.classPattern = reformatPattern( classPattern, true );
+        this.methodPattern = reformatPattern( methodPattern, false );
+        this.classConversion = classConversion;
+        isRegexTestClassPattern =
+            this.classPattern != null && this.classPattern.startsWith( 
SelectorUtils.REGEX_HANDLER_PREFIX );
+        isRegexTestMethodPattern =
+            this.methodPattern != null && this.methodPattern.startsWith( 
SelectorUtils.REGEX_HANDLER_PREFIX );
+    }
+
+    /**
+     * Test class file pattern, e.g. org&#47;**&#47;Cat*.class<br/>
+     * 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>
+     * '?' means one and only one character
+     */
+    public String getTestClassPattern()
+    {
+        return classPattern;
+    }
+
+    /**
+     * Test method, e.g. "realTestMethod".<br/>
+     * Other examples: test* or testSomethin? or %regex[testOne|testTwo] or 
%ant[testOne|testTwo]<br/>
+     * <br/>
+     * '*' means zero or more characters<br>
+     * '?' means one and only one character
+     */
+    public String getTestMethodPattern()
+    {
+        return methodPattern;
+    }
+
+    public boolean isRegexTestClassPattern()
+    {
+        return isRegexTestClassPattern;
+    }
+
+    public boolean isRegexTestMethodPattern()
+    {
+        return isRegexTestMethodPattern;
+    }
+
+    public boolean isEmpty()
+    {
+        return classPattern == null && methodPattern == null;
+    }
+
+    public boolean shouldRun( Class<?> realTestClass, String methodName )
+    {
+        if ( methodPattern != null )
+        {
+            if ( methodName != null && !SelectorUtils.matchPath( 
methodPattern, methodName ) )
+            {
+                return false;
+            }
+        }
+
+        if ( classPattern == null )
+        {
+            return methodName != null;
+        }
+        else
+        {
+            String classFile = classFile( realTestClass );
+            if ( isRegexTestClassPattern() )
+            {
+                String pattern = classPattern.indexOf( '$' ) == -1 ? 
classPattern : classPattern.replace( "$", "\\$" );
+                return SelectorUtils.matchPath( pattern, classFile );
+            }
+            else
+            {
+                if ( SelectorUtils.matchPath( classPattern, classFile ) )
+                {
+                    // match class pattern with package
+                    return true;
+                }
+                else
+                {
+                    int indexOfSimpleName = classFile.lastIndexOf( '/' );
+                    return indexOfSimpleName != -1
+                        && SelectorUtils.matchPath( classPattern, 
classFile.substring( 1 + indexOfSimpleName ) );
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        ResolvedTest that = (ResolvedTest) o;
+
+        return ( classPattern == null ? that.classPattern == null : 
classPattern.equals( that.classPattern ) )
+            && ( methodPattern == null ? that.methodPattern == null : 
methodPattern.equals( that.methodPattern ) );
+
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = classPattern != null ? classPattern.hashCode() : 0;
+        result = 31 * result + ( methodPattern != null ? 
methodPattern.hashCode() : 0 );
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        return "ResolvedTest{classPattern='" + classPattern + "', 
methodPattern='" + methodPattern + "'}";
+    }
+
+    private String classFile( Class<?> realTestClass )
+    {
+        String classFile = classConversion.get( realTestClass );
+        if ( classFile == null )
+        {
+            classFile = realTestClass.getName().replace( '.', '/' ) + 
CLASS_FILE_EXTENSION;
+            classConversion.put( realTestClass, classFile );
+        }
+        return classFile;
+    }
+
+    /**
+     * {@link Class#getSimpleName()} does not return this format with nested 
classes FirstClass$NestedTest.
+     */
+    private static String simpleClassFileName( String classFile )
+    {
+        int indexOfSimpleName = classFile.lastIndexOf( '/' );
+        return indexOfSimpleName == -1 ? classFile : classFile.substring( 1 + 
indexOfSimpleName );
+    }
+
+    private static String tryBlank( String s )
+    {
+        if ( s == null )
+        {
+            return null;
+        }
+        else
+        {
+            s = s.trim();
+            return s.length() == 0 ? null : s;
+        }
+    }
+
+    private static String reformatPattern( String s, boolean isTestClass )
+    {
+        s = tryBlank( s );
+        if ( s == null )
+        {
+            return null;
+        }
+        else if ( s.startsWith( SelectorUtils.REGEX_HANDLER_PREFIX ) )
+        {
+            if ( !s.endsWith( SelectorUtils.PATTERN_HANDLER_SUFFIX ) )
+            {
+                throw new IllegalArgumentException( s + " enclosed regex does 
not finish with ']'" );
+            }
+        }
+        else if ( s.startsWith( SelectorUtils.ANT_HANDLER_PREFIX ) )
+        {
+            if ( s.endsWith( SelectorUtils.PATTERN_HANDLER_SUFFIX ) )
+            {
+                s = SelectorUtils.REGEX_HANDLER_PREFIX + s.substring( 
SelectorUtils.ANT_HANDLER_PREFIX.length() );
+            }
+            else
+            {
+                throw new IllegalArgumentException( s + " enclosed regex does 
not finish with ']'" );
+            }
+        }
+        else if ( isTestClass )
+        {
+            s = convertToPath( s );
+        }
+        return s;
+    }
+
+    private static String convertToPath( String className )
+    {
+        if ( className == null || className.trim().length() == 0 )
+        {
+            return className;
+        }
+        else
+        {
+            if ( className.endsWith( JAVA_FILE_EXTENSION ) )
+            {
+                className = className.substring( 0, className.length() - 
JAVA_FILE_EXTENSION.length() );
+            }
+            else if ( className.endsWith( CLASS_FILE_EXTENSION ) )
+            {
+                className = className.substring( 0, className.length() - 
CLASS_FILE_EXTENSION.length() );
+            }
+            className = className.replace( '.', '/' );
+            return className + CLASS_FILE_EXTENSION;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/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
new file mode 100644
index 0000000..374d1a4
--- /dev/null
+++ 
b/surefire-api/src/main/java/org/apache/maven/surefire/testset/TestListResolver.java
@@ -0,0 +1,261 @@
+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.apache.maven.shared.utils.StringUtils;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Resolved multi pattern filter e.g. 
-Dtest=MyTest#test,!AnotherTest#otherTest into an object model
+ * composed of included and excluded tests.<br/>
+ * The methods {@link #shouldRun(Class, String)} are filters easily used in 
JUnit filter or TestNG.
+ * This class is independent of JUnit and TestNG API.<br/>
+ * This class is accessed by Java Reflection API in {@link 
org.apache.maven.surefire.booter.SurefireReflector}
+ * using specific ClassLoader.
+ */
+public class TestListResolver
+{
+    private static final String JAVA_CLASS_FILE_EXTENSION = ".class";
+
+    private final String parameterTest;
+
+    private final Set<ResolvedTest> includedFilters;
+
+    private final Set<ResolvedTest> excludedFilters;
+
+    private final Set<String> specificClasses;
+
+    public TestListResolver( String parameterTest )
+    {
+        Set<ResolvedTest> includedFilters = new LinkedHashSet<ResolvedTest>( 0 
);
+        Set<ResolvedTest> excludedFilters = new LinkedHashSet<ResolvedTest>( 0 
);
+        Set<String> specificClasses = new LinkedHashSet<String>( 0 );
+        if ( StringUtils.isNotBlank( parameterTest ) )
+        {
+            final Map<Class<?>, String> classConversion = new 
IdentityHashMap<Class<?>, String>( 512 );
+            for ( String request : StringUtils.split( parameterTest, "," ) )
+            {
+                request = request.trim();
+                if ( request.length() != 0 && !request.equals( "!" ) )
+                {
+                    final int indexOfMethodSeparator = request.indexOf( '#' );
+                    if ( indexOfMethodSeparator == -1 )
+                    {
+                        String classPattern = removeExclamationMark( request );
+                        boolean isExcluded = classPattern.length() < 
request.length();
+                        ResolvedTest test = new ResolvedTest( classPattern, 
null, classConversion );
+                        if ( !test.isEmpty() )
+                        {
+                            updatedFilters( isExcluded, test, includedFilters, 
excludedFilters );
+                        }
+                    }
+                    else
+                    {
+                        String className = request.substring( 0, 
indexOfMethodSeparator );
+                        String methodNames = request.substring( 1 + 
indexOfMethodSeparator );
+                        for ( String methodName : StringUtils.split( 
methodNames, "+" ) )
+                        {
+                            String classPattern = removeExclamationMark( 
className );
+                            boolean isExcluded = classPattern.length() < 
className.length();
+                            ResolvedTest test = new ResolvedTest( 
classPattern, methodName, classConversion );
+                            if ( !test.isEmpty() )
+                            {
+                                updatedFilters( isExcluded, test, 
includedFilters, excludedFilters );
+                            }
+                        }
+                    }
+                }
+            }
+
+            for ( ResolvedTest test : includedFilters )
+            {
+                populateSpecificClasses( specificClasses, test );
+            }
+
+            for ( ResolvedTest test : excludedFilters )
+            {
+                populateSpecificClasses( specificClasses, test );
+            }
+        }
+        this.parameterTest = StringUtils.isBlank( parameterTest ) ? null : 
parameterTest;
+        this.specificClasses = Collections.unmodifiableSet( specificClasses );
+        this.includedFilters = Collections.unmodifiableSet( includedFilters );
+        this.excludedFilters = Collections.unmodifiableSet( excludedFilters );
+    }
+
+    private TestListResolver( String parameterTest, Set<ResolvedTest> 
includedFilters,
+                              Set<ResolvedTest> excludedFilters )
+    {
+        this.includedFilters = includedFilters;
+        this.excludedFilters = excludedFilters;
+        this.specificClasses = null;
+        this.parameterTest = parameterTest;
+    }
+
+    public TestListResolver onlyMethodFilters()
+    {
+        return new TestListResolver( getPluginParameterTest(), 
selectMethodFilters( getIncludedFilters() ),
+                                     selectMethodFilters( getExcludedFilters() 
) );
+    }
+
+    public boolean shouldRun( Class<?> testClass, String methodName )
+    {
+        if ( isEmpty() || testClass == null && methodName == null )
+        {
+            return true;
+        }
+        else
+        {
+            boolean shouldRun = false;
+
+            if ( includedFilters.isEmpty() )
+            {
+                shouldRun = true;
+            }
+            else
+            {
+                for ( ResolvedTest filter : includedFilters )
+                {
+                    if ( filter.shouldRun( testClass, methodName ) )
+                    {
+                        shouldRun = true;
+                        break;
+                    }
+                }
+            }
+
+            if ( shouldRun )
+            {
+                for ( ResolvedTest filter : excludedFilters )
+                {
+                    if ( filter.shouldRun( testClass, methodName ) )
+                    {
+                        shouldRun = false;
+                        break;
+                    }
+                }
+            }
+            return shouldRun;
+        }
+    }
+
+    public boolean isEmpty()
+    {
+        return getIncludedFilters().isEmpty() && 
getIncludedFilters().isEmpty();
+    }
+
+    public String getPluginParameterTest()
+    {
+        return parameterTest;
+    }
+
+    public Set<ResolvedTest> getIncludedFilters()
+    {
+        return includedFilters;
+    }
+
+    public Set<ResolvedTest> getExcludedFilters()
+    {
+        return excludedFilters;
+    }
+
+    public Set<String> getTestSpecificClasses()
+    {
+        return specificClasses;
+    }
+
+    @Override
+    public boolean equals( Object o )
+    {
+        if ( this == o )
+        {
+            return true;
+        }
+        if ( o == null || getClass() != o.getClass() )
+        {
+            return false;
+        }
+
+        TestListResolver that = (TestListResolver) o;
+
+        return getIncludedFilters().equals( that.getIncludedFilters() )
+            && getExcludedFilters().equals( that.getExcludedFilters() );
+
+    }
+
+    @Override
+    public int hashCode()
+    {
+        int result = getIncludedFilters().hashCode();
+        result = 31 * result + getExcludedFilters().hashCode();
+        return result;
+    }
+
+    private static String removeExclamationMark( String s )
+    {
+        return s.length() != 0 && s.charAt( 0 ) == '!' ? s.substring( 1 ) : s;
+    }
+
+    private static void updatedFilters( boolean isExcluded, ResolvedTest test, 
Collection<ResolvedTest> includedFilters,
+                                        Collection<ResolvedTest> 
excludedFilters )
+    {
+        if ( isExcluded )
+        {
+            excludedFilters.add( test );
+        }
+        else
+        {
+            includedFilters.add( test );
+        }
+    }
+
+    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 Set<ResolvedTest> selectMethodFilters( 
Collection<ResolvedTest> filters )
+    {
+        Set<ResolvedTest> selectedFilters = new HashSet<ResolvedTest>( 
filters.size() );
+        for ( ResolvedTest filter : filters )
+        {
+            if ( filter.getTestMethodPattern() != null )
+            {
+                selectedFilters.add( filter );
+            }
+        }
+        return selectedFilters;
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/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 a237bbe..3a489fc 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
@@ -34,35 +34,21 @@ public class TestRequest
 
     private final File testSourceDirectory;
 
-    private final String requestedTest;
+    private final TestListResolver requestedTests;
 
     private final int rerunFailingTestsCount;
 
-    /**
-     * @since 2.7.3
-     */
-    private final String requestedTestMethod;
-
-    public TestRequest( List suiteXmlFiles, File testSourceDirectory, String 
requestedTest )
-    {
-        this( suiteXmlFiles, testSourceDirectory, requestedTest, null );
-    }
-
-    /**
-     * @since 2.7.3
-     */
-    public TestRequest( List suiteXmlFiles, File testSourceDirectory, String 
requestedTest, String requestedTestMethod )
+    public TestRequest( List suiteXmlFiles, File testSourceDirectory, 
TestListResolver requestedTests )
     {
-        this( createFiles( suiteXmlFiles ), testSourceDirectory, 
requestedTest, requestedTestMethod, 0 );
+        this( createFiles( suiteXmlFiles ), testSourceDirectory, 
requestedTests, 0 );
     }
 
-    public TestRequest( List suiteXmlFiles, File testSourceDirectory, String 
requestedTest, String requestedTestMethod,
+    public TestRequest( List suiteXmlFiles, File testSourceDirectory, 
TestListResolver requestedTests,
                         int rerunFailingTestsCount )
     {
         this.suiteXmlFiles = createFiles( suiteXmlFiles );
         this.testSourceDirectory = testSourceDirectory;
-        this.requestedTest = requestedTest;
-        this.requestedTestMethod = requestedTestMethod;
+        this.requestedTests = requestedTests;
         this.rerunFailingTestsCount = rerunFailingTestsCount;
     }
 
@@ -88,23 +74,10 @@ public class TestRequest
 
     /**
      * A specific test request issued with -Dtest= from the command line.
-     *
-     * @return The string specified at the command line
-     */
-    public String getRequestedTest()
-    {
-        return requestedTest;
-    }
-
-    /**
-     * A specific test request method issued with -Dtest=class#method from the 
command line.
-     *
-     * @return The string specified at the command line
-     * @since 2.7.3
      */
-    public String getRequestedTestMethod()
+    public TestListResolver getTestListResolver()
     {
-        return requestedTestMethod;
+        return requestedTests;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/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 ae9dbce..1ce2330 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
@@ -27,6 +27,7 @@ import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
 import org.apache.maven.surefire.testset.RunOrderParameters;
 import org.apache.maven.surefire.testset.TestArtifactInfo;
+import org.apache.maven.surefire.testset.TestListResolver;
 import org.apache.maven.surefire.testset.TestRequest;
 
 // CHECKSTYLE_OFF: imports
@@ -68,7 +69,6 @@ public class BooterDeserializer
             properties.getBooleanProperty( 
FORKTESTSET_PREFER_TESTS_FROM_IN_STREAM );
 
         final String requestedTest = properties.getProperty( REQUESTEDTEST );
-        final String requestedTestMethod = properties.getProperty( 
REQUESTEDTESTMETHOD );
         final File sourceDirectory = properties.getFileProperty( 
SOURCE_DIRECTORY );
 
         final List excludesList = properties.getStringList( 
EXCLUDES_PROPERTY_PREFIX );
@@ -90,7 +90,7 @@ public class BooterDeserializer
 
         TestArtifactInfo testNg = new TestArtifactInfo( testNgVersion, 
testArtifactClassifier );
         TestRequest testSuiteDefinition =
-            new TestRequest( testSuiteXmlFiles, sourceDirectory, 
requestedTest, requestedTestMethod,
+            new TestRequest( testSuiteXmlFiles, sourceDirectory, new 
TestListResolver( requestedTest ),
                              rerunFailingTestsCount );
 
         ReporterConfiguration reporterConfiguration =

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
----------------------------------------------------------------------
diff --git 
a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
 
b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
index 801fb4f..d46304c 100644
--- 
a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
+++ 
b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ForkedBooter.java
@@ -221,13 +221,13 @@ public class ForkedBooter
         BaseProviderFactory bpf = new BaseProviderFactory( (ReporterFactory) 
reporterManagerFactory1, isInsideFork );
         bpf.setTestRequest( providerConfiguration.getTestSuiteDefinition() );
         bpf.setReporterConfiguration( 
providerConfiguration.getReporterConfiguration() );
-        ClassLoader clasLoader = 
Thread.currentThread().getContextClassLoader();
-        bpf.setClassLoaders( clasLoader );
+        ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
+        bpf.setClassLoaders( classLoader );
         bpf.setTestArtifactInfo( providerConfiguration.getTestArtifact() );
         bpf.setProviderProperties( 
providerConfiguration.getProviderProperties() );
         bpf.setRunOrderParameters( 
providerConfiguration.getRunOrderParameters() );
         bpf.setDirectoryScannerParameters( 
providerConfiguration.getDirScannerParams() );
-        return (SurefireProvider) ReflectionUtils.instantiateOneArg( 
clasLoader,
+        return (SurefireProvider) ReflectionUtils.instantiateOneArg( 
classLoader,
                                                                      
startupConfiguration1.getActualClassName(),
                                                                      
ProviderParameters.class, bpf );
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
----------------------------------------------------------------------
diff --git 
a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
 
b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
index f75e5a6..8081988 100644
--- 
a/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
+++ 
b/surefire-booter/src/main/java/org/apache/maven/surefire/booter/ProviderFactory.java
@@ -72,16 +72,19 @@ public class ProviderFactory
         // in createProvider below. These are the same values as here.
 
         ProviderFactory providerFactory =
-            new ProviderFactory( startupConfiguration1, providerConfiguration, 
testsClassLoader,
-                                 factory );
+            new ProviderFactory( startupConfiguration1, providerConfiguration, 
testsClassLoader, factory );
         final SurefireProvider provider = providerFactory.createProvider( 
insideFork );
-
         try
         {
             return provider.invoke( testSet );
         }
         finally
         {
+            System.out.println( "TIBOR providerConfiguration: " + 
providerConfiguration );
+            System.out.println( "TIBOR 
providerConfiguration.getTestSuiteDefinition(): "
+                                    + 
providerConfiguration.getTestSuiteDefinition() );
+            System.out.println( "TIBOR 
providerConfiguration.getTestSuiteDefinition().getTestListResolver(): "
+                                    + 
providerConfiguration.getTestSuiteDefinition().getTestListResolver() );
             if ( restoreStreams && System.getSecurityManager() == null )
             {
                 System.setOut( orgSystemOut );
@@ -93,14 +96,11 @@ public class ProviderFactory
 
     public SurefireProvider createProvider( boolean isInsideFork )
     {
-        ClassLoader systemClassLoader = 
java.lang.Thread.currentThread().getContextClassLoader();
-        Thread.currentThread().setContextClassLoader( classLoader );
-
-        StartupConfiguration starterConfiguration = startupConfiguration;
-
+        final Thread currentThread = Thread.currentThread();
+        final ClassLoader systemClassLoader = 
currentThread.getContextClassLoader();
+        currentThread.setContextClassLoader( classLoader );
         // Note: Duplicated in ForkedBooter#createProviderInCurrentClassloader
-        final Object o =
-            surefireReflector.createBooterConfiguration( classLoader, 
reporterManagerFactory, isInsideFork );
+        Object o = surefireReflector.createBooterConfiguration( classLoader, 
reporterManagerFactory, isInsideFork );
         surefireReflector.setTestSuiteDefinitionAware( o, 
providerConfiguration.getTestSuiteDefinition() );
         surefireReflector.setProviderPropertiesAware( o, 
providerConfiguration.getProviderProperties() );
         surefireReflector.setReporterConfigurationAware( o, 
providerConfiguration.getReporterConfiguration() );
@@ -109,8 +109,8 @@ public class ProviderFactory
         surefireReflector.setRunOrderParameters( o, 
providerConfiguration.getRunOrderParameters() );
         surefireReflector.setIfDirScannerAware( o, 
providerConfiguration.getDirScannerParams() );
 
-        Object provider = surefireReflector.instantiateProvider( 
starterConfiguration.getActualClassName(), o );
-        Thread.currentThread().setContextClassLoader( systemClassLoader );
+        Object provider = surefireReflector.instantiateProvider( 
startupConfiguration.getActualClassName(), o );
+        currentThread.setContextClassLoader( systemClassLoader );
 
         return new ProviderProxy( provider, classLoader );
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java
----------------------------------------------------------------------
diff --git 
a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java
 
b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java
index 66901f7..d4f48d0 100644
--- 
a/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java
+++ 
b/surefire-booter/src/test/java/org/apache/maven/surefire/booter/SurefireReflectorTest.java
@@ -29,6 +29,7 @@ import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.testset.DirectoryScannerParameters;
 import org.apache.maven.surefire.testset.RunOrderParameters;
 import org.apache.maven.surefire.testset.TestArtifactInfo;
+import org.apache.maven.surefire.testset.TestListResolver;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.util.RunOrder;
 
@@ -74,7 +75,7 @@ public class SurefireReflectorTest
 
         TestRequest testSuiteDefinition =
             new TestRequest( Arrays.asList( new File( "file1" ), new File( 
"file2" ) ),
-                             new File( "TestSOurce" ), "aUserRequestedTest", 
"aMethodRequested" );
+                             new File( "TestSOurce" ), new TestListResolver( 
"aUserRequestedTest#aMethodRequested" ) );
         surefireReflector.setTestSuiteDefinition( foo, testSuiteDefinition );
         assertTrue( isCalled( foo ) );
     }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-integration-tests/pom.xml
----------------------------------------------------------------------
diff --git a/surefire-integration-tests/pom.xml 
b/surefire-integration-tests/pom.xml
index 8990d47..6361c50 100644
--- a/surefire-integration-tests/pom.xml
+++ b/surefire-integration-tests/pom.xml
@@ -101,7 +101,9 @@
           <forkMode>never</forkMode>
           <argLine>-Xmx512m -XX:MaxPermSize=356m</argLine>
           <includes>
-            <include>org/apache/**/*IT*.java</include>
+            
<!--<include>org/apache/**/TestMultipleMethodPatternsIT.java</include>-->
+            <include>org/apache/**/JUnit47ParallelIT.java</include>
+            <!--include>org/apache/**/*IT*.java</include-->
           </includes>
           <!-- Pass current surefire version to the main suite so that it -->
           <!-- can forward to all integration test projects. SUREFIRE-513 -->

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java
 
b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java
index a3b00ea..5284ea1 100644
--- 
a/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java
+++ 
b/surefire-integration-tests/src/test/java/org/apache/maven/surefire/its/TestMultipleMethodPatternsIT.java
@@ -21,6 +21,7 @@ package org.apache.maven.surefire.its;
 
 import org.apache.maven.surefire.its.fixture.OutputValidator;
 import org.apache.maven.surefire.its.fixture.SurefireJUnit4IntegrationTestCase;
+import org.apache.maven.surefire.its.fixture.SurefireLauncher;
 import org.junit.Test;
 
 
@@ -33,18 +34,142 @@ public class TestMultipleMethodPatternsIT
 
     private static final String RUNNING_WITH_JUNIT48 = "parallel='none', 
perCoreThreadCount=true, threadCount=0";
 
-    public OutputValidator multipleMethod( String projectName )
+    /*public OutputValidator multipleMethod( String projectName )
         throws Exception
     {
         return unpack( projectName 
).executeTest().verifyErrorFreeLog().assertTestSuiteResults( 7, 0, 0, 0 );
+    }*/
+
+    public SurefireLauncher multipleMethod( String projectName )
+        throws Exception
+    {
+        return unpack( projectName );
     }
 
 
-    @Test
+    /*@Test
     public void testJunit48()
         throws Exception
     {
         multipleMethod( "junit48-multiple-method-patterns" ).verifyTextInLog( 
RUNNING_WITH_JUNIT48 );
+    }*/
+
+    @Test
+    public void shouldMatchExactClassAndMethod()
+        throws Exception
+    {
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .setTestToRun( "BasicTest#testSuccessTwo" )
+            .executeTest()
+            .verifyErrorFree( 1 )
+            .verifyErrorFreeLog()
+            .verifyTextInLog( "jiras.surefire745.BasicTest#testSuccessTwo" );
+    }
+
+    @Test
+    public void shouldMatchWildcardPackageAndExactClassAndMethod()
+        throws Exception
+    {
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .setTestToRun( "jiras.**.BasicTest#testSuccessTwo" )
+            .executeTest()
+            .verifyErrorFree( 1 )
+            .verifyErrorFreeLog()
+            .verifyTextInLog( "jiras.surefire745.BasicTest#testSuccessTwo" );
+    }
+
+    @Test
+    public void shouldMatchExactClassAndMethodWildcard()
+        throws Exception
+    {
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .maven()
+            .addGoal( "-e" ).addGoal( "-X" )
+            .debugLogging().sysProp( "test", "BasicTest#test*One" )
+            .executeTest()
+            .verifyErrorFree( 1 )
+            .verifyErrorFreeLog()
+            .verifyTextInLog( "jiras.surefire745.BasicTest#testSuccessOne" );
+    }
+
+    @Test
+    public void shouldMatchExactClassAndMethodsWildcard()
+        throws Exception
+    {
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .setTestToRun( "BasicTest#testSuccess*" )
+            .executeTest()
+            .verifyErrorFree( 2 )
+            .verifyErrorFreeLog()
+            .verifyTextInLog( "jiras.surefire745.BasicTest#testSuccessOne" )
+            .verifyTextInLog( "jiras.surefire745.BasicTest#testSuccessTwo" );
+    }
+
+    @Test
+    public void shouldMatchExactClassAndMethodCharacters()
+        throws Exception
+    {
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .setTestToRun( "BasicTest#test???????One" )
+            .executeTest()
+            .verifyErrorFree( 1 )
+            .verifyErrorFreeLog()
+            .verifyTextInLog( "jiras.surefire745.BasicTest#testSuccessOne" );
+    }
+
+    @Test
+    public void shouldMatchExactClassAndMethodsPostfix()
+        throws Exception
+    {
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .setTestToRun( "TestFive#testSuccess???" )
+            .executeTest()
+            .verifyErrorFree( 2 )
+            .verifyErrorFreeLog()
+            .verifyTextInLog( "jiras.surefire745.TestFive#testSuccessOne" )
+            .verifyTextInLog( "jiras.surefire745.TestFive#testSuccessTwo" );
+    }
+
+    @Test
+    public void shouldMatchExactClassAndMethodPostfix()
+        throws Exception
+    {
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .setTestToRun( "TestFive#testSuccess?????" )
+            .executeTest()
+            .verifyErrorFree( 1 )
+            .verifyErrorFreeLog()
+            .verifyTextInLog( "jiras.surefire745.TestFive#testSuccessThree" );
+    }
+
+    @Test
+    public void shouldMatchExactClassAndMultipleMethods()
+        throws Exception
+    {
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .setTestToRun( "TestFive#testSuccessOne+testSuccessThree" )
+            .executeTest()
+            .verifyErrorFree( 2 )
+            .verifyErrorFreeLog()
+            .verifyTextInLog( "jiras.surefire745.TestFive#testSuccessOne" )
+            .verifyTextInLog( "jiras.surefire745.TestFive#testSuccessThree" );
+    }
+
+    @Test
+    public void shouldMatchMultiplePatterns()
+        throws Exception
+    {
+        String test = 
"jiras.surefire745.BasicTest#testSuccessOne+testSuccessTwo"//2
+                + ',' + "jiras.**.TestTwo"//2
+                + ',' + "jiras.surefire745.TestThree#testSuccess*"//2
+                + ',' + "jiras.surefire745.TestFour#testSuccess???"//2
+                + ',' + "jiras.surefire745.*Five#test*One";//1
+
+        multipleMethod( "junit48-multiple-method-patterns" )
+            .setTestToRun( test )
+            .executeTest()
+            .verifyErrorFree( 9 )
+            .verifyErrorFreeLog();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/pom.xml
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/pom.xml
 
b/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/pom.xml
index 023857d..f5ee204 100644
--- 
a/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/pom.xml
+++ 
b/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/pom.xml
@@ -22,22 +22,21 @@
          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>junit4</artifactId>
-  <version>1.0-SNAPSHOT</version>
-  <name>Test for JUnit 4.8.1</name>
-
-
-  <properties>
-    <junitVersion>4.8.1</junitVersion>
-  </properties>
+  <artifactId>jiras-surefire-745</artifactId>
+  <version>1.0</version>
 
   <dependencies>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
-      <version>${junitVersion}</version>
+      <version>4.8.1</version>
       <scope>test</scope>
     </dependency>
   </dependencies>
@@ -55,9 +54,10 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
-        <version>${surefire.version}</version>
         <configuration>
-          
<test>junit4.BasicTest#testSuccessOne+testSuccessTwo,junit4.TestThree#testSuccess*,junit4.TestFour#testSuccess???,junit4.*Five#test*One</test>
+          <!--<test>
+          
iras.surefire745.BasicTest#testSuccessOne+testSuccessTwo,iras.surefire745.TestThree#testSuccess*,iras.surefire745.TestFour#testSuccess???,iras.surefire745.*Five#test*One
+          </test>-->
         </configuration>
         <dependencies>
           <dependency>

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/src/test/java/jiras/surefire745/BasicTest.java
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/src/test/java/jiras/surefire745/BasicTest.java
 
b/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/src/test/java/jiras/surefire745/BasicTest.java
new file mode 100644
index 0000000..44d5978
--- /dev/null
+++ 
b/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/src/test/java/jiras/surefire745/BasicTest.java
@@ -0,0 +1,53 @@
+package jiras.surefire745;
+
+
+/*
+ * 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.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+import static org.junit.Assert.*;
+
+
+public class BasicTest
+{
+    @Rule
+    public final TestName testName = new TestName();
+
+    @Test
+    public void testSuccessOne()
+    {
+        System.out.println( getClass() + "#" + testName.getMethodName() );
+    }
+
+    @Test
+    public void testSuccessTwo()
+    {
+        System.out.println( getClass() + "#" + testName.getMethodName() );
+    }
+
+    @Test
+    public void testFailure()
+    {
+        System.out.println( getClass() + "#" + testName.getMethodName() );
+        fail( );
+    }
+}

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/889caca8/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/src/test/java/jiras/surefire745/TestFive.java
----------------------------------------------------------------------
diff --git 
a/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/src/test/java/jiras/surefire745/TestFive.java
 
b/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/src/test/java/jiras/surefire745/TestFive.java
new file mode 100644
index 0000000..7d88f70
--- /dev/null
+++ 
b/surefire-integration-tests/src/test/resources/junit48-multiple-method-patterns/src/test/java/jiras/surefire745/TestFive.java
@@ -0,0 +1,49 @@
+package jiras.surefire745;
+
+/*
+ * 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.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+
+public class TestFive
+{
+    @Rule
+    public final TestName testName = new TestName();
+
+    @Test
+    public void testSuccessOne()
+    {
+        System.out.println( getClass() + "#" + testName.getMethodName() );
+    }
+
+    @Test
+    public void testSuccessTwo()
+    {
+        System.out.println( getClass() + "#" + testName.getMethodName() );
+    }
+
+    @Test
+    public void testSuccessThree()
+    {
+        System.out.println( getClass() + "#" + testName.getMethodName() );
+    }
+}

Reply via email to