无需过时cucumber-jvm-parallel-plugin,单Runner类用Fork并行测试可行吗?
Absolutely, you can run each Cucumber feature in a separate Maven fork without relying on the deprecated cucumber-jvm-parallel-plugin. Here's a practical, modern approach using Cucumber's native integrations with JUnit 5 (or TestNG) combined with Maven Surefire's forking capabilities:
Prerequisites
- Cucumber 7.x+ (for improved JUnit Platform/TestNG integration)
- Maven Surefire Plugin 3.0.0+
- JUnit 5 (preferred) or TestNG (your fallback option)
Option 1: JUnit 5 + Cucumber JUnit Platform Engine
This is the most streamlined setup, as Cucumber's JUnit Platform engine natively exposes each feature as a distinct test "class" that Surefire can split into forks.
Step 1: Update Dependencies
Add these to your pom.xml:
<dependencies> <!-- Cucumber Core --> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-java</artifactId> <version>7.14.0</version> <scope>test</scope> </dependency> <!-- Cucumber-JUnit 5 Integration --> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-junit-platform-engine</artifactId> <version>7.14.0</version> <scope>test</scope> </dependency> <!-- JUnit 5 Suite & Engine --> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-suite-api</artifactId> <version>1.10.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency> </dependencies>
Step 2: Create a Single Suite Runner
Instead of multiple runners, make one suite that includes all your features:
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.FEATURES_PROPERTY_NAME; import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME; @Suite @IncludeEngines("cucumber") @SelectPackages("com.your.project.steps") // Path to your step definitions @ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.your.project.steps") @ConfigurationParameter(key = FEATURES_PROPERTY_NAME, value = "src/test/resources/features") // Path to your .feature files public class CucumberTestSuite {}
Step 3: Configure Surefire for Forked Execution
Tell Surefire to split features across separate JVM forks by targeting the "classes" level (each feature is treated as a class by the JUnit Platform engine):
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.2</version> <configuration> <parallel>classes</parallel> <!-- Split by Cucumber features (exposed as classes) --> <forkCount>4</forkCount> <!-- Number of parallel JVM forks (match your feature count or desired parallelism) --> <reuseForks>true</reuseForks> <!-- Reuse forks to speed up execution (set to false for fresh JVMs every time) --> <systemPropertyVariables> <cucumber.plugin>pretty,html:target/cucumber-reports</cucumber.plugin> </systemPropertyVariables> </configuration> </plugin> </plugins> </build>
Option 2: TestNG Alternative
If you prefer to stick with TestNG, use Cucumber's TestNG integration to expose each feature as a separate test, then configure Surefire to fork these tests.
Step 1: Update Dependencies
Add TestNG-specific Cucumber dependencies:
<dependencies> <!-- Cucumber TestNG Integration --> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-testng</artifactId> <version>7.14.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.8.0</version> <scope>test</scope> </dependency> <!-- Keep your existing Cucumber core dependency --> </dependencies>
Step 2: Create a TestNG Runner
import io.cucumber.testng.AbstractTestNGCucumberTests; import io.cucumber.testng.CucumberOptions; @CucumberOptions( features = "src/test/resources/features", glue = "com.your.project.steps", plugin = {"pretty", "html:target/cucumber-reports"} ) public class CucumberTestNGSuite extends AbstractTestNGCucumberTests {}
Step 3: Configure Surefire & TestNG
Create a testng.xml file:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Cucumber Suite" parallel="tests" thread-count="4"> <test name="Cucumber Features"> <classes> <class name="com.your.project.CucumberTestNGSuite"/> </classes> </test> </suite>
Update Surefire in pom.xml:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.2</version> <configuration> <parallel>tests</parallel> <!-- Split by individual Cucumber features (exposed as TestNG tests) --> <forkCount>4</forkCount> <!-- Number of parallel JVM forks --> <reuseForks>true</reuseForks> <suiteXmlFiles> <suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile> </suiteXmlFiles> </configuration> </plugin>
Verify Execution
Run mvn test and check the logs—you'll see lines indicating each feature starts in a separate JVM fork (look for Forking command line: entries). Each feature runs in complete isolation, just like with the deprecated plugin.
内容的提问来源于stack exchange,提问作者VladislavShcherba




