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

Build a Selenium TestNG program by adding Selenium’s Java bindings and TestNG to a Maven or Gradle project, creating a WebDriver for each test, and using TestNG annotations to set up, run, and clean up browser tests. A testng.xml suite file can select tests and control execution; Maven Surefire or Gradle runs them. Selenium Manager can usually find and manage the browser driver, so installing ChromeDriver manually is not normally the first step.

What Selenium and TestNG each do

Selenium WebDriver controls a browser: it opens pages, locates elements, clicks, types, and reads browser state. TestNG runs and organizes the tests, applies lifecycle hooks, and evaluates assertions. As Selenium’s documentation puts it, WebDriver “does not know a thing about testing”; it does not decide whether an expected result matches an actual result. TestNG supplies that test-runner layer.

This separation is useful when diagnosing failures. A WebDriver exception usually points to browser startup, navigation, or interaction. A TestNG failure can instead be an assertion mismatch, a setup or teardown error, or a test-runner configuration issue. Selenium’s documentation describes WebDriver as “an API and protocol that defines a language-neutral interface for controlling the behaviour of web browsers.” The Selenium documentation pages were accessed on 29 September 2026.

Create a Java project with Maven

Maven or Gradle should manage the dependencies so a local machine and a CI runner can build from the same project definition. Here is a minimal Maven layout:

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.
selenium-testng/
├── pom.xml
└── src/
    └── test/
        ├── java/
        │   └── example/
        │       └── ExampleTest.java
        └── resources/
            └── testng.xml

For a reproducible team or CI build, select Selenium and TestNG versions compatible with your Java and browser environment, pin them in the project, and update them deliberately. The example below uses Maven version ranges to make the dependency declarations usable without asserting a particular current release. A range can resolve differently at a later date; pin approved versions for repeatable builds.

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId>
  <artifactId>selenium-testng</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.seleniumhq.selenium</groupId>
      <artifactId>selenium-java</artifactId>
      <version>[4.0,)</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>[7.0,)</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

The Selenium Java installation documentation uses the org.seleniumhq.selenium:selenium-java dependency pattern, and TestNG documents org.testng:testng for Maven. The test-scoped dependencies are available to tests without becoming ordinary application dependencies. The Java source/target values in this sample are project choices, not a claim about the minimum supported Java version for every Selenium or TestNG release; check the chosen releases’ requirements before fixing your build.

Write a test with setup, assertions, and teardown

Put tests in src/test/java and give the class a name that Maven Surefire recognizes, such as ExampleTest. This example opens the standard Example Domain page, checks its title, and always attempts to close the browser afterward.

package example;

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

public class ExampleTest {
    private WebDriver driver;

    @BeforeMethod
    public void startBrowser() {
        driver = new ChromeDriver();
    }

    @Test
    public void examplePageHasExpectedTitle() {
        driver.get("https://example.com");
        Assert.assertEquals(driver.getTitle(), "Example Domain");
    }

    @AfterMethod(alwaysRun = true)
    public void stopBrowser() {
        if (driver != null) {
            driver.quit();
        }
    }
}

@BeforeMethod runs before each test method and @AfterMethod runs after each one. That arrangement gives each test a fresh browser session, reducing hidden dependencies on browser state left by a previous test. quit() closes the session and its browser window; omitting cleanup can leave processes running and make later runs unreliable. alwaysRun = true asks TestNG to run teardown even when the test fails.

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

The test uses Chrome through ChromeDriver. To test another browser, use its Selenium driver class and ensure that browser is available in the execution environment. Keep assertions about expected application behavior in the test rather than treating a successful navigation as proof that the page is correct.

Configure a TestNG suite with testng.xml

TestNG can select classes, methods, groups, or packages through annotations and a suite definition. Create src/test/resources/testng.xml to explicitly name the class to run:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Browser suite">
  <test name="Example pages">
    <classes>
      <class name="example.ExampleTest"/>
    </classes>
  </test>
</suite>

A suite may contain one or more <test> elements; each test can list one or more classes. For a small project, a single class entry is enough. As the suite grows, organize selection around meaningful groups or test classes rather than putting browser setup in the XML. Lifecycle and browser behavior belong in Java; suite selection belongs in the suite or build-runner configuration.

Run the program locally and in CI

With Maven installed and the project root as the working directory, run:

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

Maven Surefire integrates with TestNG. Keep the suite file and build configuration under source control so developers and CI use the same test selection. If the runner does not pick up the intended classes or suite, check the Surefire configuration and the file’s location instead of assuming the browser test itself is broken.

Gradle also has first-class TestNG integration. In a Gradle project, configure the test task to use TestNG with useTestNG(), and keep the dependency declarations in the Gradle build file. Do not configure Maven and Gradle as competing sources of truth for the same project unless there is a specific reason to maintain both.

Or skip the browser setup

If your goal is to obtain page screenshots rather than interact with the page and assert application behavior, a screenshot API can avoid managing a local WebDriver for that capture. ScreenshotNeo is a website screenshot API and MCP server for developers; it is not a replacement for Selenium tests that need to click, type, or verify behavior.

One GET request returns an image or PDF. For a screenshot as WebP, run this cURL example and replace the sample URL with the page you need:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com -o shot.webp

See the ScreenshotNeo API documentation for request options and response details. ScreenshotNeo accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and whether the request was billed. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.

ScreenshotNeo also supports element captures, full-page shots with lazy images loaded, PDF settings, custom CSS and JavaScript, wait conditions, device presets, and other capture controls. See ScreenshotNeo for the service overview. Sign up for 1,000 free screenshots a month with no card.

Run tests in parallel safely

TestNG supports parallel execution by methods, tests, classes, or instances, as well as parallel data providers and thread-count controls. Parallelism can increase throughput, but it changes the isolation requirements: two tests must not accidentally share one WebDriver session or mutable test data. The simple field-based example above is intentionally for sequential tests; do not turn on method-level parallel execution for it unchanged.

For parallel methods on a test class, store the driver per thread and create a new one for each method:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
private static final ThreadLocal<WebDriver> driver = new ThreadLocal<>();

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

@Test
public void examplePageHasExpectedTitle() {
    WebDriver browser = driver.get();
    browser.get("https://example.com");
    Assert.assertEquals(browser.getTitle(), "Example Domain");
}

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

Then choose the intended mode and thread count in the suite, for example <suite name="Parallel suite" parallel="methods" thread-count="3">. Start with a low concurrency level and confirm that each method has its own driver, unique test data, and independent cleanup before increasing it. A test that writes to a shared account, file, or server-side record can still race even when its browser session is isolated.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Use Selenium Manager before installing a driver manually

Selenium Manager can discover, download, and cache required drivers and, where supported, browsers. In many local setups, constructing new ChromeDriver() is enough to trigger driver management without setting a driver executable path by hand. Its documented cache location is ~/.cache/selenium.

Automatic discovery reduces setup work, but it does not make every environment identical. In CI, review or pin browser and driver versions when repeatability matters, ensure the runner can access the resources needed to obtain them, and account for the cache when diagnosing a stale or unexpected executable. Manual driver-path configuration remains an option for environments that deliberately manage binaries themselves.

Move remote or broad browser runs to Selenium Grid

A local WebDriver run uses the developer machine’s browser and operating system. Selenium Grid adds remote execution through Selenium Server and RemoteWebDriver; the official getting-started flow starts a standalone server and points tests at http://localhost:4444. Grid becomes useful when you need remote nodes, broader browser and operating-system coverage, or more controlled concurrent execution.

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

Grid also adds infrastructure to start, maintain, and debug. Compare a local setup and a Grid-backed one across execution location, browser and OS breadth, concurrency, environment reproducibility, startup and infrastructure cost, and reporting/debugging workflow. Begin locally when one browser on one machine answers the question; move to Grid when remote environments or parallel capacity are an actual requirement.

Troubleshoot common failures

  • “No tests found” or the suite runs nothing: Confirm the Java package and class name in testng.xml, ensure the file is under test resources, and check that the build runner is configured to use the suite or discover the intended test class.
  • Driver executable or browser startup error: Check that the target browser is installed and usable in the environment, that Selenium Manager can obtain what it needs, and that network or filesystem restrictions are not blocking it. If your environment pins drivers manually, verify the configured binary matches the browser setup.
  • Works locally but fails in CI: Compare browser availability, versions, permissions, network access, and environment settings. Selenium Manager can reduce manual setup but cannot eliminate environment differences; pin or review browser versions where repeatability is important.
  • Tests pass alone but fail in a suite: Look for state carried between tests, shared accounts or records, and teardown that does not execute after a failure. Prefer fresh sessions and independent test data.
  • Parallel runs fail intermittently: Check for a shared WebDriver, shared test data, or another mutable resource. Give each concurrent test its own session and isolate external state before raising the thread count.
  • Navigation succeeds but the test gives a wrong result: Inspect the assertion and the actual page state. WebDriver performs browser control; TestNG evaluates the assertion, so a successful page load alone does not establish the expected application behavior.

Frequently asked questions

Can I run Selenium tests against browsers other than Chrome?

Yes. WebDriver is a browser-control interface, and Selenium supports browser-specific drivers. Choose the corresponding driver and ensure the browser is available on the machine or remote node running the test.

Can a screenshot API replace an interaction test?

No. A screenshot is useful when the output you need is an image or PDF; a Selenium test is the better fit when the program must perform browser interactions and assert outcomes.

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.

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