BLOG POSTS
Selenium findElement and findElements Examples

Selenium findElement and findElements Examples

Selenium WebDriver’s findElement and findElements methods are fundamental building blocks for web automation testing, allowing you to locate and interact with HTML elements on web pages. While both methods use the same locator strategies, they behave differently when elements are found or missing, which can make or break your test automation scripts. In this post, you’ll learn the key differences between these methods, see practical examples of each locator strategy, understand when to use which approach, and discover common pitfalls that can save you hours of debugging.

How findElement and findElements Work

The core difference between findElement and findElements lies in their return behavior and exception handling. The findElement method returns a single WebElement object and throws a NoSuchElementException if no element is found. Meanwhile, findElements returns a List of WebElement objects and returns an empty list when no elements match the locator.

Both methods accept By objects as parameters, which define the locator strategy. Selenium supports eight primary locator strategies: ID, Name, Class Name, Tag Name, Link Text, Partial Link Text, CSS Selector, and XPath. Each strategy has its strengths and performance characteristics.

Method Return Type When No Element Found When Multiple Elements Found
findElement WebElement Throws NoSuchElementException Returns first matching element
findElements List<WebElement> Returns empty list Returns all matching elements

Step-by-Step Implementation Guide

Let’s start with basic setup and then explore each locator strategy with practical examples. First, ensure you have Selenium WebDriver dependencies in your project:


<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.15.0</version>
</dependency>

Here’s the basic WebDriver setup:


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.List;

public class SeleniumLocatorExamples {
    private WebDriver driver;
    
    public void setUp() {
        driver = new ChromeDriver();
        driver.get("https://example.com");
    }
}

ID Locator Strategy

ID locators are the fastest and most reliable when available, since IDs should be unique on a page:


// findElement with ID
WebElement loginButton = driver.findElement(By.id("login-btn"));
loginButton.click();

// findElements with ID (typically returns 0 or 1 element)
List<WebElement> loginElements = driver.findElements(By.id("login-btn"));
if (!loginElements.isEmpty()) {
    loginElements.get(0).click();
}

Name Locator Strategy

Name locators work well for form elements:


// Single element by name
WebElement usernameField = driver.findElement(By.name("username"));
usernameField.sendKeys("testuser");

// Multiple elements by name (common with radio buttons)
List<WebElement> radioButtons = driver.findElements(By.name("gender"));
for (WebElement radio : radioButtons) {
    if (radio.getAttribute("value").equals("male")) {
        radio.click();
        break;
    }
}

CSS Selector Strategy

CSS selectors offer powerful and flexible element targeting:


// Class selector
WebElement errorMessage = driver.findElement(By.cssSelector(".error-message"));

// Attribute selector
WebElement emailInput = driver.findElement(By.cssSelector("input[type='email']"));

// Complex CSS selector
List<WebElement> navLinks = driver.findElements(By.cssSelector("nav ul li a"));

// Pseudo-selectors
WebElement firstListItem = driver.findElement(By.cssSelector("ul li:first-child"));
WebElement lastRow = driver.findElement(By.cssSelector("table tr:last-child"));

XPath Strategy

XPath provides the most powerful but potentially slowest locator option:


// Absolute XPath (fragile, not recommended)
WebElement element = driver.findElement(By.xpath("/html/body/div[1]/form/input[2]"));

// Relative XPath with text content
WebElement submitBtn = driver.findElement(By.xpath("//button[text()='Submit']"));

// XPath with contains function
WebElement partialText = driver.findElement(By.xpath("//span[contains(text(), 'Welcome')]"));

// XPath with multiple conditions
List<WebElement> activeUsers = driver.findElements(
    By.xpath("//tr[@class='user-row' and contains(@data-status, 'active')]")
);

// XPath axes
WebElement nextSibling = driver.findElement(
    By.xpath("//label[text()='Username']/following-sibling::input")
);

Real-World Examples and Use Cases

Here are practical scenarios where you’d choose findElement vs findElements:

Form Validation Scenario


public boolean validateLoginForm() {
    try {
        // Use findElement when you expect exactly one element
        WebElement usernameField = driver.findElement(By.name("username"));
        WebElement passwordField = driver.findElement(By.name("password"));
        
        // Use findElements to check if error messages exist
        List<WebElement> errorMessages = driver.findElements(By.className("validation-error"));
        
        return errorMessages.isEmpty(); // No errors = valid form
    } catch (NoSuchElementException e) {
        return false; // Required fields missing
    }
}

Dynamic Content Handling


public void handleDynamicTable() {
    // Get all table rows
    List<WebElement> tableRows = driver.findElements(By.cssSelector("table tbody tr"));
    
    System.out.println("Found " + tableRows.size() + " rows");
    
    for (int i = 0; i < tableRows.size(); i++) {
        WebElement row = tableRows.get(i);
        
        // Find cells within this specific row
        List<WebElement> cells = row.findElements(By.tagName("td"));
        
        if (cells.size() >= 3) {
            String name = cells.get(0).getText();
            String email = cells.get(1).getText();
            String status = cells.get(2).getText();
            
            System.out.println("Row " + i + ": " + name + " | " + email + " | " + status);
        }
    }
}

Wait Strategy Implementation


import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;

public WebElement waitForElement(By locator, int timeoutSeconds) {
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeoutSeconds));
    return wait.until(ExpectedConditions.presenceOfElementLocated(locator));
}

public List<WebElement> waitForElements(By locator, int timeoutSeconds) {
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(timeoutSeconds));
    wait.until(ExpectedConditions.presenceOfElementLocated(locator));
    return driver.findElements(locator);
}

Performance Comparison and Best Practices

Different locator strategies have varying performance characteristics. Here’s a performance ranking from fastest to slowest:

Locator Strategy Performance Reliability Best Use Case
ID Fastest High Unique elements with stable IDs
Name Fast Medium Form elements
CSS Selector Fast High Complex selections, modern web apps
Class Name Fast Medium Elements with unique classes
Tag Name Medium Low When combined with other strategies
Link Text Medium Medium Static link text
Partial Link Text Slow Medium Dynamic or long link text
XPath Slowest High Complex relationships, text content

Best Practices

  • Always prefer findElements when checking element existence to avoid exceptions
  • Use explicit waits instead of Thread.sleep() for better reliability
  • Combine locator strategies for more robust element identification
  • Avoid absolute XPath expressions as they’re brittle to DOM changes
  • Cache frequently used elements but be aware of stale element references
  • Use Page Object Model pattern to centralize element definitions

// Good: Check existence before interaction
List<WebElement> notifications = driver.findElements(By.className("notification"));
if (!notifications.isEmpty()) {
    notifications.get(0).click();
}

// Better: Use explicit wait
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement notification = wait.until(
    ExpectedConditions.elementToBeClickable(By.className("notification"))
);
notification.click();

Common Pitfalls and Troubleshooting

Stale Element Reference Exception

This occurs when you hold references to elements that are no longer attached to the DOM:


// Problematic approach
List<WebElement> items = driver.findElements(By.className("item"));
// Page refresh or DOM manipulation happens
items.get(0).click(); // Throws StaleElementReferenceException

// Solution: Re-find elements after DOM changes
public void clickFirstItem() {
    List<WebElement> items = driver.findElements(By.className("item"));
    if (!items.isEmpty()) {
        items.get(0).click();
    }
}

Timing Issues

Elements might not be immediately available due to JavaScript loading:


// Wrong: Immediate search might fail
WebElement dynamicContent = driver.findElement(By.id("dynamic-content"));

// Right: Wait for element to appear
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement dynamicContent = wait.until(
    ExpectedConditions.presenceOfElementLocated(By.id("dynamic-content"))
);

Shadow DOM Elements

Regular locators don’t work with Shadow DOM. You need to use JavaScript execution:


import org.openqa.selenium.JavascriptExecutor;

public WebElement findElementInShadowDOM(String shadowHost, String selector) {
    JavascriptExecutor js = (JavascriptExecutor) driver;
    return (WebElement) js.executeScript(
        "return document.querySelector(arguments[0]).shadowRoot.querySelector(arguments[1])",
        shadowHost, selector
    );
}

iframe Context Issues

Elements inside iframes require context switching:


// Switch to iframe first
driver.switchTo().frame("iframe-name");
WebElement elementInFrame = driver.findElement(By.id("element-in-iframe"));

// Switch back to main content
driver.switchTo().defaultContent();

Understanding these nuances of findElement and findElements will significantly improve your Selenium automation scripts’ reliability and maintainability. The key is choosing the right method based on your specific use case and handling edge cases gracefully. For more detailed information, check the official Selenium documentation and the W3C WebDriver specification.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked