运行Cucumber Feature时Chrome启动两次的技术求助
解决Cucumber + Selenium中Chrome Driver启动两次的问题
看起来你遇到了Cucumber Hook执行范围的典型问题——因为Cucumber的@Before注解默认是全局生效的,只要在Glue路径下的所有@Before方法,不管属于哪个StepDef,运行任何Feature时都会被执行。你两个StepDef里的@Before都各自初始化了Chrome Driver并打开不同URL,自然会启动两个独立的会话。
下面是几个针对性的解决方案,按实践优先级排序:
方案1:用标签限定@Before的执行范围
这是最直接的解决方式,通过标签让@Before只在匹配的Feature运行时触发:
- 给Feature文件添加专属标签:
打开你的MOP和MOS Feature文件,分别加上对应标签:# MOP Features下的Feature文件 @MOP Feature: MOP功能测试 Scenario: 验证MOP首页加载 Given 我打开MOP网站 ...# MOS Features下的Feature文件 @MOS Feature: MOS功能测试 Scenario: 验证MOS首页加载 Given 我打开MOS网站 ... - 修改StepDef里的@Before注解:
给每个@Before加上标签限定,让它只处理对应标签的Feature:// MOPStepDefs.java @Before("@MOP") // 仅当运行带@MOP标签的Feature时执行 public void setupMOP() { driver = new ChromeDriver(); driver.get("https://mop-website-url"); } // MOSStepDefs.java @Before("@MOS") // 仅当运行带@MOS标签的Feature时执行 public void setupMOS() { driver = new ChromeDriver(); driver.get("https://mos-website-url"); } - 运行时指定标签:
在IntelliJ的运行配置中,找到"Cucumber Java"配置的"Tags"选项,输入@MOP或@MOS,这样运行时只会执行对应标签的Hook和StepDef,不会触发另一个的@Before。
方案2:统一用全局Hook管理Driver生命周期
更规范的实践是把Driver初始化逻辑抽离到单独的Hook类,避免每个StepDef重复写@Before:
- 创建全局Hook类:
在stepdefs目录下新建Hooks.java,集中管理Driver的创建和销毁:import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import io.cucumber.java.After; import io.cucumber.java.Before; import io.cucumber.java.Scenario; public class Hooks { private static WebDriver driver; @Before public void setupDriver(Scenario scenario) { // 根据当前Scenario的标签判断要打开的URL if (scenario.getSourceTagNames().contains("@MOP")) { driver = new ChromeDriver(); driver.get("https://mop-website-url"); } else if (scenario.getSourceTagNames().contains("@MOS")) { driver = new ChromeDriver(); driver.get("https://mos-website-url"); } // 把Driver传递给Page类或StepDef(可以用静态方法或依赖注入) PageBase.setDriver(driver); } @After public void teardownDriver() { if (driver != null) { driver.quit(); // 确保每次运行后关闭Driver } } } - 移除StepDef中的@Before:
删除MOPStepDefs和MOSStepDefs里的@Before方法,所有Driver初始化都交给全局Hook处理。 - 统一获取Driver:
让所有Page类和StepDef通过PageBase.getDriver()这类方式获取Driver实例,避免重复创建。
方案3:调整Glue路径(补充你尝试过的操作)
如果你之前调整Glue没用,可能是因为路径还是包含了两个StepDef包。可以尝试:
- 运行单个Feature时,在IntelliJ的运行配置中,把Glue路径指定为对应StepDef的包(比如运行MOP Feature时,Glue设为
stepdefs.MOPStepDefs),这样Cucumber只会扫描这个包下的代码,不会加载另一个StepDef的@Before。 - 不过这种方式灵活性较差,适合临时测试,长期还是推荐方案1或2。
额外注意点
- 尽量用静态Driver实例或单例模式,避免意外创建多个Driver。
- 一定要加
@After注解关闭Driver,防止残留Chrome进程占用资源。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

