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

Java-Maven Cucumber并行测试:首个浏览器空白页问题排查

问题描述

我有两个独立的Feature文件,用Maven命令执行并行测试时,会打开两个浏览器,但第一个浏览器显示空白页(无URL地址)且无任何操作,第二个浏览器正常启动并成功执行测试,导致第一个Feature文件测试失败、第二个通过。

提示:如果从maven-surefire-plugin中移除<parallel>classesAndMethods</parallel>和<useUnlimitedThreads>true</useUnlimitedThreads>两行,两个Feature文件会串行执行且全部成功,但不符合并行需求。

请问当前配置是否存在问题?


提供的代码内容

第一个Feature文件

Feature: test of a webpage one

  @desktop
  Scenario: Test landing page one
    Given Customer clicks something one 
    When Customer clicks something two
    Then Customer clicks something three

第二个Feature文件

Feature: test of a webpage two

  @desktop
  Scenario: Test landing page two
    Given Customer clicks something one 
    When Customer clicks something two
    Then Customer clicks something three

POM.xml中maven-surefire-plugin配置

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.1.2</version>
    <configuration>
        <includes>
            <include>**/TestRunner.java</include>
        </includes>
        <parallel>classesAndMethods</parallel>
        <useUnlimitedThreads>true</useUnlimitedThreads>
    </configuration>
</plugin>

TestRunner类

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(features="src/test/java/features",
        plugin = {"pretty", "json:target/jsonReports/cucumber-report.json",
                "html:target/jsonReports/cucumber-report.html"},
        glue= {"stepDefs"},
        
        )
public class TestRunner {
}

问题分析与解决方案

当前配置确实存在问题,核心原因是JUnit+Cucumber的组合与Surefire插件的并行策略不兼容,具体问题点如下:

  1. 并行策略不匹配
    Cucumber的TestRunner本质是一个JUnit入口类,本身没有可并行执行的测试方法——它是通过加载Feature文件来运行场景的。Surefire的classesAndMethods策略会尝试并行执行TestRunner内的"方法",导致TestRunner被重复实例化,进而引发WebDriver实例冲突(比如两个线程共用未初始化的驱动,或初始化逻辑未做线程隔离)。

  2. 报告文件冲突
    两个并行线程同时写入同一个JSON/HTML报告文件,会导致文件损坏或内容覆盖,间接影响测试执行稳定性。

  3. 无限制线程的风险
    <useUnlimitedThreads>true</useUnlimitedThreads>会让线程数等于CPU核心数,过多WebDriver实例会消耗大量系统资源,加剧测试不稳定。

修复方案

方案1:改用Cucumber原生并行支持(推荐)

Cucumber本身支持场景/Feature级别的并行执行,无需依赖Surefire的并行配置,步骤如下:

  1. 更新TestRunner配置(Cucumber 6+版本)
    改用JUnit Platform Suite注解,配置原生并行:

    import org.junit.platform.suite.api.ConfigurationParameter;
    import org.junit.platform.suite.api.IncludeEngines;
    import org.junit.platform.suite.api.SelectPackages;
    import org.junit.platform.suite.api.Suite;
    
    import static io.cucumber.junit.platform.engine.Constants.PARALLEL_CONFIG_PROPERTY_NAME;
    import static io.cucumber.junit.platform.engine.Constants.THREAD_COUNT_CONFIG_PROPERTY_NAME;
    import static io.cucumber.junit.platform.engine.Constants.FEATURES_PROPERTY_NAME;
    
    @Suite
    @IncludeEngines("cucumber")
    @SelectPackages("stepDefs")
    @ConfigurationParameter(key = FEATURES_PROPERTY_NAME, value = "src/test/java/features")
    @ConfigurationParameter(key = PARALLEL_CONFIG_PROPERTY_NAME, value = "true")
    @ConfigurationParameter(key = THREAD_COUNT_CONFIG_PROPERTY_NAME, value = "2") // 按需调整线程数
    public class TestRunner {
    }
    
  2. 调整Surefire配置
    移除并行相关配置,只保留TestRunner的包含规则:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.1.2</version>
        <configuration>
            <includes>
                <include>**/TestRunner.java</include>
            </includes>
        </configuration>
    </plugin>
    

方案2:调整Surefire并行策略(适配性差,不推荐)

若坚持用Surefire并行,需将策略改为classes,并为每个Feature创建独立的TestRunner:

  • 为第一个Feature创建TestRunnerOne.java,指定features="src/test/java/features/feature1.feature"
  • 为第二个Feature创建TestRunnerTwo.java,指定features="src/test/java/features/feature2.feature"
  • 修改Surefire配置:
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.1.2</version>
        <configuration>
            <includes>
                <include>**/TestRunner*.java</include>
            </includes>
            <parallel>classes</parallel>
            <threadCount>2</threadCount> <!-- 禁用无限制线程,指定固定数量 -->
        </configuration>
    </plugin>
    

关键补充:WebDriver线程隔离

无论采用哪种并行方案,必须确保每个线程拥有独立的WebDriver实例,可通过ThreadLocal实现:

public class DriverFactory {
    private static final ThreadLocal<WebDriver> DRIVER_THREAD_LOCAL = new ThreadLocal<>();

    public static WebDriver getDriver() {
        if (DRIVER_THREAD_LOCAL.get() == null) {
            ChromeOptions options = new ChromeOptions();
            // 添加必要的浏览器配置
            DRIVER_THREAD_LOCAL.set(new ChromeDriver(options));
        }
        return DRIVER_THREAD_LOCAL.get();
    }

    public static void quitDriver() {
        WebDriver driver = DRIVER_THREAD_LOCAL.get();
        if (driver != null) {
            driver.quit();
            DRIVER_THREAD_LOCAL.remove();
        }
    }
}

在Step Definition中使用DriverFactory.getDriver()获取实例,并在场景结束后调用quitDriver()清理资源。


内容的提问来源于stack exchange,提问作者Word Place

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:25:34