Jump to content

Connect SuperML | Leeroopedia MCP: Equip your AI agents with best practices, code verification, and debugging knowledge. Powered by Leeroo — building Organizational Superintelligence. Contact us at founders@leeroo.com.

Implementation:SeleniumHQ Selenium FindBy Annotation Suite

From Leeroopedia
Knowledge Sources
Domains Test_Design, Design_Patterns, Browser_Automation
Last Updated 2026-02-11 00:00 GMT

Overview

Concrete tool for declaring element locators via Java annotations provided by the Selenium Support library.

Description

The @FindBy annotation supports two forms: shorthand (@FindBy(id = "foo")) and long form (@FindBy(how = How.ID, using = "foo")). Both delegate to the matching By factory methods. @FindAll takes an array of @FindBy with OR semantics, producing a ByAll locator that returns elements matching any of the criteria. @FindBys takes an array with AND/chaining semantics, producing a ByChained locator that applies locators sequentially. The How enum provides: CLASS_NAME, CSS, ID, ID_OR_NAME, LINK_TEXT, NAME, PARTIAL_LINK_TEXT, TAG_NAME, XPATH, UNSET. Each enum constant implements the buildBy(String value) method to produce the corresponding By object. All three annotations use @PageFactoryFinder to declare their respective inner FindByBuilder class, which extends AbstractFindByBuilder.

Usage

Annotate WebElement or List<WebElement> fields in Page Object classes. Fields are populated by PageFactory.initElements() at runtime. For a single locator, use @FindBy with either shorthand or long form. For multiple locators with OR semantics, use @FindAll. For chained locators with AND semantics, use @FindBys.

Code Reference

Source Location

  • Repository: Selenium
  • File: java/src/org/openqa/selenium/support/FindBy.java (L53-90)
  • File: java/src/org/openqa/selenium/support/FindAll.java (L42-62)
  • File: java/src/org/openqa/selenium/support/FindBys.java (L41-61)
  • File: java/src/org/openqa/selenium/support/How.java (L22-85)

Signature

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
@PageFactoryFinder(FindBy.FindByBuilder.class)
public @interface FindBy {
    How how() default How.UNSET;
    String using() default "";
    String id() default "";
    String name() default "";
    String className() default "";
    String css() default "";
    String tagName() default "";
    String linkText() default "";
    String partialLinkText() default "";
    String xpath() default "";
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
@PageFactoryFinder(FindAll.FindByBuilder.class)
public @interface FindAll {
    FindBy[] value();  // OR semantics via ByAll
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
@PageFactoryFinder(FindBys.FindByBuilder.class)
public @interface FindBys {
    FindBy[] value();  // AND/chaining semantics via ByChained
}

public enum How {
    CLASS_NAME {
        @Override public By buildBy(String value) { return By.className(value); }
    },
    CSS {
        @Override public By buildBy(String value) { return By.cssSelector(value); }
    },
    ID {
        @Override public By buildBy(String value) { return By.id(value); }
    },
    ID_OR_NAME {
        @Override public By buildBy(String value) { return new ByIdOrName(value); }
    },
    LINK_TEXT {
        @Override public By buildBy(String value) { return By.linkText(value); }
    },
    NAME {
        @Override public By buildBy(String value) { return By.name(value); }
    },
    PARTIAL_LINK_TEXT {
        @Override public By buildBy(String value) { return By.partialLinkText(value); }
    },
    TAG_NAME {
        @Override public By buildBy(String value) { return By.tagName(value); }
    },
    XPATH {
        @Override public By buildBy(String value) { return By.xpath(value); }
    },
    UNSET {
        @Override public By buildBy(String value) { return ID.buildBy(value); }
    };

    public abstract By buildBy(String value);
}

Import

import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.FindAll;
import org.openqa.selenium.support.FindBys;
import org.openqa.selenium.support.How;

I/O Contract

Inputs

Name Type Required Description
how How No Locator strategy enum (long form); defaults to How.UNSET
using String No Locator value (long form); defaults to empty string
id String No Shorthand for How.ID
name String No Shorthand for How.NAME
className String No Shorthand for How.CLASS_NAME
css String No Shorthand for How.CSS
tagName String No Shorthand for How.TAG_NAME
linkText String No Shorthand for How.LINK_TEXT
partialLinkText String No Shorthand for How.PARTIAL_LINK_TEXT
xpath String No Shorthand for How.XPATH

Outputs

Name Type Description
annotation metadata Annotation Runtime-retained locator metadata for PageFactory processing

Validation

AbstractFindByBuilder.assertValidFindBy() enforces that at most one location strategy is specified per @FindBy annotation. If multiple shorthand attributes or both shorthand and long-form are set, an IllegalArgumentException is thrown with a message indicating the conflicting finders.

Usage Examples

Basic @FindBy

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;

public class LoginPage {
    @FindBy(id = "username")
    private WebElement usernameField;

    @FindBy(css = "input[type='password']")
    private WebElement passwordField;

    @FindBy(xpath = "//button[@type='submit']")
    private WebElement loginButton;

    // Long form equivalent
    @FindBy(how = How.ID, using = "username")
    private WebElement usernameFieldLongForm;
}

@FindAll (OR) and @FindBys (AND)

import org.openqa.selenium.support.FindAll;
import org.openqa.selenium.support.FindBys;
import org.openqa.selenium.support.FindBy;
import java.util.List;

public class SearchPage {
    // OR: matches elements found by ANY of these locators (uses ByAll internally)
    @FindAll({
        @FindBy(css = ".result-item"),
        @FindBy(css = ".search-result")
    })
    private List<WebElement> searchResults;

    // AND: chained locators (uses ByChained internally)
    // Finds element matching second @FindBy within results of first @FindBy
    @FindBys({
        @FindBy(id = "search-form"),
        @FindBy(tagName = "input")
    })
    private WebElement searchInput;
}

Related Pages

Implements Principle

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment