Parallel Execution Configuration
SHAFT supports multiple types of parallel execution to help you run tests faster and more efficiently. This guide covers all the different parallel execution options available and how to configure them.
Overview
SHAFT provides three main types of parallel execution:
- TestNG Parallel Execution - Run multiple test methods, classes, or suites in parallel
- Cross-Browser Parallel Execution - Run the same tests across multiple browsers simultaneously
- ThreadLocal Driver Pattern - Safely manage WebDriver instances in multi-threaded environments
1. TestNG Parallel Execution
TestNG provides built-in support for running tests in parallel. SHAFT makes it easy to configure this through properties.
Configuration
You can configure TestNG parallel execution in your testng.properties file or programmatically.
File-based Configuration
# Set the parallel mode: METHODS, CLASSES, TESTS, or INSTANCES
setParallel=METHODS
# Set the parallelization mode: STATIC or DYNAMIC
setParallelMode=DYNAMIC
# Number of threads to use
# In STATIC mode: Used as-is
# In DYNAMIC mode: Total threads = CPU cores × setThreadCount
setThreadCount=2
# Control test execution order
setPreserveOrder=false
# Group test instances together
setGroupByInstances=false
# Number of threads for data providers
setDataProviderThreadCount=1
# Test suite timeout in minutes
testSuiteTimeout=1440
Parallel Modes Explained
| Mode | Description | Use Case |
|---|---|---|
METHODS | Runs test methods in parallel | Best for independent test methods |
CLASSES | Runs test classes in parallel | Good when each class has setup/teardown |
TESTS | Runs test tags/suites in parallel | Useful for running different test suites |
INSTANCES | Runs test instances in parallel | For tests with multiple instances |
NONE | No parallelization (default) | Sequential execution |
Thread Count Calculation
- STATIC Mode: Uses the exact
setThreadCountvalue - DYNAMIC Mode: Calculates total threads as:
Total Threads = Number of CPU Cores × setThreadCount
Example Configuration Scenarios
Run test methods in parallel with 4 threads
setParallel=METHODS
setParallelMode=STATIC
setThreadCount=4
Run test classes in parallel (dynamic based on CPU cores)
setParallel=CLASSES
setParallelMode=DYNAMIC
setThreadCount=2
Run tests sequentially (no parallelization)
setParallel=NONE
setThreadCount=1
Using a testng.xml File
In addition to the properties-based configuration, you can use a testng.xml file to define your test suite, choose exactly which classes and methods to run, and control parallel execution with fine-grained options.
Why Use testng.xml?
- Explicit test selection — Choose exactly which classes and methods to run
- Multiple test groups — Define separate
<test>blocks with different configurations - Suite-level configuration — Set parameters, listeners, and groups at the suite level
- Better CI integration — Reference a single file to run your entire suite from one place
Where to Place testng.xml
Place the file in your project root or under src/test/resources:
project-root/
├── src/
│ ├── main/resources/properties/
│ │ ├── custom.properties
│ │ └── testng.properties
│ └── test/
│ ├── java/com/example/tests/
│ │ └── SearchTest.java
│ └── resources/
│ └── testng.xml ← recommended location
└── testng.xml ← or project root
Basic testng.xml Structure
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="SHAFT Test Suite" parallel="methods" thread-count="3">
<test name="Web Tests">
<classes>
<class name="com.example.tests.SearchTest"/>
<class name="com.example.tests.LoginTest"/>
</classes>
</test>
</suite>
Parallel Execution Attributes
| Attribute | Values | Description |
|---|---|---|
parallel | methods | Run test methods in parallel (most common) |
parallel | classes | Run test classes in parallel |
parallel | tests | Run <test> blocks in parallel |
parallel | instances | Run test instances in parallel |
parallel | none | No parallelization (default) |
thread-count | integer | Number of parallel threads |
Example: Run Methods in Parallel (4 Threads)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="SHAFT Test Suite" parallel="methods" thread-count="4">
<test name="All Tests">
<classes>
<class name="com.example.tests.SearchTest"/>
<class name="com.example.tests.LoginTest"/>
<class name="com.example.tests.CheckoutTest"/>
</classes>
</test>
</suite>
Example: Run Test Blocks in Parallel
Each <test> block runs in its own thread — useful for isolating smoke tests from regression tests:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="SHAFT Test Suite" parallel="tests" thread-count="2">
<test name="Smoke Tests">
<classes>
<class name="com.example.tests.SmokeTest"/>
</classes>
</test>
<test name="Regression Tests">
<classes>
<class name="com.example.tests.RegressionTest"/>
</classes>
</test>
</suite>
Configure Maven to Use testng.xml
Update the Maven Surefire Plugin in your pom.xml to point to your testng.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
Running Tests
Once Maven is configured, run as normal:
mvn test
To override the XML file path from the command line without changing pom.xml:
mvn test -DsuiteXmlFile=src/test/resources/smoke-testng.xml
testng.xmlcontrols which tests to run and how to run them (suite structure, parallel mode, thread count per suite).testng.propertiesapplies the same settings globally across all runs.
When both are present, the testng.xml suite-level settings (parallel mode and thread count) take precedence.
2. Cross-Browser Parallel Execution
SHAFT can automatically run your tests across Chrome, Firefox, and Safari either sequentially or in parallel.
Prerequisites
- Docker Desktop must be installed and configured to use Linux images
- Docker must be running before test execution
Configuration
- File-based
- CLI-based
- Code-based
# Run tests on Chrome, Firefox, and Safari in parallel
SHAFT.CrossBrowserMode=parallelized
# Or run them sequentially
# SHAFT.CrossBrowserMode=sequential
# Or disable cross-browser mode (default)
# SHAFT.CrossBrowserMode=off
# Parallel execution across browsers
mvn test -DSHAFT.CrossBrowserMode=parallelized
# Sequential execution across browsers
mvn test -DSHAFT.CrossBrowserMode=sequential
import com.shaft.driver.SHAFT;
@BeforeClass
public void beforeClass() {
// Enable parallel cross-browser execution
SHAFT.Properties.platform.set().crossBrowserMode("parallelized");
// Or sequential
// SHAFT.Properties.platform.set().crossBrowserMode("sequential");
}
Cross-Browser Modes
| Mode | Description |
|---|---|
off | Normal execution with your configured browser (default) |
sequential | Tests run on Chrome, Firefox, and Safari one after another |
parallelized | Tests run on all three browsers at the same time |
Cross-browser mode requires Docker Desktop to be installed and running. SHAFT will use Docker to spin up browser containers for parallel execution.
Example: Cross-Browser + TestNG Parallel
You can combine cross-browser execution with TestNG parallelization for maximum speed:
SHAFT.CrossBrowserMode=parallelized
setParallel=CLASSES
setThreadCount=3
This will run each test class on all three browsers in parallel.
3. ThreadLocal Driver Pattern
When running tests in parallel, each thread needs its own WebDriver instance to avoid conflicts. SHAFT recommends using ThreadLocal to manage driver instances safely.
Why ThreadLocal?
- Thread Safety: Each thread gets its own WebDriver instance
- No Conflicts: Prevents race conditions when tests run in parallel
- Clean Isolation: Each test has complete isolation from others
Implementation
Here's a complete example of using ThreadLocal with SHAFT:
import com.shaft.driver.SHAFT;
import org.testng.annotations.*;
public class ParallelThreadLocalTest {
// ThreadLocal variable to store driver per thread
private ThreadLocal<SHAFT.GUI.WebDriver> driver = new ThreadLocal<>();
private SHAFT.TestData.JSON testData;
@Test
public void loginTest() {
new LoginPage(driver.get())
.login(testData.getTestData("email"),
testData.getTestData("password"))
.verifyUserIsLoggedIn(testData.getTestData("welcomeText"));
}
@Test
public void searchTest() {
new HomePage(driver.get())
.search(testData.getTestData("searchQuery"))
.verifySearchResults(testData.getTestData("expectedResults"));
}
@BeforeClass
public void beforeClassSetup() {
// Load test data once per class
testData = new SHAFT.TestData.JSON("TestData.json");
}
@BeforeMethod
public void beforeMethodSetUp() {
// Create a new driver instance for each test method
driver.set(new SHAFT.GUI.WebDriver());
driver.get().browser().navigateToURL("https://example.com");
}
@AfterMethod
public void afterMethodTearDown() {
// Quit the driver after each test method
driver.get().quit();
}
}
Key Points for ThreadLocal Pattern
- Declare ThreadLocal: Create a
ThreadLocal<SHAFT.GUI.WebDriver>field - Set in @BeforeMethod: Initialize driver with
driver.set(new SHAFT.GUI.WebDriver()) - Access with .get(): Use
driver.get()to access the driver instance - Clean up in @AfterMethod: Always quit the driver with
driver.get().quit()
Configure TestNG for Parallel Execution
setParallel=METHODS
setThreadCount=3
Example Repository
For a complete working example, visit this repository: SHAFT Engine - Parallel Execution with ThreadLocal Demo
Best Practices and Tips
1. Start Small
- Begin with
setThreadCount=2and gradually increase - Monitor system resources (CPU, memory) during execution
- Find the optimal thread count for your machine and tests
2. Ensure Test Independence
- Each test should be completely independent
- Don't rely on test execution order
- Clean up all test data in
@AfterMethodor@AfterClass
3. Use ThreadLocal Consistently
- Always use
driver.get()to access the driver - Never share driver instances between threads
- Initialize driver in
@BeforeMethod, quit in@AfterMethod
4. Handle Shared Resources Carefully
- Use synchronization for shared test data
- Consider using separate test data for each thread
- Be cautious with database connections and file I/O
5. Configure Appropriate Timeouts
defaultElementIdentificationTimeout=30
browserNavigationTimeout=60
pageLoadTimeout=60
6. Consider Headless Execution
Running in headless mode is faster and uses fewer resources:
headlessExecution=true
7. Enable Maximum Performance Mode
For even faster execution, consider enabling maximum performance mode:
maximumPerformanceMode=2
This provides up to 400% performance boost by disabling complementary features.
Troubleshooting
Tests Failing Only in Parallel Mode
Problem: Tests pass when running individually but fail in parallel.
Solutions:
- Check for shared state between tests
- Ensure each test cleans up after itself
- Verify ThreadLocal driver is used correctly
- Look for race conditions in your page objects
Out of Memory Errors
Problem: OutOfMemoryError when running many tests in parallel.
Solutions:
- Reduce
setThreadCount - Increase JVM heap size:
mvn test -Xmx2g - Enable headless execution
- Ensure drivers are properly quit after each test
Docker Not Found for Cross-Browser
Problem: Cross-browser mode fails with Docker errors.
Solutions:
- Install Docker Desktop
- Start Docker before running tests
- Verify Docker is configured for Linux containers
- Check Docker has sufficient resources allocated
WebDriver Exceptions
Problem: NoSuchSessionException or WebDriverException in parallel tests.
Solutions:
- Verify ThreadLocal pattern is implemented correctly
- Check that
driver.set()is called in@BeforeMethod - Ensure
driver.get().quit()is in@AfterMethod - Don't reuse driver instances across methods
Performance Comparison
Here's an example of performance gains with parallel execution:
| Configuration | Execution Time | Improvement |
|---|---|---|
| Sequential (1 thread) | 60 minutes | Baseline |
| Parallel (2 threads) | 35 minutes | 42% faster |
| Parallel (4 threads) | 20 minutes | 67% faster |
| Parallel (4 threads) + Headless | 15 minutes | 75% faster |
| Parallel (4 threads) + Max Performance | 12 minutes | 80% faster |
Actual results vary based on test suite, system resources, and test complexity.
Complete Configuration Example
Here's a complete configuration for maximum parallel execution performance:
# Target browser
targetBrowserName=chrome
# Enable headless execution for better performance
headlessExecution=true
# Enable maximum performance mode
maximumPerformanceMode=2
# Cross-browser parallel execution
SHAFT.CrossBrowserMode=parallelized
# Optimize timeouts
defaultElementIdentificationTimeout=30
browserNavigationTimeout=60
pageLoadTimeout=60
# Run test methods in parallel
setParallel=METHODS
# Dynamic thread calculation based on CPU cores
setParallelMode=DYNAMIC
# 2 threads per CPU core
setThreadCount=2
# Don't preserve test order for maximum speed
setPreserveOrder=false
public class MyParallelTest {
private ThreadLocal<SHAFT.GUI.WebDriver> driver = new ThreadLocal<>();
@Test
public void testOne() {
driver.get().browser().navigateToURL("https://example.com");
// Your test code here
}
@BeforeMethod
public void setup() {
driver.set(new SHAFT.GUI.WebDriver());
}
@AfterMethod
public void teardown() {
driver.get().quit();
}
}
Related Documentation
For more information, check out these related topics:
- Properties List - Complete reference of all SHAFT properties
- Property Types - Learn about different ways to configure properties
- Common Examples - See practical configuration examples
- Web GUI Demo - Working examples of parallel execution
Summary
SHAFT provides powerful parallel execution capabilities:
- TestNG Parallel Execution: Configure through
testng.propertieswith multiple modes (METHODS, CLASSES, TESTS, INSTANCES) - Cross-Browser Execution: Run tests across Chrome, Firefox, and Safari sequentially or in parallel
- ThreadLocal Pattern: Safely manage WebDriver instances in multi-threaded environments
By combining these features and following best practices, you can significantly reduce test execution time while maintaining test reliability and stability.