配置Selenium Grid+Cucumber+TestNG时遭遇SessionNotCreatedException
问题描述
我正在搭建结合Cucumber与TestNG的Selenium Grid自动化测试框架,运行测试时抛出错误:
org.openqa.selenium.SessionNotCreatedException: Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure.
浏览器能正常启动,但无法加载目标应用,启动后显示空白页面:
相关代码
DriverFactory类代码
public class DriverFactory { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private DesiredCapabilities desiredCapabilities; protected static ThreadLocal<RemoteWebDriver> driver = new ThreadLocal<RemoteWebDriver>(); public DriverFactory() { desiredCapabilities = new DesiredCapabilities(); } public WebDriver getDriver() { return driver.get(); } public void initializeBrowser(String browserType) throws MalformedURLException { if (browserType.equalsIgnoreCase("chrome")) { ChromeOptions chromeOptions = new ChromeOptions(); driver.set(new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), chromeOptions)); desiredCapabilities.setPlatform(Platform.ANY); desiredCapabilities.setBrowserName("chrome"); } } public WebDriver setAndGetDriver() throws MalformedURLException { WebDriverManager.chromedriver().setup(); initializeBrowser("chrome"); return getDriver(); } }
步骤定义类代码
public FirstTestSteps(Hooks hooks) throws MalformedURLException { localHooks = hooks; localHooks.setup(); driver = localHooks.getDriver(); endpointData = ApiSetup.getData(); loginPage = new LoginPage(driver); landingPage = new LandingPage(driver); cartPage = new CartPage(driver); checkoutInfoPage = new CheckoutInfoPage(driver); } @When("user navigates to portal") public void userNavigates() { loginPage.accessUrl(); }
Hub与节点启动命令
java -jar selenium-server-4.10.0.jar hub java -jar selenium-server-4.10.0.jar node --detect-drivers true --publish-events tcp://192.168.1.39:4442 --subscribe-events tcp://192.168.1.39:4443 java -jar selenium-server-4.10.0.jar node --port 5556 --detect-drivers true
完整堆栈跟踪
org.openqa.selenium.SessionNotCreatedException: Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure. Host info: host: 'ADMINRG-77I9HE9', ip: '192.168.1.39' Build info: version: '4.10.0', revision: 'c14d967899' System info: os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '18.0.2.1' Driver info: org.openqa.selenium.remote.RemoteWebDriver Command: [null, newSession {capabilities=[Capabilities {acceptInsecureCerts: true, browserName: chrome, goog:chromeOptions: {args: [--remote-allow-origins=*, start-maximized], extensions: []}, platformName: Windows 10}]}] Capabilities {acceptInsecureCerts: true, browserName: chrome, goog:chromeOptions: {args: [--remote-allow-origins=*, start-maximized], extensions: []}, platformName: Windows 10} at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:549) at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:227) at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:154) at org.openqa.selenium.remote.RemoteWebDriver.<init>(RemoteWebDriver.java:134) at com.gridpro.hooks.DriverFactory.initializeBrowser(DriverFactory.java:49) at com.gridpro.hooks.DriverFactory.setAndGetDriver(DriverFactory.java:63) at com.gridpro.hooks.Hooks.setup(Hooks.java:32) at com.gridpro.definitions.FirstTestSteps.<init>(FirstTestSteps.java:34) at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:483) at org.picocontainer.injectors.AbstractInjector.newInstance(AbstractInjector.java:145) at org.picocontainer.injectors.ConstructorInjector$1.run(ConstructorInjector.java:342) at org.picocontainer.injectors.AbstractInjector$ThreadLocalCyclicDependencyGuard.observe(AbstractInjector.java:270) at org.picocontainer.injectors.ConstructorInjector.getComponentInstance(ConstructorInjector.java:364) at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.getComponentInstance(AbstractInjectionFactory.java:56) at org.picocontainer.behaviors.AbstractBehavior.getComponentInstance(AbstractBehavior.java:64) at org.picocontainer.behaviors.Stored.getComponentInstance(Stored.java:91) at org.picocontainer.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:699) at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:647) at org.picocontainer.DefaultPicoContainer.getComponent(DefaultPicoContainer.java:678) at io.cucumber.picocontainer.PicoFactory.getInstance(PicoFactory.java:54) at io.cucumber.java.AbstractGlueDefinition.invokeMethod(AbstractGlueDefinition.java:47) at io.cucumber.java.JavaStepDefinition.execute(JavaStepDefinition.java:29) at io.cucumber.core.runner.CoreStepDefinition.execute(CoreStepDefinition.java:66) at io.cucumber.core.runner.PickleStepDefinitionMatch.runStep(PickleStepDefinitionMatch.java:63) at io.cucumber.core.runner.ExecutionMode$1.execute(ExecutionMode.java:10) at io.cucumber.core.runner.TestStep.executeStep(TestStep.java:84) at io.cucumber.core.runner.TestStep.run(TestStep.java:56) at io.cucumber.core.runner.PickleStepTestStep.run(PickleStepTestStep.java:51) at io.cucumber.core.runner.TestCase.run(TestCase.java:84) at io.cucumber.core.runner.Runner.runPickle(Runner.java:75) at io.cucumber.testng.TestNGCucumberRunner.lambda$runScenario$1(TestNGCucumberRunner.java:132) at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$5(CucumberExecutionContext.java:137) at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23) at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:137) at io.cucumber.testng.TestNGCucumberRunner.runScenario(TestNGCucumberRunner.java:129) at io.cucumber.testng.AbstractTestNGCucumberTests.runScenario(AbstractTestNGCucumberTests.java:35) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) at java.base/java.lang.reflect.Method.invoke(Method.java:577) at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:139) at org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:664) at org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:227) at org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:50) at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:957) at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:200) at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:148) at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:128) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:833) Caused by: java.lang.NoSuchMethodError: 'com.google.common.collect.ImmutableMap com.google.common.collect.ImmutableMap.of(java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object, java.lang.Object)' at org.openqa.selenium.chrome.AddHasCasting.getAdditionalCommands(AddHasCasting.java:37) at org.openqa.selenium.remote.Dialect.lambda$bindAdditionalCommands$1(Dialect.java:62) at java.base/java.lang.Iterable.forEach(Iterable.java:75) at org.openqa.selenium.remote.Dialect.bindAdditionalCommands(Dialect.java:60) at org.openqa.selenium.remote.Dialect.access$100(Dialect.java:26) at org.openqa.selenium.remote.Dialect$1.getCommandCodec(Dialect.java:30) at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:165) at org.openqa.selenium.remote.TracedCommandExecutor.execute(TracedCommandExecutor.java:51) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:531) ... 50 more
解决方案
从堆栈跟踪的Caused by信息可明确,核心问题是Guava版本不兼容,旧版Guava缺少Selenium 4.10.0所需的方法,导致会话创建失败。
具体修复步骤
- 统一Guava依赖版本
Selenium 4.10.0对应兼容的Guava版本为31.1-jre,在项目依赖中明确指定该版本:
- Maven(pom.xml):
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency>
- Gradle(build.gradle):
implementation 'com.google.guava:guava:31.1-jre'
- 清理依赖冲突
使用依赖分析工具排查是否有其他依赖引入旧版Guava,例如Maven执行:
mvn dependency:tree | grep guava
找到冲突依赖后,在对应依赖中排除旧版Guava:
<dependency> <groupId>冲突依赖的groupId</groupId> <artifactId>冲突依赖的artifactId</artifactId> <version>版本号</version> <exclusions> <exclusion> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </exclusion> </exclusions> </dependency>
- 优化DriverFactory代码
当前代码中DesiredCapabilities未正确关联到ChromeOptions,且Selenium 4推荐直接使用ChromeOptions,同时Grid场景下无需本地管理驱动,修改initializeBrowser方法:
public void initializeBrowser(String browserType) throws MalformedURLException { if (browserType.equalsIgnoreCase("chrome")) { ChromeOptions chromeOptions = new ChromeOptions(); // 添加必要启动参数 chromeOptions.addArguments("--remote-allow-origins=*", "start-maximized"); // 直接用ChromeOptions创建RemoteWebDriver driver.set(new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), chromeOptions)); } }
移除setAndGetDriver中的WebDriverManager.chromedriver().setup(),Grid节点会自动管理驱动版本。
- 修正Grid节点启动命令
启动节点时明确指定Hub地址,避免自动发现异常:
java -jar selenium-server-4.10.0.jar node --hub http://localhost:4444/wd/hub --detect-drivers true
内容的提问来源于stack exchange,提问作者nikhil udgirkar
相关产品推荐
相关产品推荐

