Enable JUnit Jupiter’s parallel execution in JUnit Platform configuration, choose a bounded concurrency strategy, and give every concurrently running test its own WebDriver. Start with a small worker count and increase it only while your runner, browsers, test data, and—if used—Selenium Grid remain stable. JUnit concurrency speeds execution on the resources you already have; Grid is the step for distributing sessions across remote machines or browser and operating-system combinations.
Enable parallel execution in JUnit 5
JUnit Jupiter parallel execution is opt-in. Put its configuration in junit-platform.properties on the test classpath, commonly under src/test/resources. This example lets test methods run concurrently and bounds the worker pool at four threads:
As an Amazon Associate I earn from qualifying purchases.
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
junit.jupiter.execution.parallel.config.strategy = fixed
junit.jupiter.execution.parallel.config.fixed.parallelism = 4
junit.jupiter.execution.parallel.config.fixed.max-pool-size = 4
The numbers are an initial configuration, not a universal capacity recommendation. Select a value that fits the machine and browser sessions available to your test run, then adjust based on observed stability and resource use.
Choose what may run concurrently
The default mode above applies to test methods. JUnit also provides execution-mode settings for classes and methods, so choose deliberately whether classes, methods, or both may overlap. Concurrent tests must not depend on shared mutable fixtures or on a fixed execution order. Tests that cannot safely overlap can be constrained with JUnit’s execution controls rather than disabling concurrency for the entire suite. See the JUnit 5.11.0 User Guide for the parallel execution parameters and mode details.
#1 Best Overall
Configure Maven Surefire for Jupiter
For a Maven project, Selenium’s Java installation guide shows Surefire configuration using JUnit Platform parameters. The key is to pass the same Jupiter settings through Surefire’s configurationParameters, including a fixed strategy and a bounded pool:
<properties>
<junit.parallelism>4</junit.parallelism>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<properties>
<configurationParameters>
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
junit.jupiter.execution.parallel.config.strategy = fixed
junit.jupiter.execution.parallel.config.fixed.parallelism = ${junit.parallelism}
junit.jupiter.execution.parallel.config.fixed.max-pool-size = ${junit.parallelism}
</configurationParameters>
</properties>
</configuration>
</plugin>
</plugins>
</build>
This example follows the Maven Surefire configuration shown in Selenium’s Java installation guide. Check the Surefire version and provider used by your own project: Surefire’s JUnit Platform page contains a statement that conflicts with Jupiter’s documented parallel execution and Selenium’s example. Do not interpret that statement as a categorical limitation of current Jupiter; verify the exact plugin/provider combination and confirm that the configuration is being applied. Surefire documents that tests run through the JUnit Platform provider since version 3.6.0. See Surefire’s JUnit Platform page and its test mojo reference.
Rank #2
Maven’s generic parallel option is provider-specific. For JUnit Jupiter, use Jupiter’s JUnit Platform configuration parameters rather than assuming a generic Surefire parallel setting controls Jupiter execution. Surefire also has separate fork and parallel execution settings; consult its fork options and parallel test execution documentation before mixing process forks with JUnit worker threads.
Give each concurrent test its own WebDriver
WebDriver is not safe to share casually between concurrently executing tests. Each test should create and quit its own driver in a test-scoped lifecycle, or use a thread-associated driver in a shared extension or base class. A common pattern is ThreadLocal<WebDriver>; teardown must call quit() and then remove() so a later test cannot inherit a stale session.
Rank #3
private static final ThreadLocal<WebDriver> DRIVER = new ThreadLocal<>();
@BeforeEach
void startBrowser() {
WebDriver driver = new ChromeDriver();
DRIVER.set(driver);
}
@AfterEach
void stopBrowser() {
WebDriver driver = DRIVER.get();
try {
if (driver != null) {
driver.quit();
}
} finally {
DRIVER.remove();
}
}
static WebDriver driver() {
return DRIVER.get();
}
This is a lifecycle pattern, not a complete test framework: adapt it to your browser options and test extension, and ensure cleanup also runs when setup or a test fails. Avoid static shared drivers and shared browser state. Thread association does not isolate application data, accounts, files, or external services; tests need their own data or another deliberate isolation strategy.
Use ThreadGuard as a diagnostic
Selenium’s Java ThreadGuard wrapper can detect an accidental call to a driver from a thread other than the one that created it. For example:
Rank #4
WebDriver rawDriver = new ChromeDriver();
WebDriver driver = ThreadGuard.protect(rawDriver);
ThreadGuard throws when it detects cross-thread access; it does not make a shared driver safe or replace per-test/per-thread driver management. Selenium explicitly notes that ThreadLocal management is still needed. See Selenium ThreadGuard documentation.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Decide whether local concurrency is enough or use Grid
| Consideration | Local parallel execution | Selenium Grid |
|---|---|---|
| Where browsers run | On the test runner’s available local machines and browser installations. | On remote browser instances routed by Grid; sessions can run across machines. |
| Setup and operations | Fewer moving parts, but the runner must have capacity for all concurrent browsers. | Requires Grid deployment and capacity management, in exchange for remote distribution. |
| Browser and platform coverage | Limited to browsers and operating systems available to the runner. | Supports parallel runs across browser types, versions, and machines for cross-platform testing. |
| Concurrency ceiling | Bounded by runner CPU, memory, browser availability, and test-data isolation. | Bounded by Grid Nodes, deployed resources, browser configuration, and any CI or external service limits. |
Selenium describes Grid as a way to route WebDriver commands to remote browser instances and run tests in parallel across machines and browser versions. Its guidance says a Distributor with four CPUs can create up to four sessions concurrently in its example; an eight-CPU Node example supports up to eight concurrent sessions, except Safari, which is limited to one. The documentation estimates around 1 GB of RAM per browser session and recommends smaller Nodes for process isolation. These are Selenium documentation examples and guidance, accessed 2026-10-03—not universal benchmarks or capacity guarantees. Actual limits vary with hardware, browser, workload, and deployment. See Selenium Grid.
Best Value
Start a local standalone Grid
For a basic local Grid, Selenium’s getting-started guide lists Java 11 or higher, browsers and drivers (or Selenium Manager), and the Selenium Server JAR as prerequisites. Start the standalone server and point a remote driver at its endpoint:
java -jar selenium-server-<version>.jar standalone
WebDriver driver = new RemoteWebDriver(
URI.create("http://localhost:4444").toURL(),
new ChromeOptions()
);
Use the Selenium Server version and browser capabilities appropriate for your environment. The endpoint shown is the local standalone example, not a remote deployment address. Full setup details are in Selenium Grid getting started.
Interpret Grid’s timing examples cautiously
Selenium’s Grid applicability page illustrates possible arithmetic rather than reporting a benchmark: 15 tests estimated at 45 seconds each are shown as 11 minutes 15 seconds on one node, 2 minutes 15 seconds across five, and 45 seconds across 15. Real runs do not necessarily divide evenly: startup, queueing, uneven test durations, shared bottlenecks, and failures can change elapsed time. Use the figures as an explanation of distribution, not a promise. See Selenium Grid applicability.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Set a safe concurrency level
- Run the suite serially once and verify that individual tests clean up their browser and data.
- Enable Jupiter parallel execution with a small fixed worker count and the same maximum pool bound.
- Check that every concurrent test gets a separate WebDriver and that parallel tests do not collide on accounts, records, files, or other shared state.
- Measure total duration, runner CPU and memory, browser stability, and—if using Grid—available Node sessions and queueing.
- Increase concurrency only when the environment has headroom and results remain repeatable; otherwise lower the bound or isolate the tests that cannot safely overlap.
JUnit worker count is not the same thing as usable browser-session capacity. A Grid, CI worker, or external service may impose a lower limit. More threads can increase contention or expose test-data races instead of reducing elapsed time.
Troubleshoot common failures
| Symptom | Likely cause | What to check or change |
|---|---|---|
| Tests still run serially | Jupiter parameters are absent, misplaced, or not passed by the active test provider. | Confirm junit.jupiter.execution.parallel.enabled = true is on the test classpath or in Surefire’s configurationParameters; verify the Surefire version/provider and inspect the effective test configuration. |
| WebDriver reports a different-thread call or tests interfere through one browser | A driver or its session is shared across concurrent tests. | Create a driver per test/thread, ensure teardown calls quit() and remove(), and use ThreadGuard to identify cross-thread calls. |
| Intermittent failures only in parallel | Tests may share application data, files, accounts, or mutable fixtures, or the runner may be resource constrained. | Isolate test data and fixtures; lower fixed parallelism; compare resource use and rerun the affected tests under controlled concurrency. |
| Grid sessions wait, fail to start, or exceed capacity | Requested concurrency exceeds available Node/browser slots or deployment resources. | Match JUnit concurrency to available Grid capacity, inspect Node registration and browser availability, and scale or reduce sessions deliberately. |
| Local browsers launch but remote tests cannot connect | The test is using a local driver rather than a remote endpoint, or the Grid URL is incorrect/unreachable. | For Grid, create a RemoteWebDriver with the deployed Grid endpoint and browser options; confirm network access and server state. |
Or skip the browser setup
If your goal is to capture web pages rather than run browser interaction tests, ScreenshotNeo is a website screenshot API and MCP server. One GET request returns a PNG, JPEG, WebP, or PDF. For example, using cURL:
Quick Recap
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo API documentation for request options. ScreenshotNeo accepts cookie/consent banners and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and responses include X-Page-Verdict and X-Billed headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000. Sign up for ScreenshotNeo’s free plan.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




