UI Automation
Selenium WebDriver
Selenium with Java

Selenium with Java Tutorial

Parul Dhingra - Senior Quality Analyst
Parul Dhingra13+ Years ExperienceHire Me

Senior Quality Analyst

Updated: 1/23/2026

Java is the most popular language for Selenium automation. With strong typing, extensive IDE support, and seamless integration with TestNG and Maven, Java provides a robust foundation for enterprise-grade test automation. This tutorial covers everything from initial setup to building maintainable test frameworks.

Whether you're starting fresh or transitioning from another language, this guide will get you writing professional Selenium tests with Java.

Prerequisites and Setup

Required Software

SoftwareVersionPurpose
JDK11 or higherJava runtime
Maven3.6+Dependency management
IDEIntelliJ IDEA or EclipseDevelopment environment
BrowserChrome, Firefox, EdgeTest execution

Install JDK

# Verify Java installation
java -version
javac -version
 
# Expected output
# java version "17.0.2" 2022-01-18 LTS

If not installed, download from Oracle JDK (opens in a new tab) or use OpenJDK.

Install Maven

# Verify Maven installation
mvn -version
 
# Expected output
# Apache Maven 3.9.0

Configure Environment Variables

# Windows (System Properties > Environment Variables)
JAVA_HOME = C:\Program Files\Java\jdk-17
MAVEN_HOME = C:\Program Files\Apache\maven
 
# Add to PATH
%JAVA_HOME%\bin
%MAVEN_HOME%\bin

Maven Project Configuration

Create Maven Project

In IntelliJ IDEA:

  1. File → New → Project
  2. Select Maven
  3. Enter GroupId: com.yourcompany
  4. Enter ArtifactId: selenium-tests
  5. Click Create

Configure pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.yourcompany</groupId>
    <artifactId>selenium-tests</artifactId>
    <version>1.0-SNAPSHOT</version>
 
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <selenium.version>4.21.0</selenium.version>
        <testng.version>7.9.0</testng.version>
        <webdrivermanager.version>5.8.0</webdrivermanager.version>
    </properties>
 
    <dependencies>
        <!-- Selenium WebDriver -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>${selenium.version}</version>
        </dependency>
 
        <!-- WebDriver Manager (auto driver management) -->
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>${webdrivermanager.version}</version>
        </dependency>
 
        <!-- TestNG -->
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>${testng.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.2.5</version>
                <configuration>
                    <suiteXmlFiles>
                        <suiteXmlFile>testng.xml</suiteXmlFile>
                    </suiteXmlFiles>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Project Structure

selenium-tests/
├── src/
│   ├── main/
│   │   └── java/
│   │       └── com/yourcompany/
│   │           └── pages/        # Page Objects
│   └── test/
│       └── java/
│           └── com/yourcompany/
│               └── tests/        # Test classes
├── pom.xml
└── testng.xml

Your First Selenium Test

Simple Test Without Framework

package com.yourcompany.tests;
 
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
 
public class FirstTest {
    public static void main(String[] args) {
        // Setup ChromeDriver automatically
        WebDriverManager.chromedriver().setup();
 
        // Create driver instance
        WebDriver driver = new ChromeDriver();
 
        try {
            // Navigate to URL
            driver.get("https://www.google.com");
 
            // Find search box and enter text
            WebElement searchBox = driver.findElement(By.name("q"));
            searchBox.sendKeys("Selenium WebDriver");
            searchBox.submit();
 
            // Print page title
            System.out.println("Page title: " + driver.getTitle());
 
        } finally {
            // Close browser
            driver.quit();
        }
    }
}

Test with TestNG

package com.yourcompany.tests;
 
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.*;
 
public class GoogleSearchTest {
    private WebDriver driver;
 
    @BeforeClass
    public void setupClass() {
        WebDriverManager.chromedriver().setup();
    }
 
    @BeforeMethod
    public void setup() {
        driver = new ChromeDriver();
        driver.manage().window().maximize();
    }
 
    @Test
    public void testGoogleSearch() {
        driver.get("https://www.google.com");
 
        WebElement searchBox = driver.findElement(By.name("q"));
        searchBox.sendKeys("Selenium Java");
        searchBox.submit();
 
        Assert.assertTrue(driver.getTitle().contains("Selenium Java"),
            "Search results should show Selenium Java");
    }
 
    @AfterMethod
    public void teardown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

WebDriver Basics

Creating Driver Instances

// Chrome
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();
 
// Firefox
WebDriverManager.firefoxdriver().setup();
WebDriver driver = new FirefoxDriver();
 
// Edge
WebDriverManager.edgedriver().setup();
WebDriver driver = new EdgeDriver();

Browser Options

// Chrome with options
ChromeOptions options = new ChromeOptions();
options.addArguments("--headless");          // Headless mode
options.addArguments("--disable-gpu");
options.addArguments("--window-size=1920,1080");
options.addArguments("--incognito");         // Incognito mode
options.addArguments("--disable-notifications");
 
WebDriver driver = new ChromeDriver(options);

Navigation Commands

// Navigate to URL
driver.get("https://example.com");
driver.navigate().to("https://example.com");
 
// Browser navigation
driver.navigate().back();
driver.navigate().forward();
driver.navigate().refresh();
 
// Get page info
String title = driver.getTitle();
String url = driver.getCurrentUrl();
String source = driver.getPageSource();

Window Management

// Maximize window
driver.manage().window().maximize();
 
// Set specific size
driver.manage().window().setSize(new Dimension(1920, 1080));
 
// Full screen
driver.manage().window().fullscreen();

Locator Strategies

All Locator Types

// By ID (preferred when available)
driver.findElement(By.id("username"));
 
// By Name
driver.findElement(By.name("email"));
 
// By Class Name (single class only)
driver.findElement(By.className("btn-primary"));
 
// By Tag Name
driver.findElements(By.tagName("input"));
 
// By Link Text (exact match)
driver.findElement(By.linkText("Sign In"));
 
// By Partial Link Text
driver.findElement(By.partialLinkText("Sign"));
 
// By CSS Selector (recommended)
driver.findElement(By.cssSelector("#login-form input[type='email']"));
driver.findElement(By.cssSelector(".btn.btn-primary"));
driver.findElement(By.cssSelector("[data-testid='submit-btn']"));
 
// By XPath (when CSS can't do it)
driver.findElement(By.xpath("//button[text()='Submit']"));
driver.findElement(By.xpath("//input[@id='email']/../label"));

CSS Selector Examples

// By ID
By.cssSelector("#elementId")
 
// By class
By.cssSelector(".className")
 
// By attribute
By.cssSelector("[name='email']")
By.cssSelector("input[type='text']")
 
// Partial attribute match
By.cssSelector("[id*='partial']")     // Contains
By.cssSelector("[id^='start']")       // Starts with
By.cssSelector("[id$='end']")         // Ends with
 
// Hierarchy
By.cssSelector("form > input")        // Direct child
By.cssSelector("form input")          // Any descendant
By.cssSelector("label + input")       // Adjacent sibling
 
// nth-child
By.cssSelector("tr:nth-child(2)")     // Second row
By.cssSelector("li:first-child")
By.cssSelector("li:last-child")

Finding Multiple Elements

// Find all links
List<WebElement> links = driver.findElements(By.tagName("a"));
System.out.println("Found " + links.size() + " links");
 
// Iterate through elements
for (WebElement link : links) {
    System.out.println(link.getText() + " -> " + link.getAttribute("href"));
}
 
// Find elements within element
WebElement container = driver.findElement(By.id("nav"));
List<WebElement> navLinks = container.findElements(By.tagName("a"));

Element Interactions

Basic Interactions

WebElement element = driver.findElement(By.id("username"));
 
// Click
element.click();
 
// Type text
element.sendKeys("test@example.com");
 
// Clear field
element.clear();
 
// Submit form
element.submit();
 
// Get text content
String text = element.getText();
 
// Get attribute value
String value = element.getAttribute("value");
String placeholder = element.getAttribute("placeholder");
 
// Check element state
boolean displayed = element.isDisplayed();
boolean enabled = element.isEnabled();
boolean selected = element.isSelected();

Keyboard Actions

import org.openqa.selenium.Keys;
 
WebElement input = driver.findElement(By.id("search"));
 
// Special keys
input.sendKeys(Keys.ENTER);
input.sendKeys(Keys.TAB);
input.sendKeys(Keys.ESCAPE);
 
// Key combinations
input.sendKeys(Keys.CONTROL + "a");  // Select all
input.sendKeys(Keys.CONTROL + "c");  // Copy
 
// Clear and type
input.sendKeys(Keys.CONTROL + "a", Keys.DELETE);
input.sendKeys("new text");

Dropdown Selection

import org.openqa.selenium.support.ui.Select;
 
WebElement dropdown = driver.findElement(By.id("country"));
Select select = new Select(dropdown);
 
// Select by visible text
select.selectByVisibleText("United States");
 
// Select by value attribute
select.selectByValue("US");
 
// Select by index (0-based)
select.selectByIndex(2);
 
// Get selected option
WebElement selected = select.getFirstSelectedOption();
System.out.println("Selected: " + selected.getText());
 
// Get all options
List<WebElement> options = select.getOptions();
 
// Multi-select dropdowns
if (select.isMultiple()) {
    select.deselectAll();
    select.selectByVisibleText("Option 1");
    select.selectByVisibleText("Option 2");
}

Checkboxes and Radio Buttons

// Checkbox
WebElement checkbox = driver.findElement(By.id("remember-me"));
if (!checkbox.isSelected()) {
    checkbox.click();
}
 
// Radio button
WebElement radio = driver.findElement(By.cssSelector("input[value='option1']"));
radio.click();
 
// Verify selection
Assert.assertTrue(checkbox.isSelected());

Handling Waits

Explicit Wait (Recommended)

import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.time.Duration;
 
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
 
// Wait for element to be visible
WebElement element = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.id("result"))
);
 
// Wait for element to be clickable
WebElement button = wait.until(
    ExpectedConditions.elementToBeClickable(By.id("submit"))
);
button.click();
 
// Wait for text to appear
wait.until(
    ExpectedConditions.textToBePresentInElementLocated(
        By.id("status"), "Complete"
    )
);
 
// Wait for element to disappear
wait.until(
    ExpectedConditions.invisibilityOfElementLocated(By.id("loader"))
);
 
// Wait for URL to change
wait.until(ExpectedConditions.urlContains("/dashboard"));

Common ExpectedConditions

// Presence (in DOM, may be hidden)
ExpectedConditions.presenceOfElementLocated(locator)
 
// Visibility (in DOM and visible)
ExpectedConditions.visibilityOfElementLocated(locator)
 
// Clickable (visible and enabled)
ExpectedConditions.elementToBeClickable(locator)
 
// Text present
ExpectedConditions.textToBePresentInElement(element, text)
 
// Attribute value
ExpectedConditions.attributeToBe(locator, attribute, value)
 
// Frame available
ExpectedConditions.frameToBeAvailableAndSwitchToIt(locator)
 
// Alert present
ExpectedConditions.alertIsPresent()

Fluent Wait

import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.StaleElementReferenceException;
 
Wait<WebDriver> fluentWait = new FluentWait<>(driver)
    .withTimeout(Duration.ofSeconds(30))
    .pollingEvery(Duration.ofMillis(500))
    .ignoring(NoSuchElementException.class)
    .ignoring(StaleElementReferenceException.class);
 
WebElement element = fluentWait.until(driver ->
    driver.findElement(By.id("dynamic-content"))
);

TestNG Integration

TestNG Annotations

import org.testng.annotations.*;
 
public class TestNGExample {
 
    @BeforeSuite
    public void beforeSuite() {
        // Runs once before entire suite
    }
 
    @BeforeClass
    public void beforeClass() {
        // Runs once before all tests in class
    }
 
    @BeforeMethod
    public void setUp() {
        // Runs before each test method
    }
 
    @Test(priority = 1)
    public void testLogin() {
        // Test method
    }
 
    @Test(priority = 2, dependsOnMethods = "testLogin")
    public void testDashboard() {
        // Runs after testLogin
    }
 
    @Test(enabled = false)
    public void skippedTest() {
        // This test is disabled
    }
 
    @AfterMethod
    public void tearDown() {
        // Runs after each test method
    }
 
    @AfterClass
    public void afterClass() {
        // Runs once after all tests in class
    }
 
    @AfterSuite
    public void afterSuite() {
        // Runs once after entire suite
    }
}

testng.xml Configuration

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Regression Suite" parallel="methods" thread-count="4">
 
    <test name="Login Tests">
        <classes>
            <class name="com.yourcompany.tests.LoginTest"/>
        </classes>
    </test>
 
    <test name="Search Tests">
        <parameter name="browser" value="chrome"/>
        <classes>
            <class name="com.yourcompany.tests.SearchTest"/>
        </classes>
    </test>
 
</suite>

Parameterized Tests

@Test(dataProvider = "loginData")
public void testLogin(String username, String password, boolean shouldPass) {
    loginPage.login(username, password);
 
    if (shouldPass) {
        Assert.assertTrue(dashboard.isDisplayed());
    } else {
        Assert.assertTrue(loginPage.getErrorMessage().isDisplayed());
    }
}
 
@DataProvider(name = "loginData")
public Object[][] getLoginData() {
    return new Object[][] {
        {"validuser@test.com", "ValidPass123", true},
        {"invalid@test.com", "wrong", false},
        {"", "password", false},
        {"user@test.com", "", false}
    };
}

Page Object Model

Page Object Class

package com.yourcompany.pages;
 
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;
 
public class LoginPage {
    private WebDriver driver;
    private WebDriverWait wait;
 
    // Locators
    private By usernameField = By.id("username");
    private By passwordField = By.id("password");
    private By loginButton = By.id("login-btn");
    private By errorMessage = By.className("error-message");
 
    public LoginPage(WebDriver driver) {
        this.driver = driver;
        this.wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    }
 
    // Actions
    public void enterUsername(String username) {
        wait.until(ExpectedConditions.visibilityOfElementLocated(usernameField))
            .sendKeys(username);
    }
 
    public void enterPassword(String password) {
        driver.findElement(passwordField).sendKeys(password);
    }
 
    public DashboardPage clickLogin() {
        driver.findElement(loginButton).click();
        return new DashboardPage(driver);
    }
 
    public DashboardPage login(String username, String password) {
        enterUsername(username);
        enterPassword(password);
        return clickLogin();
    }
 
    public String getErrorText() {
        return wait.until(ExpectedConditions.visibilityOfElementLocated(errorMessage))
            .getText();
    }
 
    public boolean isLoginPageDisplayed() {
        return driver.findElement(usernameField).isDisplayed();
    }
}

Page Factory (Alternative)

package com.yourcompany.pages;
 
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
 
public class LoginPageFactory {
    private WebDriver driver;
 
    @FindBy(id = "username")
    private WebElement usernameField;
 
    @FindBy(id = "password")
    private WebElement passwordField;
 
    @FindBy(id = "login-btn")
    private WebElement loginButton;
 
    @FindBy(css = ".error-message")
    private WebElement errorMessage;
 
    public LoginPageFactory(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }
 
    public void login(String username, String password) {
        usernameField.sendKeys(username);
        passwordField.sendKeys(password);
        loginButton.click();
    }
}

Test Using Page Objects

package com.yourcompany.tests;
 
import com.yourcompany.pages.LoginPage;
import com.yourcompany.pages.DashboardPage;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.*;
 
public class LoginTest {
    private WebDriver driver;
    private LoginPage loginPage;
 
    @BeforeMethod
    public void setup() {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        driver.get("https://example.com/login");
        loginPage = new LoginPage(driver);
    }
 
    @Test
    public void testValidLogin() {
        DashboardPage dashboard = loginPage.login("user@test.com", "password123");
        Assert.assertTrue(dashboard.isWelcomeMessageDisplayed());
    }
 
    @Test
    public void testInvalidLogin() {
        loginPage.login("invalid@test.com", "wrongpassword");
        Assert.assertEquals(loginPage.getErrorText(), "Invalid credentials");
    }
 
    @AfterMethod
    public void teardown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

Advanced Techniques

Handling Alerts

import org.openqa.selenium.Alert;
 
// Wait for alert
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
Alert alert = wait.until(ExpectedConditions.alertIsPresent());
 
// Get alert text
String alertText = alert.getText();
 
// Accept alert (OK)
alert.accept();
 
// Dismiss alert (Cancel)
alert.dismiss();
 
// Send text to prompt
alert.sendKeys("Input text");
alert.accept();

Handling Frames

// Switch to frame by name or ID
driver.switchTo().frame("frameName");
 
// Switch to frame by index
driver.switchTo().frame(0);
 
// Switch to frame by WebElement
WebElement frameElement = driver.findElement(By.cssSelector("iframe.main"));
driver.switchTo().frame(frameElement);
 
// Switch back to main content
driver.switchTo().defaultContent();
 
// Switch to parent frame
driver.switchTo().parentFrame();

Handling Multiple Windows

// Get current window handle
String mainWindow = driver.getWindowHandle();
 
// Click link that opens new window
driver.findElement(By.linkText("Open New Window")).click();
 
// Get all window handles
Set<String> handles = driver.getWindowHandles();
 
// Switch to new window
for (String handle : handles) {
    if (!handle.equals(mainWindow)) {
        driver.switchTo().window(handle);
        break;
    }
}
 
// Do something in new window
System.out.println("New window title: " + driver.getTitle());
 
// Close new window and return to main
driver.close();
driver.switchTo().window(mainWindow);

JavaScript Execution

JavascriptExecutor js = (JavascriptExecutor) driver;
 
// Scroll to element
WebElement element = driver.findElement(By.id("footer"));
js.executeScript("arguments[0].scrollIntoView(true);", element);
 
// Scroll by pixels
js.executeScript("window.scrollBy(0, 500)");
 
// Click via JavaScript (bypasses overlays)
js.executeScript("arguments[0].click();", element);
 
// Get computed style
String color = (String) js.executeScript(
    "return window.getComputedStyle(arguments[0]).color;", element
);
 
// Wait for page load
js.executeScript("return document.readyState").equals("complete");

Taking Screenshots

import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.apache.commons.io.FileUtils;
import java.io.File;
 
// Take screenshot
File screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
 
// Save to file
FileUtils.copyFile(screenshot, new File("screenshots/test-failure.png"));
 
// Screenshot as Base64 (for reports)
String base64 = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BASE64);

Best Practices

1. Use WebDriver Manager

// Instead of manually managing drivers
// System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
 
// Use WebDriver Manager
WebDriverManager.chromedriver().setup();

2. Always Clean Up Resources

@AfterMethod(alwaysRun = true)
public void teardown() {
    if (driver != null) {
        driver.quit();
    }
}

3. Use Explicit Waits, Not Implicit

// Avoid
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
 
// Prefer
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(locator));

4. Create a Base Test Class

public abstract class BaseTest {
    protected WebDriver driver;
    protected WebDriverWait wait;
 
    @BeforeMethod
    public void baseSetup() {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    }
 
    @AfterMethod(alwaysRun = true)
    public void baseTeardown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

5. Use Meaningful Assertions

// Avoid generic assertions
Assert.assertTrue(element.isDisplayed());
 
// Use descriptive messages
Assert.assertTrue(element.isDisplayed(),
    "Login button should be visible on the page");

Test Your Knowledge

Quiz on Selenium with Java

Your Score: 0/10

Question: What is the purpose of WebDriverManager in Selenium Java projects?


Continue Your Selenium Journey


Frequently Asked Questions

Frequently Asked Questions (FAQs) / People Also Ask (PAA)

Which IDE should I use for Selenium with Java?

Should I use TestNG or JUnit for Selenium tests?

What is WebDriver Manager and why should I use it?

How do I handle dynamic elements that take time to load?

What is Page Object Model and why should I use it?

How do I run Selenium tests in headless mode?

Why do I get StaleElementReferenceException?

How do I take screenshots on test failure in TestNG?