Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Clear out junk files and repair common Windows errors3Fix the driver behind crashes, sound loss and screen glitchesDirect answer: Add the Selenium Java and TestNG libraries to your existing Maven or Gradle project, create a Java class with a @Test method and browser lifecycle hooks, run it through the build tool, and introduce testng.xml when you need explicit suites, groups, parameters or parallel execution. The browser and its matching driver must be available before the first test can start.
What you need before writing a test
This setup assumes a Java project, a build tool (Maven or Gradle), Selenium Java bindings, TestNG, and a browser with the corresponding WebDriver support. Selenium’s installation guidance describes adding the Java libraries through a build tool; its getting-started material also identifies the browser and driver as prerequisites. TestNG supplies annotations, lifecycle configuration, data-driven tests, groups and execution controls.
- Java: use a version supported by the exact Selenium, TestNG and build-plugin versions you select.
- Maven or Gradle: use the tool already used by the repository and CI pipeline rather than introducing a second build system.
- Browser and driver: install the browser you intend to test and make sure Selenium can obtain or locate its compatible driver.
- Project layout: place tests in the build tool’s test source directory (normally
src/test/java).
Dependency and Java compatibility change over time. TestNG documentation examples have shown version 7.9.0, but that example is not a promise that it is the newest release or compatible with every Selenium and JDK combination. Verify the versions immediately before pinning them in a new project, and check the requirements of your selected Selenium release.
Add Selenium and TestNG dependencies
Maven
Keep the versions in properties so a compatibility change is made in one place. Replace the property values with versions you have verified for your JDK and browser setup; do not copy an unverified version into production.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstall#1 Best Overall
<properties>
<selenium.version>VERIFIED_SELENIUM_VERSION</selenium.version>
<testng.version>VERIFIED_TESTNG_VERSION</testng.version>
</properties>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
The Selenium Java guide describes this build-tool installation approach, while TestNG’s Maven instructions cover adding TestNG as a test dependency. Keep both libraries in test scope unless application code genuinely imports them.
Gradle
Declare the libraries in the test configuration used by your Gradle version. The exact dependency notation is stable, but the selected versions still need compatibility checking.
def seleniumVersion = "VERIFIED_SELENIUM_VERSION"
def testngVersion = "VERIFIED_TESTNG_VERSION"
dependencies {
testImplementation "org.seleniumhq.selenium:selenium-java:${seleniumVersion}"
testImplementation "org.testng:testng:${testngVersion}"
}
test {
useTestNG()
}
TestNG points to Gradle’s official TestNG integration documentation for the current task configuration. If your project already has a custom test task, merge useTestNG() into that task instead of creating a competing task.
Write a minimal Selenium TestNG class
TestNG runs methods marked with @Test; a normal test does not need a main method. Configuration annotations provide setup and teardown hooks. The following is a minimal illustration using a public example page. Replace the URL and assertion with a page that belongs to your application.
Recommended Free Tools
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 setUp() {
driver = new ChromeDriver();
}
@Test
public void pageHasExpectedTitle() {
driver.get("https://example.com");
Assert.assertEquals(driver.getTitle(), "Example Domain");
}
@AfterMethod(alwaysRun = true)
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
}
This code is a minimal pattern, not a claim that it was executed in your environment. alwaysRun = true asks TestNG to perform cleanup even when the test fails. The null check prevents teardown from masking an earlier setup failure.
Rank #2
Why the lifecycle matters
@BeforeMethodcreates a fresh browser before each test method, reducing state leakage.@Testcontains the user-visible behavior and assertions.@AfterMethod(alwaysRun = true)closes the session and releases the driver process.
For a deliberately class-scoped browser, use @BeforeClass and @AfterClass, but only when tests can safely share state. A method-scoped browser is the safer default for independent UI checks.
Run the test through your build tool
Maven
Start with the project’s normal test command:
mvn test
Maven Surefire is the component that discovers and runs test classes during the test phase. Ensure the TestNG dependency is present and that your test source is under the configured test-source directory. If the project has a custom Surefire configuration, preserve its existing include and exclude rules while enabling TestNG support according to the current Surefire documentation.
Gradle
Run the standard test task after adding useTestNG():
./gradlew test
On Windows, use gradlew.bat test. Read the generated report location printed by Gradle when a test fails; it normally includes the failing method, stack trace and captured output.
What a first successful run proves
A passing run confirms that dependency resolution, TestNG discovery, browser startup, navigation and teardown all worked together. It does not prove that every browser version, operating system or CI agent is configured identically.
Rank #3
Use testng.xml for explicit suites
A tiny project can rely entirely on Maven or Gradle discovery. Add an XML suite when you need named collections, class or package selection, groups, parameters, or parallel controls. TestNG describes a suite as one XML file and supports suite, test and class elements.
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Browser suite">
<test name="Smoke tests">
<classes>
<class name="example.ExampleTest"/>
</classes>
</test>
</suite>
Save it as testng.xml (often in the project root or test resources) and configure your build to pass that suite to TestNG. The exact Maven or Gradle wiring depends on the project’s existing plugin configuration; avoid maintaining a second, contradictory test-discovery path.
Select groups
Annotate a method or class with groups, then include or exclude those groups in the XML:
@Test(groups = {"smoke"})
public void loginPageLoads() {
// test steps
}
<suite name="Smoke suite">
<test name="Smoke">
<groups>
<run>
<include name="smoke"/>
</run>
</groups>
<packages>
<package name="example"/>
</packages>
</test>
</suite>
Pass parameters
Use XML parameters for values that vary by suite, such as an environment URL, and read them with TestNG’s @Parameters annotation. Keep secrets out of source control; inject them through CI variables or a secret manager.
<suite name="Environment suite">
<parameter name="baseUrl" value="https://example.com"/>
<test name="Navigation">
<classes>
<class name="example.ParameterizedTest"/>
</classes>
</test>
</suite>
import org.testng.annotations.Parameters;
@Parameters("baseUrl")
@Test
public void opensSite(String baseUrl) {
driver.get(baseUrl);
}
Choose sequential or parallel execution
Sequential execution is the reliable starting point. TestNG can run methods, classes, tests, instances or suites in parallel and can limit concurrency with a thread count in XML. Parallel mode is an advanced optimization, not a substitute for isolation.
Rank #4
<suite name="Parallel classes" parallel="classes" thread-count="2">
<test name="UI tests">
<packages>
<package name="example"/>
</packages>
</test>
</suite>
Before enabling it, make every concurrently running test own its WebDriver instance, test data and mutable state. Do not store a single static driver, reuse one account without coordination, or write multiple tests to the same file. Start with a small thread count and increase it only when the CI machine and application can handle the additional browsers.
Maven versus Gradle, and XML versus build discovery
| Decision | Prefer this when | Trade-off |
|---|---|---|
| Maven | The repository and CI already use Maven and Surefire. | Changing the established lifecycle can make discovery harder to diagnose. |
| Gradle | The project uses Gradle and its existing test task. | Custom task conventions may require merging, rather than replacing, current settings. |
| Build-tool discovery | You have a small suite and standard naming conventions. | Less convenient for named combinations of groups, parameters and packages. |
testng.xml |
You need explicit suite composition, parameters, groups or parallel settings. | An additional file must stay synchronized with package and class names. |
| Sequential tests | Tests share infrastructure or are still being stabilized. | Longer wall-clock runs. |
| Parallel tests | Tests are isolated and the machine has capacity for multiple browsers. | Shared state, ports, accounts and data can create intermittent failures. |
Troubleshoot the first failures
“Cannot find symbol” for TestNG annotations
The TestNG dependency is missing, in the wrong scope, or the IDE has not reloaded the build. Re-import the Maven or Gradle project, verify the dependency tree, and confirm the import is org.testng.annotations.Test.
No tests were found
Check that the class is under the configured test source directory, the method has @Test, and Surefire or Gradle has not excluded the class by its naming pattern. If using XML, verify the fully qualified class or package name.
Driver or browser startup error
Install the browser on the execution machine and make its driver available through the Selenium-supported mechanism or the machine’s PATH. Confirm that the browser version, driver and Selenium release are compatible. A dependency fix alone cannot install a missing browser.
The browser opens and immediately fails
Capture the complete exception and check whether the failure occurs in navigation, an assertion or teardown. Keep quit() in alwaysRun cleanup, then fix the earliest failure rather than suppressing it.
Best Value
XML suite errors
Validate element nesting, use fully qualified class names, and ensure package names match the compiled classes. A malformed or stale suite can prevent every test from starting even though the Java code compiles.
Parallel-only failures
Return to sequential execution, then identify shared drivers, accounts, downloads, ports and static variables. Make those resources independent before reducing the problem to a safe, small thread count.
Or skip the browser setup
If your goal is a repeatable page image rather than an interactive Selenium assertion, ScreenshotNeo provides a website screenshot API and MCP server. One GET request can return PNG, JPEG, WebP or PDF. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each cleanup step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers.
See the parameter reference and integration details in the ScreenshotNeo documentation. The following calls are complete examples; replace the URL and API key.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
cURL
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Python
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Node.js
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const body = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', body);
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients. Features include full-page lazy-image loading, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS or JavaScript, clicks, selector or network-idle waits, request and resource blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, TTL caching, signed image links, asynchronous webhooks, bulk capture for up to 100 URLs per call, usage reporting and an OpenAPI specification. Existing parameter names used by other screenshot APIs are accepted to ease migration.
The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan, and yearly billing gives two months free. Create a free ScreenshotNeo account to try it without a card.
Practical checklist
- Confirm the JDK, Selenium, TestNG, browser and driver versions are compatible.
- Add Selenium Java and TestNG through Maven or Gradle, using test scope/configuration.
- Create a class with
@BeforeMethod,@Testand@AfterMethod(alwaysRun = true). - Run the project’s normal Maven or Gradle test task before adding XML complexity.
- Add
testng.xmlfor explicit classes, packages, groups, parameters or parallel settings. - Keep each parallel test’s browser, data and mutable state isolated.
- Use the earliest exception and the build report to diagnose failures.
Frequently Asked Questions
Does every Selenium TestNG project require testng.xml?
No. A small project can run annotated classes through Maven Surefire or Gradle. Add the XML suite when explicit selection, parameters, groups or parallel controls justify the extra file.
Should one WebDriver be shared by all TestNG tests?
Usually no. Creating and quitting a driver per test method is the safer default, especially if you may later enable parallel execution.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Can TestNG replace Selenium WebDriver?
No. Selenium controls the browser; TestNG organizes, configures and reports the Java tests that call Selenium.
Quick Recap
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.




