Why POM creates maintainable test code in Selenium Java - Automation Benefits in Action
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 org.openqa.selenium.chrome.ChromeDriver; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; import java.time.Duration; // Page Object for Login Page class LoginPage { private WebDriver driver; private WebDriverWait wait; private By emailField = By.id("email"); private By passwordField = By.id("password"); private By loginButton = By.id("loginBtn"); public LoginPage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } public void enterEmail(String email) { wait.until(ExpectedConditions.visibilityOfElementLocated(emailField)).sendKeys(email); } public void enterPassword(String password) { wait.until(ExpectedConditions.visibilityOfElementLocated(passwordField)).sendKeys(password); } public void clickLogin() { wait.until(ExpectedConditions.elementToBeClickable(loginButton)).click(); } } // Page Object for Dashboard Page class DashboardPage { private WebDriver driver; private WebDriverWait wait; private By logoutButton = By.id("logoutBtn"); public DashboardPage(WebDriver driver) { this.driver = driver; this.wait = new WebDriverWait(driver, Duration.ofSeconds(10)); } public boolean isLogoutButtonVisible() { return wait.until(ExpectedConditions.visibilityOfElementLocated(logoutButton)).isDisplayed(); } } public class LoginTest { private WebDriver driver; private LoginPage loginPage; private DashboardPage dashboardPage; @BeforeEach public void setUp() { driver = new ChromeDriver(); driver.manage().window().maximize(); driver.get("https://example.com/login"); loginPage = new LoginPage(driver); dashboardPage = new DashboardPage(driver); } @Test public void testSuccessfulLogin() { loginPage.enterEmail("testuser@example.com"); loginPage.enterPassword("Test@1234"); loginPage.clickLogin(); // Verify URL contains /dashboard new WebDriverWait(driver, Duration.ofSeconds(10)) .until(ExpectedConditions.urlContains("/dashboard")); assertTrue(driver.getCurrentUrl().contains("/dashboard"), "Dashboard URL should be displayed"); // Verify logout button is visible assertTrue(dashboardPage.isLogoutButtonVisible(), "Logout button should be visible on dashboard"); } @AfterEach public void tearDown() { if (driver != null) { driver.quit(); } } }
This test uses the Page Object Model (POM) to keep the code clean and maintainable.
LoginPage class holds locators and actions for the login page. It uses explicit waits to wait for elements before interacting.
DashboardPage class holds locators and checks for the dashboard page.
The test testSuccessfulLogin uses these page objects to perform login and verify results. This separation means if the login page changes, only LoginPage needs updating, not the test itself.
Explicit waits avoid flaky tests by waiting for elements properly.
Assertions check the URL and visibility of logout button to confirm successful login.
This structure makes the test easy to read, maintain, and extend.
Now add data-driven testing with 3 different sets of login credentials (valid and invalid).