@FindBy annotations in Selenium Java - Build an Automation Script
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.time.Duration; public class LoginPage { private WebDriver driver; private WebDriverWait wait; @FindBy(id = "email") private WebElement emailInput; @FindBy(id = "password") private WebElement passwordInput; @FindBy(id = "loginBtn") private WebElement loginButton; public LoginPage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, Duration.ofSeconds(10)); PageFactory.initElements(driver, this); } public void enterEmail(String email) { wait.until(ExpectedConditions.visibilityOf(emailInput)); emailInput.clear(); emailInput.sendKeys(email); } public void enterPassword(String password) { wait.until(ExpectedConditions.visibilityOf(passwordInput)); passwordInput.clear(); passwordInput.sendKeys(password); } public void clickLogin() { wait.until(ExpectedConditions.elementToBeClickable(loginButton)); loginButton.click(); } } public class LoginTest { private WebDriver driver; private LoginPage loginPage; @BeforeClass public void setUp() { // Initialize WebDriver (e.g., ChromeDriver) here driver = new org.openqa.selenium.chrome.ChromeDriver(); driver.manage().window().maximize(); driver.get("https://example.com/login"); loginPage = new LoginPage(driver); } @Test public void testSuccessfulLogin() { loginPage.enterEmail("user@example.com"); loginPage.enterPassword("Password123!"); loginPage.clickLogin(); WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); wait.until(ExpectedConditions.urlContains("/dashboard")); String currentUrl = driver.getCurrentUrl(); Assert.assertTrue(currentUrl.contains("/dashboard"), "URL should contain '/dashboard' after login"); } @AfterClass public void tearDown() { if (driver != null) { driver.quit(); } } }
This code uses the @FindBy annotation to locate the email input, password input, and login button elements on the login page. The LoginPage class represents the login page using the Page Object Model pattern, which helps keep the code organized and reusable.
In the LoginTest class, the test opens the browser, navigates to the login page, and uses the LoginPage methods to enter credentials and click the login button. It then waits explicitly for the URL to contain '/dashboard' to confirm successful login. Finally, it asserts that the URL is correct.
Explicit waits ensure the test waits for elements to be ready before interacting, avoiding flaky tests. The test cleans up by closing the browser after running.
Now add data-driven testing with 3 different sets of login credentials (valid and invalid) using TestNG data provider.
Practice
@FindBy annotation in Selenium Java?Solution
Step 1: Understand the role of
The@FindBy@FindByannotation is used to specify how to find a web element on a page, such as by id, name, xpath, etc.Step 2: Compare with other options
Options B, C, and D describe other Selenium features but not element locating.Final Answer:
To locate web elements on a page using different strategies -> Option BQuick Check:
@FindBy locates elements = A [OK]
- Confusing @FindBy with WebDriver commands
- Thinking @FindBy executes scripts
- Assuming @FindBy starts browser sessions
@FindBy annotation?Solution
Step 1: Check correct attribute usage
The@FindByannotation requires the attribute name and value as a string. For ID, it isid = "value".Step 2: Validate each option
@FindBy(id = "submitBtn") correctly usesid = "submitBtn". @FindBy(name = submitBtn) misses quotes. @FindBy(xpath = submitBtn) uses xpath but without quotes. @FindBy(css = #submitBtn) uses CSS selector but with incorrect syntax (should becss = "#submitBtn").Final Answer:
@FindBy(id = "submitBtn") -> Option AQuick Check:
Correct syntax uses id with quotes = B [OK]
- Omitting quotes around locator values
- Mixing locator types incorrectly
- Using invalid syntax for CSS selectors
button.isDisplayed() is called?public class LoginPage {
@FindBy(name = "loginBtn")
WebElement button;
public LoginPage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
}
// In test method:
LoginPage page = new LoginPage(driver);
boolean visible = page.button.isDisplayed();
System.out.println(visible);Solution
Step 1: Understand PageFactory initialization
The constructor callsPageFactory.initElements(driver, this), which initializes all @FindBy annotated elements, includingbutton.Step 2: Check behavior of
If the element with name 'loginBtn' exists and is visible,isDisplayed()isDisplayed()returns true; otherwise false. No NullPointerException occurs because initialization is done.Final Answer:
true if the element with name 'loginBtn' is visible on the page -> Option CQuick Check:
PageFactory initializes elements = true if visible [OK]
- Assuming elements are null without initialization
- Confusing isDisplayed() with element presence
- Ignoring the need to call PageFactory.initElements
@FindBy:public class HomePage {
@FindBy(xpath = "//button[@id='start']")
WebElement startButton;
public HomePage(WebDriver driver) {
// Missing initialization
}
}Solution
Step 1: Check element initialization
The constructor does not callPageFactory.initElements(driver, this), sostartButtonremains null.Step 2: Validate other options
XPath syntax is correct. WebElement visibility (private/public) is optional. Manual initialization is not needed if PageFactory is used.Final Answer:
Missing call to PageFactory.initElements to initialize elements -> Option AQuick Check:
PageFactory.initElements missing = D [OK]
- Forgetting to initialize elements with PageFactory
- Assuming XPath syntax errors without checking
- Thinking manual findElement is required with @FindBy
@FindBy. Which declaration is correct to store all matching elements in a list?public class ProductsPage {
// Which line is correct?
}Solution
Step 1: Understand locating multiple elements
To store multiple elements, the field must be aList<WebElement>. Using@FindBywithclassNamelocator is valid.Step 2: Check each option's type and locator
@FindBy(className = "product-item") List<WebElement> products; usesList<WebElement>with correct locator. Options A, B, and D use singleWebElement, which can only hold one element.Final Answer:
@FindBy(className = "product-item") List<WebElement> products; -> Option DQuick Check:
Multiple elements need List<WebElement> = C [OK]
- Declaring multiple elements as single WebElement
- Using wrong locator type for multiple elements
- Forgetting to import java.util.List
Ready to prove it?
Pass the test and this pattern moves unknown
