What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Use TestNG as the Java test runner and organizer, and Selenium WebDriver as the browser-control layer. A TestNG @Test method performs WebDriver actions, while TestNG annotations provide setup and cleanup, assertions determine outcomes, and optional testng.xml files select suites, groups, parameters, and classes.
This separation matters: Selenium’s documentation explains that WebDriver does not compare values, decide pass or fail, or provide test reporting. Those responsibilities belong to a test framework such as TestNG or JUnit. See the Selenium project’s runner guidance and component overview.
What TestNG and Selenium each do
| Component | Responsibility |
|---|---|
| Selenium WebDriver | Starts a browser session, opens URLs, locates elements, clicks, types, selects, and reads page state. |
| TestNG | Discovers and runs Java test methods, controls lifecycle hooks, groups and parameterizes tests, handles assertions through your chosen assertion library, and integrates execution with build tools and reports. |
A typical flow is: TestNG calls @BeforeMethod, your test creates or uses a driver, the @Test method performs browser steps and assertions, and @AfterMethod quits the session. The exact lifecycle scope should match your isolation needs.
Prerequisites and project dependencies
- JDK installed and selected in your IDE and build tool.
- Maven or Gradle.
- A browser such as Chrome, Edge, or Firefox.
- Compatible Selenium Java, browser, driver, TestNG, and JDK versions.
Selenium’s installation guide uses a Maven property such as ${selenium.version} rather than declaring a permanently latest version. Check the current Selenium downloads information when creating a project. The TestNG homepage currently displays release 7.9.0 and states that TestNG 7.6.0 and later require JDK 11 or higher; verify those statements against the current TestNG homepage before pinning versions.
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 glitches#1 Best Overall
Maven
Put Selenium and TestNG on the test classpath. Replace the Selenium property with the version you have verified for your environment.
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<selenium.version>REPLACE_WITH_VERIFIED_VERSION</selenium.version>
<testng.version>7.9.0</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>
Use the TestNG Maven Surefire provider or your IDE’s TestNG integration so the build actually discovers TestNG tests. Confirm the provider configuration against the versions used by your Maven setup.
Gradle
dependencies {
testImplementation("org.seleniumhq.selenium:selenium-java:REPLACE_WITH_VERIFIED_VERSION")
testImplementation("org.testng:testng:7.9.0")
}
tasks.test {
useTestNG()
}
Do not treat 7.9.0 as a timeless recommendation: TestNG releases and JDK requirements change. If your project must run on JDK 8, select a TestNG release that officially supports it and verify the matching documentation.
Create a first Selenium TestNG class
The following example uses Chrome. Selenium’s first-script documentation demonstrates the same basic sequence: create a ChromeDriver, navigate, interact, and quit. Selenium Manager may obtain a suitable driver in current Selenium releases, but browser and driver setup remains environment-dependent; see the driver-session guidance.
package example;
import java.time.Duration;
import org.openqa.selenium.By;
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 SearchTest {
private WebDriver driver;
@BeforeMethod
public void setUp() {
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
}
@Test
public void pageTitleContainsExpectedText() {
driver.get("https://example.com/");
String heading = driver.findElement(By.cssSelector("h1")).getText();
Assert.assertEquals(heading, "Example Domain");
}
@AfterMethod(alwaysRun = true)
public void tearDown() {
if (driver != null) {
driver.quit();
driver = null;
}
}
}
Why this lifecycle is safe
@BeforeMethodcreates a fresh browser for each test method, reducing state leakage.@AfterMethod(alwaysRun = true)runs cleanup even when the test fails or an earlier configuration method throws.quit()closes the session and its browser windows; it is preferable to leaving processes running after a test.- The field is private to the class, so tests do not accidentally share a driver across classes.
Use explicit waits for application conditions when possible. An implicit wait can help with simple element lookup, but mixing many waiting strategies can make failures difficult to diagnose. Keep assertions in TestNG (or another assertion library) rather than expecting WebDriver to decide whether behavior is correct.
Run the test
From an IDE
Right-click the class or its @Test method and choose the IDE’s TestNG run action. If the class appears as an ordinary Java class, install or enable the IDE’s TestNG integration and confirm that TestNG is on the test classpath.
From Maven
mvn test
Surefire must be configured to discover TestNG tests. If your project uses naming filters or an explicit suite file, ensure those settings include this class.
Rank #2
From Gradle
./gradlew test
The useTestNG() setting is required; without it Gradle’s default test engine may not execute TestNG classes.
Use testng.xml for repeatable suites
TestNG’s documented workflow is annotated test logic plus test information in testng.xml or a build file. A suite can contain one or more tests, and each TestNG test can contain one or more classes. The official reference is TestNG Documentation.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="smoke-suite" verbose="1">
<test name="homepage">
<classes>
<class name="example.SearchTest"/>
</classes>
</test>
</suite>
Run the XML from your IDE’s TestNG action, or configure Maven/Gradle to pass it as the selected suite according to that build tool’s TestNG integration.
Select individual methods
<methods>
<include name="pageTitleContainsExpectedText"/>
</methods>
Place the <methods> element inside a class declaration when you need a narrow selection. Keep suite files readable; use them for named CI flows and deliberate selection rather than duplicating every test detail.
Groups, parameters, and data providers
Groups
@Test(groups = {"smoke", "search"})
public void pageTitleContainsExpectedText() { ... }
Include or exclude groups in XML with <groups>, <run>, <include>, and <exclude>. Groups let CI run a smoke subset without maintaining a second copy of the tests.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →XML parameters
<parameter name="baseUrl" value="https://example.com/"/>
import org.testng.annotations.Parameters;
@Parameters("baseUrl")
@BeforeMethod
public void setUp(String baseUrl) {
driver = new ChromeDriver();
driver.get(baseUrl);
}
Parameter scope matters: a suite, test, class, or method can receive different values. Keep secrets out of XML committed to source control; inject credentials through your CI secret mechanism.
Data providers
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@DataProvider(name = "queries")
public Object[][] queries() {
return new Object[][] {{"selenium"}, {"testng"}};
}
@Test(dataProvider = "queries")
public void searchTermIsAccepted(String query) {
// use query in a WebDriver flow
}
Data providers are useful for repeating one test with controlled inputs. Ensure each invocation has isolated browser and application data when tests can run in parallel.
Rank #3
Choose the right lifecycle scope
| Annotations | Typical use | Isolation trade-off |
|---|---|---|
@BeforeSuite/@AfterSuite |
One-time suite resources such as reporting or external fixtures. | Too broad for a shared browser in most UI tests. |
@BeforeTest/@AfterTest |
Resources for an XML <test> section. |
May share state across classes. |
@BeforeClass/@AfterClass |
Setup once per Java class. | Faster, but browser state can leak between methods. |
@BeforeMethod/@AfterMethod |
Independent browser session per test method. | More startup time; usually the safest default. |
TestNG also provides group-level hooks. Select the narrowest scope that satisfies performance and data-isolation requirements. A shared driver is not automatically safe when tests execute in parallel.
Parallel execution and remote browsers
TestNG supports parallel policies and Selenium supports local drivers as well as remote execution through Selenium Server/Grid; Selenium describes these architectures in its components documentation. Parallel execution does not make shared browser sessions, static fields, downloaded files, accounts, or test data thread-safe.
- Use one driver per parallel test thread or method.
- Do not store a mutable driver in a static field.
- Give each test unique users, records, and output paths.
- Start with a small parallel count and watch for environment saturation.
- For remote runs, create a
RemoteWebDriverwith the Grid endpoint and suitable browser options.
Faster execution is a design goal, not a guaranteed result. Measure your own suite and reduce parallelism when failures indicate shared-state or infrastructure contention.
Troubleshooting common failures
“Cannot find symbol” for TestNG annotations
Cause: TestNG is missing from the test classpath or the IDE has not reloaded the build.
Fix: Confirm the dependency, refresh Maven/Gradle, and verify that imports use org.testng.annotations.*.
No tests were run
Cause: The build is using its default JUnit engine, the class or method is not annotated with @Test, naming filters exclude it, or the XML names the wrong class.
Free tools Windows power users keep installed
One-click scans. No signup required.
Fix: Enable useTestNG() in Gradle or configure Maven Surefire for TestNG, then run the class directly to isolate discovery from suite configuration.
Rank #4
SessionNotCreatedException
Cause: Browser, driver, Selenium, or JDK versions are incompatible, or the browser is unavailable in the execution environment.
Fix: Check installed browser versions, Selenium’s driver guidance, JDK selection, and whether the CI image contains the browser. Avoid hard-coded driver paths that do not exist on the runner.
StaleElementReferenceException or intermittent missing elements
Cause: The page re-rendered after the element was located, or the test races application readiness.
Recommended Free Tools
Fix: Locate the element after the relevant state change and wait for a specific condition instead of adding arbitrary long sleeps.
Browsers remain after failures
Cause: Cleanup was skipped or the driver field was never initialized.
Fix: Keep alwaysRun = true, guard against null, and call quit() rather than only closing one window.
Parallel tests interfere with each other
Cause: Shared driver instances, accounts, files, ports, or server-side records.
Best Value
Fix: isolate those resources per invocation, remove mutable static state, and lower parallelism while correcting data ownership.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
ScreenshotNeo provides a website screenshot API and MCP server when your task is to capture a page rather than operate it interactively. One GET request returns PNG, JPEG, WebP, or PDF. Its cleanup options accept cookie and consent banners before capture and remove more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.
Use the ScreenshotNeo API documentation for all parameters. 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)
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}`);
ScreenshotNeo also supports full-page and element captures, dark mode, device presets and custom viewports, retina scale, PDF paper and page-range controls, custom CSS/JavaScript, clicks, selector waits, network-idle waits, blocked resources, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, usage reporting, and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to 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. Create a free ScreenshotNeo account.
Practical design checklist
- Keep browser actions in page objects or focused helper methods as the suite grows.
- Use stable selectors and explicit, state-based waits.
- Give each test one clear behavior and assertion outcome.
- Choose
@BeforeMethodisolation unless measured reuse is safe. - Keep environment URLs and non-secret parameters configurable.
- Run a small XML smoke suite in CI, then broader groups on an appropriate schedule.
- Record browser, JDK, Selenium, TestNG, and build-tool versions with failures.
Frequently Asked Questions
Is TestNG required to use Selenium WebDriver?
No. Selenium WebDriver can be used with other Java test runners, including JUnit. TestNG is an option that supplies lifecycle annotations, grouping, parameters, execution control, and reporting integration.
What is the purpose of a testng.xml file?
It describes a named TestNG suite: the tests and classes to execute, selected methods, groups, parameters, and sometimes parallel settings. It is useful when repeatable selection belongs outside Java source code.
Should one WebDriver instance be shared by all TestNG tests?
Usually not for independent UI tests. A per-method or per-class session limits state leakage. Sharing can reduce startup cost but requires strict state reset and thread-safe design, especially under parallel execution.
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.

