← Blog

"Selenium Series #3: Browser Drivers — ChromeDriver, GeckoDriver and WebDriverManager"

Understand why browser drivers exist, how WebDriverManager eliminates manual driver management, and how to configure Chrome and Firefox with options, profiles and capabilities.

reading now
views
comments

Series Navigation

Part 2: Project Setup — Maven, Dependencies and Your First Test

Part 4: Locators — ID, Name, XPath, CSS and Beyond


Why Do Browser Drivers Exist?

Browsers are written in C++. Your Selenium test is written in Java. They cannot talk directly. Browser drivers are the bridge.

Java Test Code
      │
      │  HTTP (JSON Wire Protocol / W3C WebDriver Protocol)
      ▼
ChromeDriver.exe        ← written by Google's Chrome team
      │
      │  Chrome DevTools Protocol (CDP)
      ▼
Chrome Browser

Each browser has its own driver maintained by the browser's own team:

Browser Driver Maintained By
Chrome ChromeDriver Google Chrome Team
Firefox GeckoDriver Mozilla
Edge EdgeDriver (msedgedriver) Microsoft
Safari SafariDriver Apple (built into macOS)
Internet Explorer IEDriverServer Selenium Project

The Version Mismatch Problem

ChromeDriver must match your Chrome browser version exactly. Chrome auto-updates, so this breaks constantly:

Chrome 85  →  needs ChromeDriver 85
Chrome 86  →  needs ChromeDriver 86  ← Chrome updated, test breaks
Chrome 87  →  needs ChromeDriver 87

Without automation, every Chrome update requires you to:

  1. Check your Chrome version
  2. Go to chromedriver.chromium.org
  3. Download the matching driver
  4. Replace the old file
  5. Update the path in your code

This breaks CI pipelines at 2am when Chrome updates silently.


WebDriverManager — The Solution

WebDriverManager (by Bonigarcia) detects your browser version and downloads the matching driver automatically at runtime:

// Before WebDriverManager — manual path management
System.setProperty("webdriver.chrome.driver", "C:/drivers/chromedriver_85.exe");
WebDriver driver = new ChromeDriver();

// After WebDriverManager — one line, works forever
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();

What happens when you call .setup():

1. Detect Chrome version installed on this machine (e.g. Chrome 86)
2. Check local cache: ~/.m2/repository/webdriver/...
3. If not cached → download ChromeDriver 86 from chromedriver.chromium.org
4. Set the system property automatically
5. Done — driver is ready to use

WebDriverManager for All Browsers

import io.github.bonigarcia.wdm.WebDriverManager;

// Chrome
WebDriverManager.chromedriver().setup();
WebDriver driver = new ChromeDriver();

// Firefox
WebDriverManager.firefoxdriver().setup();
WebDriver driver = new FirefoxDriver();

// Edge
WebDriverManager.edgedriver().setup();
WebDriver driver = new EdgeDriver();

// Safari (macOS only — no driver download needed)
WebDriver driver = new SafariDriver();

// Opera
WebDriverManager.operadriver().setup();
WebDriver driver = new OperaDriver();

ChromeOptions — Configuring Chrome Behaviour

ChromeOptions lets you control how Chrome launches:

ChromeOptions options = new ChromeOptions();

// Window settings
options.addArguments("--start-maximized");        // open maximized
options.addArguments("--window-size=1920,1080");  // exact size (for headless)
options.addArguments("--incognito");              // incognito mode

// Disable UI elements that interfere with tests
options.addArguments("--disable-notifications");  // block notification popups
options.addArguments("--disable-infobars");       // hide "automated" info bar
options.addArguments("--disable-extensions");     // disable all extensions
options.addArguments("--disable-popup-blocking"); // allow popups in tests

// Performance
options.addArguments("--no-sandbox");             // required in Linux/Docker
options.addArguments("--disable-dev-shm-usage");  // required in Docker

// Headless mode (no visible browser window)
options.addArguments("--headless");               // run without UI
options.addArguments("--disable-gpu");            // required for headless on some systems

// Ignore SSL certificate errors
options.addArguments("--ignore-certificate-errors");
options.setAcceptInsecureCerts(true);

WebDriver driver = new ChromeDriver(options);

Controlling Download Behaviour

ChromeOptions options = new ChromeOptions();

Map<String, Object> prefs = new HashMap<>();
// Set custom download directory
prefs.put("download.default_directory", "/tmp/downloads");
// Don't show download dialog
prefs.put("download.prompt_for_download", false);
// Don't open PDFs in browser
prefs.put("plugins.always_open_pdf_externally", true);

options.setExperimentalOption("prefs", prefs);
WebDriver driver = new ChromeDriver(options);

FirefoxOptions — Configuring Firefox

import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.firefox.FirefoxProfile;

// Basic Firefox options
FirefoxOptions options = new FirefoxOptions();
options.addArguments("--width=1920");
options.addArguments("--height=1080");
options.setHeadless(true);  // headless mode

// Firefox profile for custom settings
FirefoxProfile profile = new FirefoxProfile();
// Accept untrusted certificates
profile.setAcceptUntrustedCertificates(true);
profile.setAssumeUntrustedCertificateIssuer(false);
// Custom download folder
profile.setPreference("browser.download.dir", "/tmp/downloads");
profile.setPreference("browser.download.folderList", 2);
profile.setPreference("browser.helperApps.neverAsk.saveToDisk",
    "application/pdf,application/octet-stream");

options.setProfile(profile);

WebDriverManager.firefoxdriver().setup();
WebDriver driver = new FirefoxDriver(options);

EdgeOptions — Configuring Microsoft Edge

import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;

EdgeOptions options = new EdgeOptions();
options.addArguments("--start-maximized");
options.addArguments("--disable-notifications");
options.setCapability("acceptInsecureCerts", true);

WebDriverManager.edgedriver().setup();
WebDriver driver = new EdgeDriver(options);

DesiredCapabilities (Legacy — Still Used in Selenium Grid)

DesiredCapabilities is the older way to configure browsers, still used when connecting to Selenium Grid or cloud providers (BrowserStack, Sauce Labs):

import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import java.net.URL;

DesiredCapabilities caps = new DesiredCapabilities();
caps.setBrowserName("chrome");
caps.setVersion("86.0");
caps.setPlatform(Platform.WINDOWS);
caps.setCapability("resolution", "1920x1080");

// Connect to remote Selenium Grid or cloud
WebDriver driver = new RemoteWebDriver(
    new URL("http://hub:4444/wd/hub"),
    caps
);

Browser Driver Factory — Clean Architecture

Rather than duplicating browser setup code, create a factory:

// src/test/java/com/yourname/selenium/base/DriverFactory.java
package com.yourname.selenium.base;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;

public class DriverFactory {

    public static WebDriver createDriver(String browserName) {
        switch (browserName.toLowerCase()) {
            case "chrome":
                return createChromeDriver();
            case "firefox":
                return createFirefoxDriver();
            case "edge":
                return createEdgeDriver();
            default:
                throw new IllegalArgumentException(
                    "Browser not supported: " + browserName +
                    ". Supported: chrome, firefox, edge"
                );
        }
    }

    private static WebDriver createChromeDriver() {
        WebDriverManager.chromedriver().setup();
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        options.addArguments("--disable-notifications");
        options.addArguments("--disable-infobars");
        options.addArguments("--no-sandbox");
        options.addArguments("--disable-dev-shm-usage");
        return new ChromeDriver(options);
    }

    private static WebDriver createFirefoxDriver() {
        WebDriverManager.firefoxdriver().setup();
        FirefoxOptions options = new FirefoxOptions();
        options.addArguments("--width=1920", "--height=1080");
        return new FirefoxDriver(options);
    }

    private static WebDriver createEdgeDriver() {
        WebDriverManager.edgedriver().setup();
        EdgeOptions options = new EdgeOptions();
        options.addArguments("--start-maximized");
        return new EdgeDriver(options);
    }
}

Use it in BaseTest:

@BeforeMethod
public void setUp() {
    // Read browser from config.properties or system property
    String browser = System.getProperty("browser",
        config.getProperty("browser", "chrome"));

    WebDriver driver = DriverFactory.createDriver(browser);
    driverThreadLocal.set(driver);
}

Now run tests on different browsers without changing code:

mvn test -Dbrowser=chrome
mvn test -Dbrowser=firefox
mvn test -Dbrowser=edge

What's Next

In Part 4 we go deep on locators — the most critical skill in Selenium. We cover ID, Name, XPath, CSS selectors, link text, and how to choose the right strategy for every situation.

Discussion

Loading...

Leave a Comment

All comments are reviewed before appearing. No links please.

0 / 1000