This is an automated email from the ASF dual-hosted git repository.

benweidig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit 4a38af4394d0d5ac38503b4aceb1f19494808b1f
Author: Ben Weidig <[email protected]>
AuthorDate: Sun Jul 26 14:31:17 2026 +0200

    TAP5-2817: SeleniumTestCase improve error handling during testStartup
---
 .../apache/tapestry5/test/SeleniumTestCase.java    | 216 ++++++++++++---------
 1 file changed, 125 insertions(+), 91 deletions(-)

diff --git 
a/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java 
b/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
index fe4dfef27..ec7bc2891 100644
--- 
a/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
+++ 
b/tapestry-test/src/main/java/org/apache/tapestry5/test/SeleniumTestCase.java
@@ -246,128 +246,162 @@ public abstract class SeleniumTestCase extends Assert 
implements Selenium
 
         final Runnable stopWebServer = launchWebServer(container, 
webAppFolder, contextPath, port, sslPort);
 
-        FirefoxDriverManager.firefoxdriver().setup();
+        FirefoxDriver driver = null;
 
-        DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
-        FirefoxOptions options = new FirefoxOptions(desiredCapabilities); 
-
-        // TAP5-2819: Run headless on CI
-        if (Boolean.parseBoolean(System.getProperty("ci", "false")))
+        try
         {
-            options.addArguments("-headless", "--width=1920", "--height=1080");
-        }
+            FirefoxDriverManager.firefoxdriver().setup();
 
-        File ffProfileTemplate = new 
File(TapestryRunnerConstants.MODULE_BASE_DIR, 
"src/test/conf/ff_profile_template");
-        // From 
https://forums.parasoft.com/discussion/5682/using-selenium-with-firefox-snap-ubuntu
-        String osName = System.getProperty("os.name");
-        String snapProfileRoot = osName.contains("Linux") && new 
File("/snap/firefox").exists()
-                ? createProfileRootInUserHome()
-                : null;
+            DesiredCapabilities desiredCapabilities = new 
DesiredCapabilities();
+            FirefoxOptions options = new FirefoxOptions(desiredCapabilities); 
 
-        FirefoxProfile profile;
-        if (ffProfileTemplate.isDirectory())
-        {
-            LOGGER.info("Loading Firefox profile from: {}", ffProfileTemplate);
-            profile = new FirefoxProfile(ffProfileTemplate);
-        }
-        else if (snapProfileRoot != null)
-        {
-            File snapSafeDir = new File(snapProfileRoot, "tmp-profile");
-            snapSafeDir.mkdirs();
-            LOGGER.info("Creating Snap-compatible Firefox profile in: {}", 
snapSafeDir);
+            // TAP5-2819: Run headless on CI
+            if (Boolean.parseBoolean(System.getProperty("ci", "false")))
+            {
+                options.addArguments("-headless", "--width=1920", 
"--height=1080");
+            }
 
-            profile = new FirefoxProfile(snapSafeDir);
-            profile.setPreference("intl.accept_languages", "en,fr,de");
-        }
-        else
-        {
-            LOGGER.info("Using default Firefox profile");
-            profile = new FirefoxProfile();
-            profile.setPreference("intl.accept_languages", "en,fr,de");
-        }
+            File ffProfileTemplate = new 
File(TapestryRunnerConstants.MODULE_BASE_DIR, 
"src/test/conf/ff_profile_template");
+            // From 
https://forums.parasoft.com/discussion/5682/using-selenium-with-firefox-snap-ubuntu
+            String osName = System.getProperty("os.name");
+            String snapProfileRoot = osName.contains("Linux") && new 
File("/snap/firefox").exists()
+                    ? createProfileRootInUserHome()
+                    : null;
 
-        options.setProfile(profile);
+            FirefoxProfile profile;
+            if (ffProfileTemplate.isDirectory())
+            {
+                LOGGER.info("Loading Firefox profile from: {}", 
ffProfileTemplate);
+                profile = new FirefoxProfile(ffProfileTemplate);
+            }
+            else if (snapProfileRoot != null)
+            {
+                File snapSafeDir = new File(snapProfileRoot, "tmp-profile");
+                snapSafeDir.mkdirs();
+                LOGGER.info("Creating Snap-compatible Firefox profile in: {}", 
snapSafeDir);
 
-        FirefoxDriver driver = snapProfileRoot != null
-                ? new FirefoxDriver(createGeckoDriverService(snapProfileRoot), 
options)
-                : new FirefoxDriver(options);
+                profile = new FirefoxProfile(snapSafeDir);
+                profile.setPreference("intl.accept_languages", "en,fr,de");
+            }
+            else
+            {
+                LOGGER.info("Using default Firefox profile");
+                profile = new FirefoxProfile();
+                profile.setPreference("intl.accept_languages", "en,fr,de");
+            }
 
-        // Implicit waiting can interfere with WebDriverWait
-        // driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10L));
+            options.setProfile(profile);
 
-        CommandProcessor webDriverCommandProcessor = new 
WebDriverCommandProcessor(baseURL, driver);
+            driver = snapProfileRoot != null
+                    ? new 
FirefoxDriver(createGeckoDriverService(snapProfileRoot), options)
+                    : new FirefoxDriver(options);
 
-        final ErrorReporterImpl errorReporter = new ErrorReporterImpl(driver, 
testContext);
+            // Implicit waiting can interfere with WebDriverWait
+            // 
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10L));
 
-        ErrorReportingCommandProcessor commandProcessor = new 
ErrorReportingCommandProcessor(webDriverCommandProcessor,
-                errorReporter);
+            CommandProcessor webDriverCommandProcessor = new 
WebDriverCommandProcessor(baseURL, driver);
 
-        Selenium selenium = new WebDriverBackedSelenium(driver, baseURL);
+            final ErrorReporterImpl errorReporter = new 
ErrorReporterImpl(driver, testContext);
 
-        testContext.setAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE, 
baseURL);
-        testContext.setAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE, 
selenium);
-        
testContext.setAttribute(TapestryTestConstants.ERROR_REPORTER_ATTRIBUTE, 
errorReporter);
-        
testContext.setAttribute(TapestryTestConstants.COMMAND_PROCESSOR_ATTRIBUTE, 
commandProcessor);
+            ErrorReportingCommandProcessor commandProcessor = new 
ErrorReportingCommandProcessor(webDriverCommandProcessor,
+                    errorReporter);
 
-        testContext.setAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE, new 
Runnable()
-        {
-            @Override
-            public void run()
+            Selenium selenium = new WebDriverBackedSelenium(driver, baseURL);
+
+            testContext.setAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE, 
baseURL);
+            testContext.setAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE, 
selenium);
+            
testContext.setAttribute(TapestryTestConstants.ERROR_REPORTER_ATTRIBUTE, 
errorReporter);
+            
testContext.setAttribute(TapestryTestConstants.COMMAND_PROCESSOR_ATTRIBUTE, 
commandProcessor);
+
+            testContext.setAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE, 
new Runnable()
             {
-                try
+                @Override
+                public void run()
                 {
-                    LOGGER.info("Shutting down selenium client ...");
-
                     try
                     {
-                        selenium.stop();
-                    } catch (RuntimeException e)
-                    {
-                        LOGGER.error("Selenium client shutdown failure.", e);
-                    }
+                        LOGGER.info("Shutting down selenium client ...");
+
+                        try
+                        {
+                            selenium.stop();
+                        } catch (RuntimeException e)
+                        {
+                            LOGGER.error("Selenium client shutdown failure.", 
e);
+                        }
 
-                    LOGGER.info("Shutting down webdriver ...");
+                        LOGGER.info("Shutting down webdriver ...");
 
-                    try
-                    {
-                        if (webDriver != null) { // is sometimes null... but 
why?
-                            webDriver.quit();
+                        try
+                        {
+                            if (webDriver != null) { // is sometimes null... 
but why?
+                                webDriver.quit();
+                            }
+                        } catch (RuntimeException e)
+                        {
+                            LOGGER.error("Webdriver shutdown failure.", e);
                         }
-                    } catch (RuntimeException e)
-                    {
-                        LOGGER.error("Webdriver shutdown failure.", e);
-                    }
 
-                    LOGGER.info("Shutting down selenium server ...");
+                        LOGGER.info("Shutting down selenium server ...");
 
-                    LOGGER.info("Shutting web server ...");
+                        LOGGER.info("Shutting web server ...");
 
-                    try
-                    {
-                        stopWebServer.run();
-                    } catch (RuntimeException e)
+                        try
+                        {
+                            stopWebServer.run();
+                        } catch (RuntimeException e)
+                        {
+                            LOGGER.error("Web server shutdown failure.", e);
+                        }
+
+                        // Output, at the end of the Test, any html capture or 
screen shots (this makes it much easier
+                        // to locate them at the end of the run; there's such 
a variance on where they end up based
+                        // on whether the tests are running from inside an IDE 
or via one of the command line
+                        // builds.
+
+                        errorReporter.writeOutputPaths();
+                    } finally
                     {
-                        LOGGER.error("Web server shutdown failure.", e);
+                        
testContext.removeAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE);
+                        
testContext.removeAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE);
+                        
testContext.removeAttribute(TapestryTestConstants.ERROR_REPORTER_ATTRIBUTE);
+                        
testContext.removeAttribute(TapestryTestConstants.COMMAND_PROCESSOR_ATTRIBUTE);
+                        
testContext.removeAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE);
+                        
testContext.removeAttribute(TapestryTestConstants.PAGE_LOAD_TIMEOUT_PARAMETER);
+                        
testContext.removeAttribute(TapestryTestConstants.WEBDRIVER_WAIT_TIMEOUT_PARAMETER);
                     }
+                }
+            });
+        } catch (Exception ex)
+        {
+            // Nothing has been stored in the test context yet, so 
testShutdown() has no way
+            // of cleaning up after a failure here. Release the browser and 
the web server now; otherwise
+            // the port stays bound for the rest of the JVM's life and every 
later <test> in the suite
+            // fails with "Failed to bind".
 
-                    // Output, at the end of the Test, any html capture or 
screen shots (this makes it much easier
-                    // to locate them at the end of the run; there's such a 
variance on where they end up based
-                    // on whether the tests are running from inside an IDE or 
via one of the command line
-                    // builds.
+            LOGGER.error("Startup of the integration test environment failed; 
releasing resources.", ex);
 
-                    errorReporter.writeOutputPaths();
-                } finally
+            if (driver != null)
+            {
+                try
+                {
+                    driver.quit();
+                } catch (RuntimeException e)
                 {
-                    
testContext.removeAttribute(TapestryTestConstants.BASE_URL_ATTRIBUTE);
-                    
testContext.removeAttribute(TapestryTestConstants.SELENIUM_ATTRIBUTE);
-                    
testContext.removeAttribute(TapestryTestConstants.ERROR_REPORTER_ATTRIBUTE);
-                    
testContext.removeAttribute(TapestryTestConstants.COMMAND_PROCESSOR_ATTRIBUTE);
-                    
testContext.removeAttribute(TapestryTestConstants.SHUTDOWN_ATTRIBUTE);
-                    
testContext.removeAttribute(TapestryTestConstants.PAGE_LOAD_TIMEOUT_PARAMETER);
-                    
testContext.removeAttribute(TapestryTestConstants.WEBDRIVER_WAIT_TIMEOUT_PARAMETER);
+                    LOGGER.error("Webdriver shutdown failure.", e);
                 }
             }
-        });
+
+            try
+            {
+                stopWebServer.run();
+            } catch (RuntimeException e)
+            {
+                LOGGER.error("Web server shutdown failure.", e);
+            }
+
+            throw ex;
+        }
     }
     
     private static String createProfileRootInUserHome() {

Reply via email to