Cucumber多场景执行异常:仅首个场景运行其余被忽略排查
问题描述
在一个Cucumber Feature文件中创建了多个登录场景,单独执行每个场景均正常无报错,但执行整个Feature文件时,仅首个场景执行成功,其余场景步骤被忽略,抛出如下错误:
org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?
问题原因
- Spring默认Bean作用域为单例(Singleton),WebDriver实例一旦创建就会被所有场景复用
- 在
Hooks类的@After方法中调用了webDriver.quit(),销毁了第一个场景的浏览器会话 - 后续场景执行时,注入的仍是已被quit的WebDriver实例,会话已失效,导致报错
解决方案
1. 修改WebDriver配置类,设置Bean为原型作用域
将WebDriver Bean的作用域改为prototype,确保每个场景都会创建全新的WebDriver实例:
@Configuration public class WebDriverLibrary { @Value("${remote.url}") private URL remoteUrl; @Value("${browser}") private String browser; @Bean @Scope("prototype") // 新增:设置原型作用域 public WebDriver getChromeDriver(){ ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments("--remote-allow-origins=*"); return new ChromeDriver(chromeOptions); } }
2. 调整Hooks类,管理每个场景的WebDriver生命周期
通过ApplicationContext获取原型Bean,确保每个场景使用独立的WebDriver,并在场景结束后销毁:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.openqa.selenium.WebDriver; import cucumber.api.Scenario; import cucumber.api.java.After; import cucumber.api.java.Before; import org.springframework.beans.factory.annotation.Value; public class Hooks { @Autowired private ApplicationContext context; private WebDriver webDriver; @Value("${app.url}") private String appUrl; @Before public void InitializeTest(Scenario scenario){ // 每次场景开始时获取新的WebDriver实例 webDriver = context.getBean(WebDriver.class); webDriver.navigate().to(appUrl); webDriver.manage().window().maximize(); } @After public void TearDownTest(Scenario scenario){ if(scenario.isFailed()){ System.out.println(scenario.getName()); } if(webDriver != null){ webDriver.quit(); // 显式销毁当前场景的WebDriver会话 } } }
3. 调整Step Definition中的Page元素初始化
由于WebDriver变为原型,需要确保Page元素绑定当前场景的WebDriver实例,可在Step类中添加初始化逻辑:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.openqa.selenium.WebDriver; import org.openqa.selenium.support.PageFactory; import org.junit.Assert; public class LoginSteps { private WebDriver webDriver; @Autowired private ApplicationContext context; @Autowired private LandingPage landingPage; @Autowired private LoginPage loginPage; @Autowired private SignUpPage signUpPage; @Autowired private QuestionnairePage questionnairePage; @Before // Cucumber的Before注解,在每个场景步骤前执行 public void setUp() { webDriver = context.getBean(WebDriver.class); // 重新初始化所有Page元素,绑定当前WebDriver PageFactory.initElements(webDriver, landingPage); PageFactory.initElements(webDriver, loginPage); PageFactory.initElements(webDriver, signUpPage); PageFactory.initElements(webDriver, questionnairePage); } @Given("User is on Landing Page") public void userIsOnLandingPage() { Assert.assertTrue(landingPage.btnGetStarted.isDisplayed()); } // 其余步骤代码保持不变... }
额外疑问解答
问:未使用webDriver.quit()时浏览器也会关闭,是否需要添加@After注解?
答:
- 必须保留
@After注解并显式调用webDriver.quit(),原因如下:- 浏览器自动关闭通常是测试进程结束后JVM回收WebDriver实例触发的,属于被动回收,无法保证会话资源(如驱动进程、临时文件)完全释放,易引发内存泄漏
webDriver.quit()会主动终止WebDriver会话,彻底销毁浏览器实例和相关资源,确保测试环境干净- 统一的teardown逻辑能避免后续场景受前序场景的残留状态影响,保证测试稳定性
内容的提问来源于stack exchange,提问作者Santhiya s
相关产品推荐
相关产品推荐

