How to Prioritize TestNG Tests with Selenium
Use TestNG priorities, dependencies, and groups to control Selenium test runs. Learn when each fits and how to avoid order-dependent browser tests.
Direct answer: Use TestNG’s priority to schedule otherwise independent test methods, with lower numbers running first. Use dependsOnMethods or dependsOnGroups only when a test truly needs another test to succeed. Use groups to select a quick set or a broader regression run. These mechanisms solve different problems; none automatically ranks tests by business risk.
For Selenium suites, keep tests independently runnable wherever possible. Selenium’s guidance is explicit: “Your tests should be able to run in any order, and not rely on other tests to complete in order to be successful.” Selenium test dependency guidance.
1. Choose the mechanism that matches your goal
| Goal | TestNG mechanism | What it means | Main caution |
|---|---|---|---|
| Run independent methods in a chosen sequence | @Test(priority = n) |
Lower priority values are scheduled first. | Ordering does not make one test a prerequisite for another. |
| A method needs a prior method or group to succeed | dependsOnMethods / dependsOnGroups |
Expresses a prerequisite; a hard dependent test is skipped if its prerequisite fails. | Creates a real execution dependency and can hide independent coverage behind a skip. |
| Run a selected subset | groups, suite XML, or command-line selection |
Choose a fast confidence set, feature set, or full regression set. | Group meaning is a team convention; define it and keep it current. |
| Reduce elapsed time | parallel and thread-count |
Runs work concurrently at a selected scope. | Parallelism is not importance ranking; browser sessions and test data must be isolated. |
TestNG documents these annotations, group selection, ordering, and parallel modes in its official documentation. Check the documentation matching the TestNG version pinned by your project before relying on version-specific behavior.
2. Add priority to independent Selenium tests
Here is a complete Java example using Selenium WebDriver and TestNG. Each test creates its own browser session and navigates to the page it needs, so the priority controls scheduling rather than sharing browser state. This assumes Selenium and TestNG are already on the project classpath and a compatible browser driver is available.
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.Test;
public class StoreSmokeTest {
private WebDriver openHomePage() {
WebDriver driver = new ChromeDriver();
driver.get("https://example.com");
return driver;
}
@Test(priority = 1, groups = {"smoke"})
public void homePageLoads() {
WebDriver driver = openHomePage();
try {
Assert.assertTrue(driver.getTitle().length() > 0, "Expected a page title");
} finally {
driver.quit();
}
}
@Test(priority = 2, groups = {"smoke"})
public void primaryContentIsVisible() {
WebDriver driver = openHomePage();
try {
Assert.assertTrue(driver.findElement(By.tagName("h1")).isDisplayed(),
"Expected the main heading to be visible");
} finally {
driver.quit();
}
}
@Test(priority = 10, groups = {"regression"})
public void footerIsPresent() {
WebDriver driver = openHomePage();
try {
Assert.assertTrue(driver.findElement(By.tagName("footer")).isDisplayed(),
"Expected the footer to be visible");
} finally {
driver.quit();
}
}
}
The example uses example.com as a placeholder target: replace it and the assertions with your application’s URL and behavior. A real suite should also use explicit waits for asynchronous UI state rather than assuming navigation means every element is ready.
Keep priority values readable
- Use a small, documented range that signals the intended sequence, such as early confidence checks followed by slower checks.
- Do not assign every test a unique number just to create a global order. That makes the suite harder to change and can disguise shared state.
- If a test must run after another only because they share created data or a logged-in session, reconsider setup and isolation before encoding an order.
3. Use dependencies only for real prerequisites
A dependency means the dependent method is not independently useful or valid unless its prerequisite has succeeded. For example, if a workflow test specifically consumes a resource created by a setup test, a dependency can express that relationship:
import org.testng.annotations.Test;
public class OrderWorkflowTest {
@Test(groups = "order-setup")
public void createOrderFixture() {
// Create a uniquely identified order fixture through an approved test setup path.
}
@Test(dependsOnMethods = "createOrderFixture")
public void verifyOrderCanBeOpened() {
// Verify the fixture created above, then clean it up where appropriate.
}
}
This is a schematic example: the setup and assertions are application-specific. A hard dependency makes the second method contingent on successful completion of the first; if setup fails, TestNG skips the dependent method. Prefer having a test establish its own preconditions when practical, so a setup failure does not suppress unrelated checks.
TestNG also supports dependsOnGroups. Use it when a method requires a group-level prerequisite, rather than to create a general-purpose phase ordering. The alwaysRun = true attribute can make a dependency soft: the dependent method can run even if the dependency failed. That is appropriate only when the earlier method’s success is not actually required and only ordering matters. See the TestNG dependency documentation.
4. Use groups and suite selection for quick runs
Groups are usually the clearest way to run a deliberately selected subset before the full suite. The labels below are examples; define their meaning locally so developers and CI jobs select the same tests consistently.
import org.testng.annotations.Test;
public class AccountTest {
@Test(groups = {"smoke", "account"})
public void signInPageIsAvailable() {
// Independent short availability check.
}
@Test(groups = {"regression", "account"})
public void passwordResetFlowWorks() {
// Broader flow check with isolated test data.
}
}
A suite XML file can select a group:
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Quick confidence run">
<test name="Smoke">
<groups>
<run>
<include name="smoke"/>
</run>
</groups>
<packages>
<package name="com.example.tests"/>
</packages>
</test>
</suite>
TestNG also documents command-line group inclusion and exclusion with -groups and -excludegroups, and method selection with -methods. For example, where your runner invokes TestNG directly:
java org.testng.TestNG -groups smoke testng.xml
java org.testng.TestNG -groups regression -excludegroups slow testng.xml
Build tools and CI wrappers may pass selection options differently; use the runner configuration for your project. XML-listed methods run in XML order by default in the documented suite context. Setting preserve-order="false" makes listed classes and methods run in an unpredictable order. XML order is not a substitute for modeling a true prerequisite or making tests independent.
5. Separate prioritization from parallel execution
If the goal is shorter wall-clock time, consider TestNG parallel execution after deciding which tests should run. TestNG documents methods, tests, classes, and instances scopes, with a thread count. These scopes distribute work differently: for example, parallel="methods" runs methods on separate threads, while parallel="tests" can run separate XML <test> blocks on different threads.
<suite name="Parallel smoke" parallel="tests" thread-count="2">
<test name="Chrome checks">
<classes>
<class name="com.example.tests.ChromeSmokeTest"/>
</classes>
</test>
<test name="Firefox checks">
<classes>
<class name="com.example.tests.FirefoxSmokeTest"/>
</classes>
</test>
</suite>
This configuration only makes sense if the named tests and their browser setup support that isolation. Before increasing threads, check that each worker has its own WebDriver instance, test data does not collide, cleanup is safe, and shared utilities are thread-safe. Dependencies still constrain dependent methods’ order. More threads do not make an important test run earlier, and concurrency can add resource contention.
6. If you need risk-based ordering
TestNG provides scheduling and selection controls, but the cited documentation does not define a universal risk score or weighting formula. A team can define a local heuristic using business impact, code areas changed, historical failures, and runtime, then use that policy to decide which tests belong in an early group. Treat the result as project policy, not a TestNG feature or a guaranteed prediction of failures.
Keep the rule explainable and review it when product architecture or failure patterns change. Groups can represent the resulting selections; priorities can order independent tests inside a run. Do not confuse a locally computed rank with a prerequisite.
7. Common problems and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| A test is skipped after another test fails | It has a hard method or group dependency. | Check whether the prerequisite is genuinely required. If not, remove the dependency and make the test establish its own data. |
| Tests pass only in one sequence | They share browser state, application data, or cleanup assumptions. | Make setup explicit per test, use unique fixtures, clean up safely, and run tests in varying order during development. |
| Priority appears not to order the whole suite | Ordering may be affected by class, XML, dependency, or parallel execution context; priority is a method scheduling attribute, not a global risk scheduler. | Inspect the actual selected methods and suite configuration. Avoid depending on a total order across concurrent work. |
| A smoke run includes too many tests or none | Group labels or suite/runner selection do not match annotations. | Verify annotation group names, included and excluded names, package selection, and the command used by CI. |
| Parallel runs fail intermittently | Shared WebDriver, test data collisions, static mutable state, or unsafe cleanup. | Give each execution its own driver and fixture, and reduce parallel scope until shared state is isolated. |
| Dependent test runs despite a failed prerequisite | The dependency may be soft, for example with alwaysRun = true. |
Remove soft behavior when success is required; otherwise make the dependent method handle missing state explicitly. |
| Browser element is missing in an early test | The page has not reached the expected asynchronous state. | Use a Selenium explicit wait for the condition before asserting; do not use priority as a timing workaround. |
8. Performance, reliability, and cost
- Earlier feedback: A small selected group can report basic failures before a full regression run. Keep the group focused and maintain its membership.
- Total runtime: Priority changes order, not the amount of browser work. Group selection reduces work for that run; parallelism can reduce elapsed time when the environment has capacity and tests are isolated.
- Reliability: Independent tests are easier to retry, distribute, and diagnose. Dependencies can cause skips, while shared state can make results sensitive to order.
- Infrastructure cost: Parallel browsers may consume more CI workers and browser resources at once. Choose thread count based on available capacity and stability, not a presumed universal speedup.
- Risk policy: The source documentation does not establish benchmark gains or a standard risk formula. Measure your own suite and keep project-specific prioritization rules visible.
9. Or skip the browser setup
If you need screenshots as part of a UI check or reporting workflow, ScreenshotNeo is a website screenshot API and MCP server. One GET request can return a PNG, JPEG, WebP, or PDF. The API can accept consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status. An MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents.
For a URL screenshot, use the documented API parameters and replace the placeholder key and target URL. See the ScreenshotNeo API documentation for configuration and the other supported options.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
It also supports full-page capture, CSS-selector element capture, device presets and custom viewports, retina scale, PDF settings, HTML/CSS capture, custom CSS and JavaScript, clicks, selector hiding, wait conditions, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, caching, signed public image links, async jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI spec.
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()
with open("shot.webp", "wb") as f:
f.write(r.content)
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(`Screenshot request failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo accepts the parameter names used by other screenshot APIs to make switching easier. All features are available on every plan: 1,000 shots/month free with no card; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free.
Create a free ScreenshotNeo account for 1,000 screenshots a month with no card.
10. FAQ
Does priority zero run before priority one?
Yes. TestNG schedules lower numeric priorities first.
Can I use priority to decide which test is most important?
You can use your team’s policy to assign an early position, but TestNG does not calculate business or regression risk for you.
Should every test depend on a setup test?
No. Dependencies are for genuine prerequisites. Prefer independent setup when it keeps a test meaningful on its own.
Does parallel mode ignore dependencies?
No. TestNG documents that dependent methods still respect their dependency ordering, though unrelated work may run concurrently.


