Advanced Chapter 15 · 11 min read

Parallel Execution

Run Cucumber scenarios in parallel to cut execution time — thread-safe drivers, TestNG parallel DataProvider, and Behave parallel plugins.

Parallel Execution

Running scenarios sequentially is slow. Parallel execution runs multiple scenarios simultaneously, dramatically reducing total test time. The key challenge: making WebDriver thread-safe.

ThreadSafeContext.java
package com.bdd.course.context;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

// Thread-safe WebDriver using ThreadLocal
public class ThreadSafeContext {

    private static final ThreadLocal<WebDriver> driverThread =
        new ThreadLocal<>();

    public WebDriver getDriver() {
        if (driverThread.get() == null) {
            WebDriver driver = new ChromeDriver();
            driver.manage().window().maximize();
            driverThread.set(driver);
        }
        return driverThread.get();
    }

    public void tearDown() {
        WebDriver driver = driverThread.get();
        if (driver != null) {
            driver.quit();
            driverThread.remove();
        }
    }
}
ParallelRunner.java
package com.bdd.course.runner;

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
import org.testng.annotations.DataProvider;

@CucumberOptions(
    features = "src/test/resources/features",
    glue = "com.bdd.course.stepdefinitions",
    plugin = {"pretty", "html:target/cucumber-reports.html"}
)
public class ParallelRunner extends AbstractTestNGCucumberTests {

    @Override
    @DataProvider(parallel = true)
    public Object[][] scenarios() {
        return super.scenarios();
    }
}

// testng.xml for thread count:
// <suite name="BDD" parallel="methods" thread-count="4">
//   <test name="Cucumber">
//     <classes>
//       <class name="com.bdd.course.runner.ParallelRunner"/>
//     </classes>
//   </test>
// </suite>

// Maven Surefire parallel:
// <plugin>
//   <artifactId>maven-surefire-plugin</artifactId>
//   <configuration>
//     <parallel>methods</parallel>
//     <threadCount>4</threadCount>
//   </configuration>
// </plugin>
parallel_run.sh
# Behave doesn't natively support parallel.
# Use behave-parallel or pytest-bdd for parallel execution.

# Option 1: behavex (parallel behave runner)
# pip install behavex
behavex -t @smoke --parallel-processes 4 --parallel-scheme scenario

# Option 2: pytest-bdd (Cucumber-compatible, pytest-powered)
# pip install pytest-bdd pytest-xdist
# Write scenarios in .feature files, steps with @given/@when/@then
pytest -n 4  # 4 parallel processes

# Option 3: Run features in parallel via xargs
ls features/*.feature | xargs -P4 -I{} behave {}

# Option 4: Use subprocess for manual parallelism
# python run_parallel.py
run_parallel.py
"""Manual parallel behave execution"""
import subprocess
import os
from concurrent.futures import ProcessPoolExecutor, as_completed

def run_feature(feature_file):
    result = subprocess.run(
        ['behave', feature_file, '--no-capture'],
        capture_output=True, text=True
    )
    return {
        'feature': os.path.basename(feature_file),
        'returncode': result.returncode,
        'output': result.stdout
    }

if __name__ == '__main__':
    features = [
        f'features/{f}' for f in os.listdir('features')
        if f.endswith('.feature')
    ]

    print(f"Running {len(features)} features in parallel...")

    with ProcessPoolExecutor(max_workers=4) as executor:
        futures = {executor.submit(run_feature, f): f for f in features}
        for future in as_completed(futures):
            result = future.result()
            status = 'PASS' if result['returncode'] == 0 else 'FAIL'
            print(f"  [{status}] {result['feature']}")

Cucumber BDD Advanced Parallel Execution

Written by PV

© 2026 All Rights Reserved