Base page class pattern in Selenium Java - Build an Automation Script
import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import java.time.Duration; // BasePage class holds common driver and wait public class BasePage { protected WebDriver driver; protected WebDriverWait wait; public BasePage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } protected WebElement waitForVisibility(By locator) { return wait.until(ExpectedConditions.visibilityOfElementLocated(locator)); } protected WebElement waitForClickable(By locator) { return wait.until(ExpectedConditions.elementToBeClickable(locator)); } } // LoginPage class extends BasePage and contains login page actions public class LoginPage extends BasePage { private By usernameInput = By.id("username"); private By passwordInput = By.id("password"); private By loginButton = By.id("loginBtn"); public LoginPage(WebDriver driver) { super(driver); } public void enterUsername(String username) { WebElement userField = waitForVisibility(usernameInput); userField.clear(); userField.sendKeys(username); } public void enterPassword(String password) { WebElement passField = waitForVisibility(passwordInput); passField.clear(); passField.sendKeys(password); } public void clickLogin() { WebElement loginBtn = waitForClickable(loginButton); loginBtn.click(); } } // Test class to automate the login test case import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class LoginTest { private WebDriver driver; private LoginPage loginPage; @BeforeEach public void setUp() { driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://example.com/login"); loginPage = new LoginPage(driver); } @Test public void testSuccessfulLogin() { loginPage.enterUsername("testuser"); loginPage.enterPassword("Test@1234"); loginPage.clickLogin(); // Wait for URL to contain '/dashboard' boolean urlContainsDashboard = new WebDriverWait(driver, Duration.ofSeconds(10)) .until(d -> d.getCurrentUrl().contains("/dashboard")); Assertions.assertTrue(urlContainsDashboard, "URL should contain '/dashboard' after login"); } @AfterEach public void tearDown() { if (driver != null) { driver.quit(); } } }
The BasePage class holds the WebDriver and WebDriverWait objects. It provides common methods to wait for element visibility and clickability. This avoids repeating wait code in every page class.
The LoginPage class extends BasePage and contains locators and actions specific to the login page. It uses the wait methods from BasePage to ensure elements are ready before interacting.
The LoginTest class sets up the ChromeDriver, opens the login page URL, and uses the LoginPage methods to perform login steps. It then waits for the URL to contain '/dashboard' and asserts this condition to verify successful login.
This structure follows the Page Object Model and uses explicit waits for reliability. It keeps code clean, reusable, and easy to maintain.
Now add data-driven testing with 3 different username and password combinations
Practice
BasePage class in Selenium Java testing?Solution
Step 1: Understand the role of BasePage
The BasePage class contains common methods like click, type, and wait that many page classes use.Step 2: Identify the benefit
By grouping these common actions, BasePage helps avoid repeating the same code in every page class.Final Answer:
To group common web actions and avoid code repetition across page classes -> Option CQuick Check:
BasePage groups common actions = A [OK]
- Confusing BasePage with test data storage
- Thinking BasePage runs tests directly
- Mixing BasePage with database handling
Solution
Step 1: Identify correct constructor syntax
In Java, constructors have no return type and match the class name exactly.Step 2: Check parameter assignment
The constructor should assign the passed driver to the class field usingthis.driver = driver;.Final Answer:
public BasePage(WebDriver driver) { this.driver = driver; } -> Option AQuick Check:
Constructor no return + this.driver = driver [OK]
- Adding void return type to constructor
- Reversing assignment order
- Declaring driver inside constructor without class field
public void clickElement(By locator) {
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
wait.until(ExpectedConditions.elementToBeClickable(locator)).click();
System.out.println("Clicked successfully");
}Solution
Step 1: Understand WebDriverWait behavior
The wait.until waits up to 5 seconds for the element to be clickable.Step 2: Outcome if element not found
If the element is not clickable within 5 seconds, wait.until throws a TimeoutException and the click and print statements are skipped.Final Answer:
Throws TimeoutException and does not print anything -> Option DQuick Check:
Wait fails = TimeoutException, no print [OK]
- Assuming print runs even if element not found
- Confusing TimeoutException with NoSuchElementException
- Thinking click happens immediately without wait
public void enterText(By locator, String text) {
WebElement element = driver.findElement(locator);
element.sendKeys();
}Solution
Step 1: Check sendKeys usage
The sendKeys method requires a String argument to input text.Step 2: Fix the method call
Changeelement.sendKeys();toelement.sendKeys(text);to send the provided text.Final Answer:
sendKeys() is missing the text argument; fix by adding sendKeys(text) -> Option AQuick Check:
sendKeys needs text argument [OK]
- Calling sendKeys without arguments
- Using findElements instead of findElement for single element
- Changing locator type incorrectly
public boolean isElementVisible(By locator) that returns true if element is visible. How would you use this method in a LoginPage class to verify the login button is visible before clicking it?Solution
Step 1: Use isElementVisible with locator argument
The method requires a By locator to check visibility, so passloginButtonLocator.Step 2: Conditionally click if visible
Use an if statement to callclickElement(loginButtonLocator)only if the element is visible.Final Answer:
if (isElementVisible(loginButtonLocator)) { clickElement(loginButtonLocator); } -> Option BQuick Check:
Check visibility with locator before click [OK]
- Calling isElementVisible without locator argument
- Clicking without checking visibility
- Calling clickElement without locator
Ready to prove it?
Pass the test and this pattern moves unknown
