0
0
Selenium Javatesting~15 mins

Custom annotations in Selenium Java - Build an Automation Script

Choose your learning style9 modes available
Automate login test using custom annotation for test metadata
Preconditions (2)
Step 1: Navigate to the login page URL
Step 2: Enter 'user@example.com' in the email input field with id 'email'
Step 3: Enter 'Password123' in the password input field with id 'password'
Step 4: Click the login button with id 'loginBtn'
Step 5: Verify that the URL changes to the dashboard page URL 'https://example.com/dashboard'
Step 6: Verify that a welcome message with id 'welcomeMsg' is displayed
✅ Expected Result: User is successfully logged in and redirected to the dashboard page with welcome message visible
Automation Requirements - Selenium with TestNG
Assertions Needed:
Verify current URL is 'https://example.com/dashboard'
Verify welcome message element is displayed
Best Practices:
Use Page Object Model to separate page elements and actions
Use explicit waits to wait for elements or URL changes
Create a custom annotation to add metadata to the test method (e.g., @TestInfo)
Use the custom annotation to store test case ID and description
Use TestNG assertions for validation
Automated Solution
Selenium Java
package tests;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
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.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Duration;

// Custom annotation definition
@Retention(RetentionPolicy.RUNTIME)
@interface TestInfo {
    String testCaseId();
    String description();
}

// 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) {
        WebElement emailInput = wait.until(ExpectedConditions.visibilityOfElementLocated(emailField));
        emailInput.clear();
        emailInput.sendKeys(email);
    }

    public void enterPassword(String password) {
        WebElement passwordInput = wait.until(ExpectedConditions.visibilityOfElementLocated(passwordField));
        passwordInput.clear();
        passwordInput.sendKeys(password);
    }

    public void clickLogin() {
        WebElement loginBtn = wait.until(ExpectedConditions.elementToBeClickable(loginButton));
        loginBtn.click();
    }
}

// Page Object for Dashboard Page
class DashboardPage {
    private WebDriver driver;
    private WebDriverWait wait;

    private By welcomeMessage = By.id("welcomeMsg");

    public DashboardPage(WebDriver driver) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    }

    public boolean isWelcomeMessageDisplayed() {
        return wait.until(ExpectedConditions.visibilityOfElementLocated(welcomeMessage)).isDisplayed();
    }
}

public class LoginTest {
    private WebDriver driver;
    private LoginPage loginPage;
    private DashboardPage dashboardPage;

    @BeforeClass
    public void setUp() {
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        loginPage = new LoginPage(driver);
        dashboardPage = new DashboardPage(driver);
    }

    @Test
    @TestInfo(testCaseId = "TC001", description = "Verify successful login redirects to dashboard")
    public void testSuccessfulLogin() {
        driver.get("https://example.com/login");

        loginPage.enterEmail("user@example.com");
        loginPage.enterPassword("Password123");
        loginPage.clickLogin();

        // Wait for URL to change to dashboard
        new WebDriverWait(driver, Duration.ofSeconds(10))
            .until(ExpectedConditions.urlToBe("https://example.com/dashboard"));

        Assert.assertEquals(driver.getCurrentUrl(), "https://example.com/dashboard", "URL should be dashboard URL after login");
        Assert.assertTrue(dashboardPage.isWelcomeMessageDisplayed(), "Welcome message should be visible on dashboard");
    }

    @AfterClass
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

This test script uses Selenium WebDriver with TestNG to automate the login test.

We define a @TestInfo custom annotation to add metadata like test case ID and description to the test method. This helps organize and document tests clearly.

The Page Object Model is used to separate page elements and actions for the login and dashboard pages. This makes the code cleaner and easier to maintain.

Explicit waits ensure the test waits for elements to be visible or clickable before interacting, avoiding flaky tests.

The test method navigates to the login page, enters credentials, clicks login, then waits for the URL to change to the dashboard URL. It asserts the URL and checks that the welcome message is displayed.

Finally, the @AfterClass method closes the browser to clean up.

Common Mistakes - 5 Pitfalls
Not using explicit waits and relying on Thread.sleep
Hardcoding locators with brittle XPath expressions
Not separating page elements and actions into Page Objects
Not using custom annotations for test metadata
Not quitting the WebDriver after tests
Bonus Challenge

Now add data-driven testing with 3 different sets of login credentials using TestNG data provider

Show Hint