You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行Cucumber Feature时Chrome启动两次的技术求助

解决Cucumber + Selenium中Chrome Driver启动两次的问题

看起来你遇到了Cucumber Hook执行范围的典型问题——因为Cucumber的@Before注解默认是全局生效的,只要在Glue路径下的所有@Before方法,不管属于哪个StepDef,运行任何Feature时都会被执行。你两个StepDef里的@Before都各自初始化了Chrome Driver并打开不同URL,自然会启动两个独立的会话。

下面是几个针对性的解决方案,按实践优先级排序:

方案1:用标签限定@Before的执行范围

这是最直接的解决方式,通过标签让@Before只在匹配的Feature运行时触发:

  1. 给Feature文件添加专属标签:
    打开你的MOP和MOS Feature文件,分别加上对应标签:
    # MOP Features下的Feature文件
    @MOP
    Feature: MOP功能测试
      Scenario: 验证MOP首页加载
        Given 我打开MOP网站
        ...
    
    # MOS Features下的Feature文件
    @MOS
    Feature: MOS功能测试
      Scenario: 验证MOS首页加载
        Given 我打开MOS网站
        ...
    
  2. 修改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");
    }
    
  3. 运行时指定标签:
    在IntelliJ的运行配置中,找到"Cucumber Java"配置的"Tags"选项,输入@MOP或@MOS,这样运行时只会执行对应标签的Hook和StepDef,不会触发另一个的@Before。

方案2:统一用全局Hook管理Driver生命周期

更规范的实践是把Driver初始化逻辑抽离到单独的Hook类,避免每个StepDef重复写@Before:

  1. 创建全局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
            }
        }
    }
    
  2. 移除StepDef中的@Before:
    删除MOPStepDefs和MOSStepDefs里的@Before方法,所有Driver初始化都交给全局Hook处理。
  3. 统一获取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:53:40