What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Set the TestNG suite’s parallel mode and thread-count, then make sure each concurrently running test has its own WebDriver session and isolated test data. For example, parallel="methods" can run independent test methods at once; Selenium Grid can provide browser sessions on other machines when local capacity is not enough. The right thread count is limited by available browser slots and machine resources, not just by the number in your XML file.

Configure TestNG parallel execution

TestNG’s parallel suite attribute chooses what TestNG schedules together, while thread-count sets the number of threads allocated for parallel execution. Put these attributes on the suite element in testng.xml. This runnable configuration assumes the named test classes are available on the test classpath:

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Parallel Suite" parallel="methods" thread-count="4">
  <test name="UI tests">
    <classes>
      <class name="tests.LoginTest"/>
      <class name="tests.CheckoutTest"/>
    </classes>
  </test>
</suite>

Run the suite using the same mechanism you already use to run TestNG, such as the project’s build tool or IDE. TestNG will schedule eligible work using the configured mode and thread pool; it does not create additional CPUs, browser capacity, or independent test data.

Choose a mode that matches test isolation

Mode What TestNG groups Useful when Trade-off
methods Methods can run concurrently, without method-level grouping. Methods are independent and method-level concurrency is useful. Requires careful isolation of class fields, drivers, and test data.
classes Methods within a class run in the same thread. Classes are independent but methods within a class share setup or state. Available parallelism is bounded by the number of classes.
tests Methods inside each XML <test> group stay together on a thread; separate groups can run on separate threads. XML groups represent separate browser configurations or isolated suites. Groups must not collide through shared accounts, records, or other mutable resources.
instances Methods on the same test object instance share a thread. Different instances represent independent test contexts. Instances must not share mutable resources that make their work interfere.

These are TestNG’s documented parallel modes; check the TestNG documentation for the behavior supported by the version in your project. If existing tests rely on mutable class fields or ordered fixtures, begin with a grouping mode that preserves those assumptions, or isolate that state before choosing finer-grained concurrency.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Give concurrent tests independent browser sessions

A parallel method must not drive the same mutable WebDriver object as another method. Create a session for each independently executing test context, and close it in teardown even if an assertion or browser operation fails. Keep accounts, database records, downloaded files, and other test inputs independent or uniquely allocated as well.

Here is one Java pattern using TestNG lifecycle hooks and ThreadLocal. It is an implementation choice, not a Selenium requirement. It assumes Selenium and TestNG dependencies are already on the project classpath and that the browser driver is available to Selenium in the execution environment.

package tests;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class LoginTest {
  private static final ThreadLocal<WebDriver> DRIVER = new ThreadLocal<>();

  @BeforeMethod
  public void startBrowser() {
    DRIVER.set(new ChromeDriver());
  }

  @Test
  public void loginPageLoads() {
    WebDriver driver = DRIVER.get();
    driver.get("https://example.com/");
    // Add assertions for the application under test.
  }

  @AfterMethod(alwaysRun = true)
  public void stopBrowser() {
    WebDriver driver = DRIVER.get();
    try {
      if (driver != null) {
        driver.quit();
      }
    } finally {
      DRIVER.remove();
    }
  }
}

The example creates and closes a browser around each TestNG method invocation. If the suite uses parallel="classes" or another grouping mode, choose lifecycle and storage semantics deliberately: a thread-local driver is safe only when the test’s intended session lifetime and the TestNG scheduling model match that design. For example, if several methods are supposed to share one session, do not blindly create and quit a new browser around each method; instead define a fixture scope that matches the grouped work and still prevents concurrently running groups from sharing the same driver.

  • Do not store one static WebDriver and let parallel methods issue commands against it.
  • Do not assume a test account or record is safe to reuse just because browser sessions are separate.
  • Use teardown that runs after failures, and remove per-thread references when finished.
  • Keep screenshots, downloads, and other file outputs unique per test if concurrent runs write them.

Scale browser execution with Selenium Grid

Selenium Grid runs suites in parallel against multiple machines (Nodes) and can support different browser types, browser versions, and operating systems. A local standalone Grid is a practical first step for exercising remote-session setup, but it is one machine, not a distributed multi-node deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Start a local standalone server

With Selenium Server available, start it in standalone mode:

java -jar selenium-server-<version>.jar standalone

Replace <version> with the Selenium Server jar version you have obtained. The standalone server is intended to put the Grid components on one machine. Check the official Grid getting-started guide for current prerequisites and server startup details.

Connect TestNG tests through RemoteWebDriver

Use the Grid endpoint when constructing the test’s driver. For a local standalone server, the documented endpoint is http://localhost:4444:

import java.net.URL;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;

URL gridUrl = new URL("http://localhost:4444");
WebDriver driver = new RemoteWebDriver(gridUrl, new ChromeOptions());

Use this in place of local new ChromeDriver() in the lifecycle code, preserving the same per-test session ownership and teardown with quit(). The browser capability in the options must be supported by the Grid. For a remote Grid, replace the localhost endpoint with the endpoint provided by that deployment and configure any required authentication or network access according to its operator.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose a topology and capacity deliberately

Use a single-machine standalone setup for local evaluation. For more machines or a wider browser matrix, choose Hub/Node or distributed roles according to the desired machine count, browser combinations, concurrent sessions, and available resources. Grid session capacity depends on processor availability and configuration; Selenium’s guide gives approximately 1 GB RAM per browser session as a planning reference, not a universal requirement or guarantee. Workloads vary, so measure your own suite.

The Selenium project illustrates the effect of node count with simplified calculations: 15 tests taking 45 seconds each are shown as 11 minutes 15 seconds on one node, 2 minutes 15 seconds on five nodes, and 45 seconds on 15 nodes. A separate illustration gives 13 minutes 20 seconds for 100 tests of 120 seconds each on 15 nodes. These are documentation examples, not benchmark results or guaranteed wall-clock times: they do not account for scheduling overhead, browser startup, dependencies, application contention, or uneven test duration. The same guide uses examples of up to four concurrently created sessions at a four-CPU Distributor and up to eight sessions on an eight-CPU Node, with Safari limited to one in that example; treat these as example capacity guidance, not universal defaults.

Set thread-count from observed capacity

Start with a modest thread-count, then compare elapsed time, stability, machine load, and Grid availability as you increase it. A larger number can make a suite slower or less reliable when browsers compete for CPU or memory, when the Grid has fewer usable slots, or when tests contend for application services and shared data. Raise concurrency only while the workload remains stable and the additional workers improve throughput.

  • Local browsers: account for the memory and CPU cost of each browser process, as well as the test runner.
  • Grid: account for available browser slots and the capacity of the Distributor and Nodes.
  • Application and data: check whether the test environment, accounts, APIs, or databases can handle the same concurrency.
  • Suite shape: long setup time, serial dependencies, and uneven test durations can prevent extra threads from reducing total runtime proportionally.

TestNG also has separate data-provider thread pools and pool controls; their defaults and available controls can differ by version. The documentation notes a default of 10 for data-provider pools running from XML, and additional pool controls beginning with TestNG 7.9.0. Do not assume that suite thread-count is the only concurrency setting: verify the behavior for the TestNG version and data-provider configuration in use in the TestNG documentation and TestNG parameters documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot parallel runs

Tests fail only when run together

Look for shared mutable state first: a static driver, class fields used by concurrently scheduled methods, the same account, a shared database record, or a fixed output filename. Give each execution independent state or use a TestNG grouping mode that preserves the intended fixture boundary. A slower serial run can help identify whether failures depend on concurrency, but it does not by itself establish the root cause.

More threads make the run slower or unstable

Reduce thread-count and inspect CPU, memory, browser startup time, Grid slots, application response time, and external service limits. If local capacity is the constraint, run on appropriately provisioned Grid nodes rather than increasing the thread setting alone. Re-measure after each change instead of assuming a particular thread-to-CPU ratio.

Remote session creation fails

Confirm the Selenium Server is running, the URL and port match the active Grid endpoint, and the requested browser capability is available. For a local standalone setup, check that the server is listening at http://localhost:4444. In a multi-machine deployment, also verify network reachability and the Grid’s configured node registration and capacity.

Browsers remain open after failed tests

Ensure teardown runs after failure and invokes quit(), not merely close(). Use a TestNG teardown hook such as @AfterMethod(alwaysRun = true), and clean up thread-local references in a finally block so a failed test does not leave stale state for later work.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Grid is reachable from places it should not be

Restrict Grid access with firewall and network controls. Selenium warns that an exposed Grid can provide access to infrastructure and internal applications, or allow third parties to run binaries. Do not treat a reachable endpoint as safe to expose publicly.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server, not a substitute for Selenium functional tests: it captures a page, rather than running your TestNG assertions or interactions. If your goal is a clean screenshot artifact, one GET request can capture a URL without managing a browser locally. The example below saves a WebP response; consult the ScreenshotNeo documentation for request options and response details.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Before capture, ScreenshotNeo can accept cookie or consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each of those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents and MCP clients. The Free plan includes 1,000 screenshots per month without a card; paid plans start at $5 for 3,000 shots.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month with no card.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What to remember when designing the suite

Parallel execution is a combination of scheduling, isolation, and capacity. Choose the TestNG mode that matches how tests share fixtures, give concurrent work independent browser sessions and data, and add Grid when you need sessions beyond one machine or a broader browser matrix. Tune the thread count against measured behavior rather than treating it as a speed setting.

Frequently Asked Questions

Does TestNG run tests in parallel by default?

Parallel execution is configured on the suite; set its parallel mode and thread-count when you want TestNG to schedule work concurrently.

Can I run TestNG parallel tests without Selenium Grid?

Yes. TestNG can schedule work on the local machine. Grid is for distributing browser execution across machines or browser environments, not a prerequisite for TestNG parallel mode.

Is ThreadLocal required for Selenium parallel testing?

No. It is one Java technique for keeping per-thread driver references separate. The essential requirement is that concurrently executing tests do not control the same mutable WebDriver session.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.