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/09/06 22:58:38 UTC

[07/17] maven-surefire git commit: [SUREFIRE-580] Allow "fail fast" or stop running on first failure

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
index 77f41be..d481bb2 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGExecutor.java
@@ -23,6 +23,8 @@ import org.apache.maven.surefire.booter.ProviderParameterNames;
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.report.RunListener;
 import org.apache.maven.surefire.testng.conf.Configurator;
+import org.apache.maven.surefire.testng.utils.FailFastListener;
+import org.apache.maven.surefire.testng.utils.Stoppable;
 import org.apache.maven.surefire.testset.TestListResolver;
 import org.apache.maven.surefire.testset.TestSetFailedException;
 import org.apache.maven.surefire.util.ReflectionUtils;
@@ -44,6 +46,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.maven.surefire.util.ReflectionUtils.instantiate;
+
 /**
  * Contains utility methods for executing TestNG.
  *
@@ -69,7 +73,7 @@ public class TestNGExecutor
     public static void run( Class<?>[] testClasses, String testSourceDirectory,
                             Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
                             RunListener reportManager, TestNgTestSuite suite, File reportsDirectory,
-                            TestListResolver methodFilter, List<CommandLineOption> mainCliOptions )
+                            TestListResolver methodFilter, List<CommandLineOption> mainCliOptions, boolean isFailFast )
         throws TestSetFailedException
     {
         TestNG testng = new TestNG( true );
@@ -119,7 +123,7 @@ public class TestNGExecutor
 
         testng.setXmlSuites( xmlSuites );
         configurator.configure( testng, options );
-        postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory );
+        postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, isFailFast );
         testng.run();
     }
 
@@ -260,13 +264,14 @@ public class TestNGExecutor
 
     public static void run( List<String> suiteFiles, String testSourceDirectory,
                             Map<String, String> options, // string,string because TestNGMapConfigurator#configure()
-                            RunListener reportManager, TestNgTestSuite suite, File reportsDirectory )
+                            RunListener reportManager, TestNgTestSuite suite, File reportsDirectory,
+                            boolean isFailFast )
         throws TestSetFailedException
     {
         TestNG testng = new TestNG( true );
         Configurator configurator = getConfigurator( options.get( "testng.configurator" ) );
         configurator.configure( testng, options );
-        postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory );
+        postConfigure( testng, testSourceDirectory, reportManager, suite, reportsDirectory, isFailFast );
         testng.setTestSuites( suiteFiles );
         testng.run();
     }
@@ -291,8 +296,8 @@ public class TestNGExecutor
         }
     }
 
-    private static void postConfigure( TestNG testNG, String sourcePath, RunListener reportManager,
-                                       TestNgTestSuite suite, File reportsDirectory )
+    private static void postConfigure( TestNG testNG, String sourcePath, final RunListener reportManager,
+                                       TestNgTestSuite suite, File reportsDirectory, boolean skipAfterFailure )
         throws TestSetFailedException
     {
         // turn off all TestNG output
@@ -301,7 +306,22 @@ public class TestNGExecutor
         TestNGReporter reporter = createTestNGReporter( reportManager, suite );
         testNG.addListener( (Object) reporter );
 
-        // FIXME: use classifier to decide if we need to pass along the source dir (onyl for JDK14)
+        if ( skipAfterFailure )
+        {
+            ClassLoader cl = Thread.currentThread().getContextClassLoader();
+            testNG.addListener( instantiate( cl, "org.apache.maven.surefire.testng.utils.FailFastNotifier",
+                                             Object.class ) );
+            Stoppable stoppable = new Stoppable()
+            {
+                public void pleaseStop()
+                {
+                    reportManager.testExecutionSkippedByUser();
+                }
+            };
+            testNG.addListener( new FailFastListener( stoppable ) );
+        }
+
+        // FIXME: use classifier to decide if we need to pass along the source dir (only for JDK14)
         if ( sourcePath != null )
         {
             testNG.setSourcePath( sourcePath );

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/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 d28d6ac..8777ceb 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
@@ -24,12 +24,16 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.maven.surefire.booter.Command;
+import org.apache.maven.surefire.booter.MasterProcessListener;
+import org.apache.maven.surefire.booter.MasterProcessReader;
 import org.apache.maven.surefire.cli.CommandLineOption;
 import org.apache.maven.surefire.providerapi.AbstractProvider;
 import org.apache.maven.surefire.providerapi.ProviderParameters;
 import org.apache.maven.surefire.report.ReporterConfiguration;
 import org.apache.maven.surefire.report.ReporterFactory;
 import org.apache.maven.surefire.suite.RunResult;
+import org.apache.maven.surefire.testng.utils.FailFastEventsSingleton;
 import org.apache.maven.surefire.testset.TestListResolver;
 import org.apache.maven.surefire.testset.TestRequest;
 import org.apache.maven.surefire.testset.TestSetFailedException;
@@ -37,6 +41,8 @@ import org.apache.maven.surefire.util.RunOrderCalculator;
 import org.apache.maven.surefire.util.ScanResult;
 import org.apache.maven.surefire.util.TestsToRun;
 
+import static org.apache.maven.surefire.booter.MasterProcessCommand.SKIP_SINCE_NEXT_TEST;
+
 /**
  * @author Kristian Rosenvold
  * @noinspection UnusedDeclaration
@@ -58,12 +64,16 @@ public class TestNGProvider
 
     private final RunOrderCalculator runOrderCalculator;
 
-    private List<CommandLineOption> mainCliOptions;
+    private final List<CommandLineOption> mainCliOptions;
+
+    private final MasterProcessReader commandsReader;
 
     private TestsToRun testsToRun;
 
     public TestNGProvider( ProviderParameters booterParameters )
     {
+        // don't start a thread in MasterProcessReader while we are in in-plugin process
+        commandsReader = booterParameters.isInsideFork() ? MasterProcessReader.getReader() : null;
         providerParameters = booterParameters;
         testClassLoader = booterParameters.getTestClassLoader();
         runOrderCalculator = booterParameters.getRunOrderCalculator();
@@ -77,44 +87,55 @@ public class TestNGProvider
     public RunResult invoke( Object forkTestSet )
         throws TestSetFailedException
     {
-
-        final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
-
-        if ( isTestNGXmlTestSuite( testRequest ) )
+        try
         {
-            TestNGXmlTestSuite testNGXmlTestSuite = getXmlSuite();
-            testNGXmlTestSuite.locateTestSets( testClassLoader );
-            if ( forkTestSet != null && testRequest == null )
+            if ( isFailFast() && commandsReader != null )
             {
-                testNGXmlTestSuite.execute( (String) forkTestSet, reporterFactory );
+                registerPleaseStopListener();
             }
-            else
-            {
-                testNGXmlTestSuite.execute( reporterFactory );
-            }
-        }
-        else
-        {
-            if ( testsToRun == null )
+
+            final ReporterFactory reporterFactory = providerParameters.getReporterFactory();
+
+            if ( isTestNGXmlTestSuite( testRequest ) )
             {
-                if ( forkTestSet instanceof TestsToRun )
+                TestNGXmlTestSuite testNGXmlTestSuite = newXmlSuite();
+                testNGXmlTestSuite.locateTestSets( testClassLoader );
+                if ( forkTestSet != null && testRequest == null )
                 {
-                    testsToRun = (TestsToRun) forkTestSet;
+                    testNGXmlTestSuite.execute( (String) forkTestSet, reporterFactory );
                 }
-                else if ( forkTestSet instanceof Class )
+                else
                 {
-                    testsToRun = TestsToRun.fromClass( (Class) forkTestSet );
+                    testNGXmlTestSuite.execute( reporterFactory );
                 }
-                else
+            }
+            else
+            {
+                if ( testsToRun == null )
                 {
-                    testsToRun = scanClassPath();
+                    if ( forkTestSet instanceof TestsToRun )
+                    {
+                        testsToRun = (TestsToRun) forkTestSet;
+                    }
+                    else if ( forkTestSet instanceof Class )
+                    {
+                        testsToRun = TestsToRun.fromClass( (Class) forkTestSet );
+                    }
+                    else
+                    {
+                        testsToRun = scanClassPath();
+                    }
                 }
+                TestNGDirectoryTestSuite suite = newDirectorySuite();
+                suite.execute( testsToRun, reporterFactory );
             }
-            TestNGDirectoryTestSuite suite = getDirectorySuite();
-            suite.execute( testsToRun, reporterFactory );
-        }
 
-        return reporterFactory.close();
+            return reporterFactory.close();
+        }
+        finally
+        {
+            closeCommandsReader();
+        }
     }
 
     boolean isTestNGXmlTestSuite( TestRequest testSuiteDefinition )
@@ -123,18 +144,45 @@ public class TestNGProvider
         return suiteXmlFiles != null && !suiteXmlFiles.isEmpty() && !hasSpecificTests();
     }
 
-    private TestNGDirectoryTestSuite getDirectorySuite()
+    private boolean isFailFast()
+    {
+        return providerParameters.getSkipAfterFailureCount() > 0;
+    }
+
+    private void closeCommandsReader()
+    {
+        if ( commandsReader != null )
+        {
+            commandsReader.stop();
+        }
+    }
+
+    private MasterProcessListener registerPleaseStopListener()
+    {
+        MasterProcessListener listener = new MasterProcessListener()
+        {
+            public void update( Command command )
+            {
+                FailFastEventsSingleton.getInstance().setSkipOnNextTest();
+            }
+        };
+        commandsReader.addListener( SKIP_SINCE_NEXT_TEST, listener );
+        return listener;
+    }
+
+    private TestNGDirectoryTestSuite newDirectorySuite()
     {
         return new TestNGDirectoryTestSuite( testRequest.getTestSourceDirectory().toString(), providerProperties,
                                              reporterConfiguration.getReportsDirectory(), createMethodFilter(),
-                                             runOrderCalculator, scanResult, mainCliOptions );
+                                             runOrderCalculator, scanResult, mainCliOptions, isFailFast() );
     }
 
-    private TestNGXmlTestSuite getXmlSuite()
+    private TestNGXmlTestSuite newXmlSuite()
     {
-        return new TestNGXmlTestSuite( testRequest.getSuiteXmlFiles(), testRequest.getTestSourceDirectory().toString(),
+        return new TestNGXmlTestSuite( testRequest.getSuiteXmlFiles(),
+                                       testRequest.getTestSourceDirectory().toString(),
                                        providerProperties,
-                                       reporterConfiguration.getReportsDirectory() );
+                                       reporterConfiguration.getReportsDirectory(), isFailFast() );
     }
 
     @SuppressWarnings( "unchecked" )
@@ -144,7 +192,7 @@ public class TestNGProvider
         {
             try
             {
-                return getXmlSuite().locateTestSets( testClassLoader ).keySet();
+                return newXmlSuite().locateTestSets( testClassLoader ).keySet();
             }
             catch ( TestSetFailedException e )
             {

http://git-wip-us.apache.org/repos/asf/maven-surefire/blob/2a944f06/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
----------------------------------------------------------------------
diff --git a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
index 552e482..bf105fe 100644
--- a/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
+++ b/surefire-providers/surefire-testng/src/main/java/org/apache/maven/surefire/testng/TestNGXmlTestSuite.java
@@ -49,6 +49,8 @@ public class TestNGXmlTestSuite
 
     private final File reportsDirectory;
 
+    private final boolean isFailFast;
+
     // Not really used
     private Map<File, String> testSets;
 
@@ -57,15 +59,13 @@ public class TestNGXmlTestSuite
      * xml file(s). The XML files are suite definitions files according to TestNG DTD.
      */
     public TestNGXmlTestSuite( List<File> suiteFiles, String testSourceDirectory, Map<String, String> confOptions,
-                               File reportsDirectory )
+                               File reportsDirectory, boolean isFailFast )
     {
         this.suiteFiles = suiteFiles;
-
         this.options = confOptions;
-
         this.testSourceDirectory = testSourceDirectory;
-
         this.reportsDirectory = reportsDirectory;
+        this.isFailFast = isFailFast;
     }
 
     public void execute( ReporterFactory reporterManagerFactory )
@@ -80,8 +80,8 @@ public class TestNGXmlTestSuite
         ConsoleOutputCapture.startCapture( (ConsoleOutputReceiver) reporter );
 
         TestNGDirectoryTestSuite.startTestSuite( reporter, this );
-        TestNGExecutor.run( this.suiteFilePaths, this.testSourceDirectory, this.options, reporter, this,
-                            reportsDirectory );
+        TestNGExecutor.run( suiteFilePaths, testSourceDirectory, options, reporter, this, reportsDirectory,
+                            isFailFast );
         TestNGDirectoryTestSuite.finishTestSuite( reporter, this );
     }