Resource library

QA How-To

Selenium Cheat Sheet: Locators, Waits, and Commands

Use this selenium cheat sheet for current WebDriver locators, waits, actions, frames, windows, screenshots, Grid, and runnable Java examples for QA teams.

23 min read | 2,664 words

TL;DR

This selenium cheat sheet uses current Selenium 4 Java APIs. Create a driver, locate with `By`, synchronize through `WebDriverWait`, interact with `WebElement`, switch context explicitly, capture evidence on failure, and always call `quit()` in teardown.

Key Takeaways

  • Create and quit one isolated WebDriver session per test unless a proven design requires broader scope.
  • Prefer unique stable IDs, names, or test attributes before CSS and relationship-based XPath.
  • Use explicit waits for observable state and avoid fixed sleeps.
  • Switch into frames, windows, alerts, and shadow roots before using commands in that context.
  • Use native WebDriver interactions first, with JavaScript only for behavior that the requirement truly needs.
  • Capture screenshots, page source, URL, browser logs, and correlation data before quitting a failed session.
  • Keep Selenium API commands inside business-focused page components rather than test scripts.

This selenium cheat sheet is a practical reference for the Selenium 4 WebDriver commands an SDET uses most: session setup, locators, waits, element interactions, frames, windows, alerts, actions, cookies, screenshots, and Grid. The reliable pattern is always the same: enter a known browser state, locate by stable meaning, wait for the exact condition, perform a user-like action, and verify an observable result.

Examples use Java and JUnit 5 with APIs that remain current in Selenium 4. Keep your build on a maintained Selenium release, let Selenium Manager handle ordinary local driver discovery, and adapt the same WebDriver interfaces for remote execution. Bookmark the command tables, but read the explanations before copying a snippet into a framework.

TL;DR

ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new");
WebDriver driver = new ChromeDriver(options);
try {
    driver.get("https://example.com");
    By heading = By.cssSelector("h1");
    String text = new WebDriverWait(driver, Duration.ofSeconds(10))
            .until(ExpectedConditions.visibilityOfElementLocated(heading))
            .getText();
    Assertions.assertEquals("Example Domain", text);
} finally {
    driver.quit();
}
Task API Important note
Open URL driver.get(url) Wait for the page's defining state after navigation
Find one driver.findElement(by) Throws NoSuchElementException if absent
Find many driver.findElements(by) Returns an empty list if absent
Wait new WebDriverWait(driver, duration).until(condition) Use an observable condition
Type element.sendKeys(value) Clear only when the product behavior permits it
Switch frame driver.switchTo().frame(...) Return with defaultContent()
New tab driver.switchTo().newWindow(WindowType.TAB) Store handles for deterministic switching
Screenshot ((TakesScreenshot) driver).getScreenshotAs(...) Capture before quit()
End session driver.quit() Closes all windows and the driver process

1. Selenium Cheat Sheet: Driver Setup and Teardown

Create the driver in setup and guarantee cleanup in teardown. Selenium Manager is integrated with Selenium 4 and can manage ordinary browser-driver discovery when you call a local driver constructor. Do not hard-code a developer-specific executable path.

import java.time.Duration;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

abstract class UiTestBase {
    protected WebDriver driver;

    @BeforeEach
    void createDriver() {
        ChromeOptions options = new ChromeOptions();
        if (Boolean.parseBoolean(System.getProperty("headless", "true"))) {
            options.addArguments("--headless=new");
        }
        options.setPageLoadTimeout(Duration.ofSeconds(30));
        driver = new ChromeDriver(options);
    }

    @AfterEach
    void quitDriver() {
        if (driver != null) {
            driver.quit();
        }
    }
}

close() closes the current top-level window. quit() ends the session and closes every associated window. Teardown should normally call quit(). One session per test gives strong isolation for cookies, storage, windows, and browser state. Shared sessions reduce startup cost but create order dependence and make parallel execution difficult.

Useful option methods include addArguments, addExtensions, setAcceptInsecureCerts, setPageLoadStrategy, and browser-specific experimental options. Enable insecure certificates only in a controlled test environment. Never disable security behavior merely to make an unrelated test pass.

For a remote grid, construct RemoteWebDriver with a trusted grid URL and options. Do not place grid credentials directly in a logged URL. Inject secrets through approved runtime configuration and redact capability output.

2. Navigation, Browser State, and Timeouts

Navigation commands control the current top-level browsing context. A navigation call returning does not guarantee that a single-page application has fetched its data or rendered the component your test needs. Follow navigation with an application-specific wait.

driver.get("https://example.com");
driver.navigate().to("https://example.com/help");
driver.navigate().back();
driver.navigate().forward();
driver.navigate().refresh();

String url = driver.getCurrentUrl();
String title = driver.getTitle();
String source = driver.getPageSource();

WebDriver timeouts have different purposes:

Timeout Java API Scope
Page load driver.manage().timeouts().pageLoadTimeout(duration) Navigation completion
Script driver.manage().timeouts().scriptTimeout(duration) Asynchronous JavaScript execution
Implicit driver.manage().timeouts().implicitlyWait(duration) Element lookup
Explicit new WebDriverWait(driver, duration) One declared condition

Prefer explicit waits for application behavior. Keep implicit wait at zero or a consciously small suite-wide value. A large implicit wait affects every element lookup, including lookups inside explicit wait conditions, which complicates failure duration.

Use driver.manage().window().setSize(new Dimension(width, height)) when viewport behavior is under test. maximize() depends on the host window manager and may behave differently in headless or container environments. Choose a defined viewport for responsive assertions.

Page source is diagnostic evidence, not a perfect serialization of every live browser property. Attributes and JavaScript properties differ. Use getDomAttribute, getDomProperty, or getAttribute according to the value you need, and verify current Selenium documentation when semantics matter.

3. Selenium Locator Cheat Sheet

Selenium supports ID, name, class name, tag name, link text, partial link text, CSS selector, and XPath strategies. Start with a unique, stable application contract. A locator must be precise and resilient, not merely short.

By.id("email");
By.name("username");
By.className("error-message");       // One class token only
By.tagName("button");
By.linkText("Account settings");
By.partialLinkText("Account");
By.cssSelector("[data-testid='save-profile']");
By.xpath("//tr[td[normalize-space()='INV-42']]//button[@name='open']");
Strategy Best use Main risk
ID Unique, durable element ID Generated or reused IDs
Name Stable form and action names Duplicate names
Test attribute Explicit automation contract Poor naming or overuse on every node
CSS Attributes, classes, hierarchy Styling classes and deep structure
XPath Text and meaningful relationships Absolute paths and broad partial matches
Link text Stable visible anchor text Copy and localization changes
Class name One stable class token Styling refactors and invalid compound value

Selenium 4 relative locators such as RelativeLocator.with(By.tagName("input")).below(label) can express spatial relationships, but layout and responsive changes affect them. Prefer a semantic DOM connection when one exists.

Use findElement when absence is exceptional. Use findElements to inspect an optional collection because it returns an empty list. Avoid catching NoSuchElementException as a routine way to test absence. The dynamic XPath in Selenium Java guide covers safe runtime XPath construction.

4. Find Elements and Read Their State

WebElement represents a remote reference to a DOM element. If the application removes or replaces that node, the reference can become stale. Store stable By values in page components and locate close to the action when redraws are common.

WebElement email = driver.findElement(By.name("email"));
List<WebElement> rows = driver.findElements(By.cssSelector("table tbody tr"));

String text = email.getText();
String value = email.getAttribute("value");
String domName = email.getDomAttribute("name");
String propertyValue = email.getDomProperty("value");
boolean displayed = email.isDisplayed();
boolean enabled = email.isEnabled();
boolean selected = email.isSelected();
Rectangle rectangle = email.getRect();
String tag = email.getTagName();

getText() returns rendered element text according to WebDriver behavior. Form input values are properties or attributes, not visible child text, so getText() on an input often returns an empty string. Read the value through the appropriate property.

isDisplayed() answers Selenium's displayedness algorithm for a located element. It does not guarantee that another element will not intercept a click or that the control is inside the viewport. isEnabled() reflects enabled state, but application-specific aria-disabled behavior may require an explicit assertion.

Search within an element to constrain scope:

WebElement dialog = driver.findElement(By.cssSelector("[role='dialog']"));
WebElement confirm = dialog.findElement(By.cssSelector("button[name='confirm']"));

For an open shadow root, call host.getShadowRoot() and use the returned SearchContext. Page-level XPath and CSS selectors do not automatically cross a shadow boundary.

5. Selenium Waits and ExpectedConditions Reference

An explicit wait repeatedly evaluates a condition until it returns a successful value or the timeout expires. Wait for the state required by the next action, such as a result row appearing, a button becoming enabled, or a URL reaching a known route.

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
By save = By.cssSelector("button[name='save']");

WebElement visible = wait.until(
        ExpectedConditions.visibilityOfElementLocated(save));
WebElement clickable = wait.until(
        ExpectedConditions.elementToBeClickable(save));
boolean textReady = wait.until(
        ExpectedConditions.textToBePresentInElementLocated(save, "Save"));
boolean gone = wait.until(
        ExpectedConditions.invisibilityOfElementLocated(By.cssSelector(".spinner")));

Frequently useful conditions include:

Goal ExpectedConditions method Returns
Node exists presenceOfElementLocated(by) WebElement
Node is displayed visibilityOfElementLocated(by) WebElement
Element is visible and enabled elementToBeClickable(by) WebElement
All elements visible visibilityOfAllElementsLocatedBy(by) List<WebElement>
Text included textToBePresentInElementLocated(by, text) Boolean
Attribute value attributeToBe(element, name, value) Boolean
Node becomes stale stalenessOf(element) Boolean
URL matches urlMatches(regex) Boolean
Frame ready frameToBeAvailableAndSwitchToIt(locator) WebDriver
Alert exists alertIsPresent() Alert

elementToBeClickable does not model every overlay, animation, or product rule. A domain-specific wait can use a lambda and return the desired element when ready. Keep timeouts bounded, messages meaningful, and ignored exceptions narrow. See the Selenium WebDriverWait guide for advanced custom conditions.

6. Click, Type, Submit, and Upload Files

Use native WebDriver interactions because they follow browser input behavior more closely than JavaScript shortcuts. Verify the resulting state instead of treating a completed command as proof of success.

WebElement field = wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.name("email")));
field.clear();
field.sendKeys("qa@example.test");

WebElement save = wait.until(ExpectedConditions.elementToBeClickable(
        By.cssSelector("button[type='submit']")));
save.click();

wait.until(ExpectedConditions.visibilityOfElementLocated(
        By.cssSelector("[role='status']")));

clear() is suitable only when replacing the field content matches the scenario. Some JavaScript controls react differently to keyboard shortcuts, incremental input, or blur. Tests should reproduce the required user interaction. submit() submits the form associated with an element, but clicking the actual submit control usually represents product behavior more clearly.

Upload a local file by sending its absolute path to an <input type="file">:

Path file = Path.of("src/test/resources/sample.pdf").toAbsolutePath();
WebElement upload = driver.findElement(By.cssSelector("input[type='file']"));
upload.sendKeys(file.toString());

Do not automate the operating system file picker when WebDriver can set the file input directly. With RemoteWebDriver, configure file transfer behavior supported by the grid, commonly a LocalFileDetector, when the client-side file must be uploaded to a remote node.

For click interception, inspect overlays, viewport, animation, and enabled state. A JavaScript click bypasses user hit testing and can hide a real defect. Use it only when the requirement intentionally targets JavaScript behavior that a user gesture does not represent.

7. Selects, Checkboxes, Keyboard, Mouse, and Scrolling

Selenium's Select class works with native <select> elements, not custom dropdown divs. Select by stable value or visible label, then verify selection.

Select country = new Select(driver.findElement(By.id("country")));
country.selectByValue("US");
String selected = country.getFirstSelectedOption().getAttribute("value");
Assertions.assertEquals("US", selected);

WebElement newsletter = driver.findElement(By.name("newsletter"));
if (!newsletter.isSelected()) {
    newsletter.click();
}

Use Actions for composite keyboard and pointer interactions:

WebElement source = driver.findElement(By.id("source"));
WebElement target = driver.findElement(By.id("target"));
new Actions(driver)
        .moveToElement(source)
        .clickAndHold()
        .moveToElement(target)
        .release()
        .perform();

new Actions(driver)
        .keyDown(Keys.CONTROL)
        .sendKeys("a")
        .keyUp(Keys.CONTROL)
        .sendKeys("replacement")
        .perform();

Keyboard modifiers differ by platform, so use the appropriate key when the behavior is platform-dependent. Drag-and-drop widgets also vary in their event implementation. Test the real supported behavior rather than assuming one action chain works for every library.

WebDriver often scrolls elements into view for interaction. When explicit scrolling is part of the scenario, Selenium's wheel input actions include scrollToElement and scrollByAmount. JavaScript scrollIntoView() is available as a fallback for a purposeful scroll operation, but it can place content under sticky headers. Always wait for the resulting rendered state.

8. Frames, Windows, Tabs, and Alerts

WebDriver commands operate in the current browsing context. Switch explicitly and restore context in a finally block when later steps depend on the original page.

By frame = By.cssSelector("iframe[title='Payment']");
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(frame));
try {
    driver.findElement(By.name("card-number")).sendKeys("4111111111111111");
} finally {
    driver.switchTo().defaultContent();
}

parentFrame() moves up one frame. defaultContent() returns to the top document. A missing element inside an iframe often indicates wrong context rather than a weak locator.

Manage windows by handle, not set ordering:

String original = driver.getWindowHandle();
driver.switchTo().newWindow(WindowType.TAB);
driver.get("https://example.com/help");
driver.close();
driver.switchTo().window(original);

When the application opens a new window, capture existing handles, click, wait until the handle count increases, compute the new handle, and switch to it. getWindowHandles() returns a set, so do not assume its iteration order identifies the newest window.

Handle JavaScript alerts through Alert:

Alert alert = wait.until(ExpectedConditions.alertIsPresent());
String message = alert.getText();
alert.accept();
// For a prompt: alert.sendKeys("value");
// To cancel: alert.dismiss();

An unexpected alert can block ordinary commands. Capture its text when safe and determine whether it is expected product behavior or an environmental interruption.

9. Cookies, Storage, JavaScript, and Screenshots

WebDriver exposes cookie management for the current domain. Navigate to the domain before adding a cookie, and never print authentication values in logs.

Cookie locale = new Cookie.Builder("locale", "en-US")
        .path("/")
        .isSecure(true)
        .build();
driver.manage().addCookie(locale);
Cookie actual = driver.manage().getCookieNamed("locale");
driver.manage().deleteCookieNamed("locale");

Use JavascriptExecutor for a deliberate browser script, not as a default interaction layer:

JavascriptExecutor js = (JavascriptExecutor) driver;
String readyState = (String) js.executeScript("return document.readyState");
Object token = js.executeScript("return window.localStorage.getItem('theme')");

Access to storage can be helpful for setup or diagnosis, but setting application state behind the UI changes the test boundary. Document that choice and cover the real UI path elsewhere when it carries user risk. Never retrieve or expose production tokens.

Capture screenshots before quitting:

Path destination = Path.of("build/artifacts/failure.png");
Files.createDirectories(destination.getParent());
Path source = ((TakesScreenshot) driver)
        .getScreenshotAs(OutputType.FILE).toPath();
Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);

Some drivers support element screenshots with element.getScreenshotAs(...). Combine the image with URL, title, browser capabilities, safe test ID, page source when permitted, and application correlation data. A screenshot alone cannot reveal network or backend state.

10. Page Components, Assertions, and Failure Evidence

Keep tests focused on behavior. Page and component objects should own locators, waits, and browser mechanics, while assertions remain visible at the scenario or domain assertion layer. Avoid generic wrappers that make every click look identical.

final class LoginPage {
    private final WebDriver driver;
    private final WebDriverWait wait;
    private final By email = By.name("email");
    private final By password = By.name("password");
    private final By signIn = By.cssSelector("button[type='submit']");

    LoginPage(WebDriver driver) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    }

    void signIn(String user, String secret) {
        wait.until(ExpectedConditions.visibilityOfElementLocated(email))
                .sendKeys(user);
        driver.findElement(password).sendKeys(secret);
        wait.until(ExpectedConditions.elementToBeClickable(signIn)).click();
    }
}

Do not log secret. Create a separate destination component that waits for a defining element and exposes an observable account name or status. A test can then assert the business result rather than the absence of an exception.

On failure, preserve the first failure before retries. Capture artifacts in a JUnit extension or test framework listener while the driver is still valid. Include test and application revision, environment, browser version, viewport, current context, timestamps, and safe data identity. Redact page source if it can contain secrets or personal information.

Use soft assertions only when collecting several independent observations provides more value than stopping. Do not continue destructive actions after a failed prerequisite. Clear assertion messages should state expected business behavior and actual safe evidence.

11. RemoteWebDriver, Grid, and Parallel Execution

RemoteWebDriver sends WebDriver commands to a remote endpoint such as Selenium Grid. The test APIs remain the same, while browser options become requested capabilities.

URI gridUri = URI.create(System.getenv().getOrDefault(
        "SELENIUM_GRID_URL", "http://localhost:4444"));
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless=new");
WebDriver driver = new RemoteWebDriver(gridUri.toURL(), options);

Treat the grid URL as configuration and protect credentials. Use W3C standard capabilities plus documented vendor namespaced options for a cloud provider. Do not invent top-level capability keys. Log sanitized session ID, browser name and version, platform, and node-related metadata made available by your provider.

Parallel tests need more than separate driver objects. Isolate accounts, database records, downloads, file names, ports, report paths, and external resource leases. Remove static mutable driver fields. A ThreadLocal<WebDriver> can associate a session with a thread, but it does not make shared users or test data safe.

Use unique, traceable case data and targeted cleanup. Do not delete all orders or reset a shared environment during teardown. Cap concurrency based on application and grid capacity, then measure queue time and first-attempt failures.

When a remote session cannot start, capture the server response, requested sanitized capabilities, grid status, and node logs. Retrying indefinitely can amplify an outage. One bounded infrastructure retry may be a policy choice, but it must remain visible in reporting.

12. Selenium Cheat Sheet: Runnable Smoke Test and Review

This complete JUnit test uses a local data URL, so the browser interaction does not depend on an external site. It demonstrates setup, stable locators, explicit waits, form interaction, a result assertion, and guaranteed teardown.

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

class SeleniumSmokeTest {
    @Test
    void submitsProfile() {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--headless=new");
        WebDriver driver = new ChromeDriver(options);
        try {
            String html = """
                <label>Email <input name='email'></label>
                <button name='save'
                  onclick="document.querySelector('[role=status]').textContent=
                           document.querySelector('[name=email]').value">Save</button>
                <p role='status'></p>
                """;
            driver.get("data:text/html;charset=utf-8,"
                    + URLEncoder.encode(html, StandardCharsets.UTF_8));

            WebDriverWait wait = new WebDriverWait(
                    driver, Duration.ofSeconds(5));
            driver.findElement(By.name("email")).sendKeys("qa@example.test");
            wait.until(ExpectedConditions.elementToBeClickable(
                    By.name("save"))).click();

            String result = wait.until(ExpectedConditions.visibilityOfElementLocated(
                    By.cssSelector("[role='status']"))).getText();
            assertEquals("qa@example.test", result);
        } finally {
            driver.quit();
        }
    }
}

Before copying any command, review context, synchronization, isolation, result, and evidence. Ask which window or frame is active, what state makes the target ready, which resources the test owns, what observable result proves success, and what artifacts will explain failure.

For systematic failure analysis, keep the Selenium exception troubleshooting guide beside this command reference. API recall helps you write code, but diagnostic reasoning keeps the suite trustworthy.

Interview Questions and Answers

Q: What is the difference between findElement and findElements?

findElement returns the first matching element and throws NoSuchElementException when none exists. findElements returns every match and returns an empty list when none exists. I use the collection form for optional state or when count is part of the assertion.

Q: Why are explicit waits better than Thread.sleep?

An explicit wait polls for a meaningful condition and can finish as soon as it succeeds. A fixed sleep always consumes its full duration and still fails if the event takes longer. Conditions also create more useful diagnostic intent.

Q: What is the difference between close and quit?

close() closes the current window. quit() ends the complete WebDriver session and closes all associated windows. Test teardown normally calls quit() to prevent leaked browser and driver processes.

Q: How do you choose a Selenium locator?

I prefer a unique stable ID, name, or documented test attribute. CSS is concise for attributes and hierarchy, while XPath is useful for text and semantic relationships. I avoid generated classes, absolute paths, and global indexes.

Q: What does elementToBeClickable guarantee?

It waits until an element is visible and enabled. It does not guarantee that an overlay, animation, or application-specific condition cannot block the click. I inspect intercepted clicks and wait for the actual blocking state to clear.

Q: How do you automate an element inside an iframe?

I wait for the frame and switch to it before locating the element. After the frame workflow, I return through parentFrame() or defaultContent() as appropriate. A page-level locator cannot automatically search inside another frame.

Q: How do you make Selenium tests parallel-safe?

I isolate driver sessions, test users, records, files, downloads, and report artifacts. I remove static mutable state and use targeted resource leasing where sharing is unavoidable. Thread-local drivers alone do not isolate business data.

Q: When is JavaScriptExecutor appropriate?

It is appropriate for a deliberate script-based observation or operation required by the test design. It should not be the default fix for clicks and typing because it bypasses user interaction behavior. I document the changed boundary and verify the resulting state.

Common Mistakes

  • Sharing one browser across tests and allowing cookies or windows to leak.
  • Setting webdriver.chrome.driver to a developer-specific path.
  • Combining long implicit waits with explicit waits.
  • Copying absolute XPath or layout classes into page objects.
  • Calling getText() for an input's value.
  • Treating click completion as proof that the business operation succeeded.
  • Using JavaScript click to hide overlays or intercepted input.
  • Selecting the newest window by set iteration order.
  • Searching inside an iframe or shadow root without switching context.
  • Using native Select against a custom dropdown component.
  • Logging credentials, cookies, tokens, or sensitive page source.
  • Making drivers thread-local while sharing the same account and records.
  • Capturing screenshots after the driver has already quit.
  • Retrying every browser failure instead of classifying its cause.

Conclusion

A useful selenium cheat sheet is more than a list of method names. Stable Selenium automation combines correct commands with semantic locators, explicit application-state waits, isolated sessions and data, explicit context switching, and diagnostic evidence captured before teardown.

Run the self-contained smoke test, then map each pattern to one component in your suite. Centralize lifecycle and artifacts, keep locators with their components, and make every interaction end with an observable assertion rather than another blind command.

Interview Questions and Answers

What is the difference between findElement and findElements?

`findElement` returns the first match and throws when no match exists. `findElements` returns a list and uses an empty list for no matches. I use the latter when optional presence or count is part of the behavior.

Explain implicit and explicit waits in Selenium.

Implicit wait affects element lookup across the driver session. Explicit wait polls one declared condition within a bound. I primarily use explicit waits because they state the required application condition and avoid combining them with a large implicit timeout.

How do you handle StaleElementReferenceException?

I determine which state transition replaced the DOM node, wait for that transition, and locate the current element close to the action. I avoid caching elements on reactive pages. Blindly retrying every stale reference can hide an unstable workflow.

How do close() and quit() differ?

`close()` closes only the current top-level window. `quit()` terminates the WebDriver session and all its windows. Reliable teardown uses `quit()` in a guaranteed cleanup path.

How do you choose between CSS and XPath?

I choose CSS for stable attributes and straightforward hierarchy. I choose XPath when text, an ancestor, a sibling, or a table-cell relationship is the durable signal. I prefer a stable test hook over either complex selector.

How do you switch to an iframe safely?

I wait for the frame and switch using `frameToBeAvailableAndSwitchToIt`. I execute the frame-specific workflow and restore the expected context in a `finally` block. Frame context is part of test state and should be explicit.

What artifacts do you collect for a Selenium failure?

I capture the screenshot, URL, title, relevant DOM, sanitized browser logs, capabilities, test and application revision, timestamps, and a correlation or safe data ID. I collect them before quitting and preserve the first failure even if a retry later passes. Every artifact follows the team's retention and redaction policy.

How does Selenium Grid change test code?

The test continues using the WebDriver interface, but session creation uses `RemoteWebDriver` and browser options sent to the grid. The framework must manage configuration, credentials, capacity, artifacts, and parallel resource isolation. I correlate failures with the remote session and node rather than the client machine alone.

Frequently Asked Questions

What are the most important Selenium WebDriver commands?

Core commands include `get`, `findElement`, `findElements`, `click`, `sendKeys`, `getText`, explicit `until` waits, context switching, screenshot capture, and `quit`. Reliable tests combine those commands with a stable locator and an observable result.

Does Selenium 4 require ChromeDriver setup?

Selenium Manager can handle ordinary driver discovery or acquisition when you create a local browser driver and no driver is otherwise configured. The browser still needs to run in the environment, and managed CI or enterprise environments may use a preconfigured driver or remote grid.

Which Selenium locator is best?

A unique stable ID, name, or documented test attribute is usually the strongest option. Use CSS for concise attribute and hierarchy selection, and XPath when text or a meaningful element relationship identifies the target.

What is the recommended Selenium wait?

Use `WebDriverWait` with an `ExpectedConditions` condition or a small custom condition describing application readiness. Avoid fixed sleeps and keep implicit wait zero or deliberately small when explicit waits are your primary strategy.

How do I take a screenshot in Selenium Java?

Cast the driver to `TakesScreenshot` and call `getScreenshotAs` with `OutputType.FILE`, `BYTES`, or `BASE64`. Capture it before calling `quit()` and store it with safe run metadata.

How do I open and switch to a new tab?

Use `driver.switchTo().newWindow(WindowType.TAB)` when the test creates the tab directly. When the application opens it, wait for a new handle, compute the handle not present before the click, and switch by that handle.

Can Selenium automate shadow DOM?

Selenium 4 can access an open shadow root through `WebElement.getShadowRoot()` and locate inside the returned search context. Page-level selectors do not cross the boundary, and a closed shadow root needs an application-supported alternative.

Related Guides