Q15 of 21 · BDD / Cucumber
How do you run Cucumber scenarios in parallel, and what are the key pitfalls?
Short answer
Short answer: Cucumber supports parallel execution via the parallel plugin (Maven Surefire/Failsafe), JUnit 5 parallel execution config, or native JS worker threads. Pitfalls: shared mutable state, shared test data, and non-thread-safe WebDriver instances.
Detail
Java — Maven Surefire parallel:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<parallel>methods</parallel>
<threadCount>4</threadCount>
</configuration>
</plugin>
Or use the Cucumber parallel plugin to split by feature or scenario:
@CucumberOptions(plugin = {"parallel"})
JavaScript — @cucumber/cucumber parallel flag:
cucumber-js --parallel 4
Key pitfalls:
1. Shared WebDriver / page instance: Each parallel scenario needs its own driver or browser context. Don't share a driver between threads.
// Thread-local driver (Java)
private static final ThreadLocal<WebDriver> driver = new ThreadLocal<>();
@Before
public void setUp() { driver.set(new ChromeDriver()); }
@After
public void tearDown() { driver.get().quit(); driver.remove(); }
2. Shared test data: If two scenarios use the same user account or the same DB row, they'll interfere. Fix: unique test data per scenario (random or scenario-name-scoped IDs).
3. Shared state in step definition classes: Static fields shared across threads cause race conditions. Use DI (PicoContainer creates a new instance per scenario per thread) or the World object in JS.
4. Report merging: Parallel runs produce multiple JSON/XML reports. Merge them with cucumber-results-aggregator or the Allure framework before publishing.
// EXAMPLE
// Thread-safe driver management for parallel Cucumber
public class DriverManager {
private static final ThreadLocal<WebDriver> tlDriver = new ThreadLocal<>();
public static WebDriver getDriver() { return tlDriver.get(); }
public static void initDriver() {
tlDriver.set(new ChromeDriver());
}
public static void quitDriver() {
if (tlDriver.get() != null) {
tlDriver.get().quit();
tlDriver.remove();
}
}
}