Unit 1: Introduction to Selenium

CSE377 — Web Automation Testing 10 min read

I. Orientation

Selenium is an open-source suite for automating web browsers. It was created for testing web applications through real browser interactions such as clicking, typing, navigation, and verification. Selenium automation generally follows the WebDriver standard, in which a test program sends commands to a browser driver, and the driver communicates with the browser.

  • Governing principle: Automate the same user-visible browser actions that occur in a web application.
  • Primary target: Web applications accessed through browsers, rather than desktop applications or native mobile applications.
  • Execution model: A test script sends commands through Selenium WebDriver to a browser-specific driver.
  • Locator principle: Elements are identified using properties such as id, name, CSS selectors, XPath, link text, or tag name.
  • Verification principle: A test is meaningful only when it checks an expected result using assertions or explicit validation.
  • Portability: The same test logic can often run in Firefox, Chrome, Edge, or Safari, with changes mainly to driver configuration.
  • Limitation: Selenium does not automatically determine whether an application is correct; the tester must define actions, expected results, synchronization, and assertions.

II. Selenium

Selenium is a collection of tools and libraries for controlling browsers programmatically. Its modern foundation is Selenium WebDriver, which communicates with browsers using standardized browser automation protocols.

A. Who developed Selenium?

This subsection identifies the people and project history behind Selenium.

  • Original developer: Jason Huggins created Selenium in 2004 while working at ThoughtWorks.
  • Initial purpose: Huggins developed a JavaScript-based tool called JavaScriptTestRunner to reduce repetitive manual testing of an internal web application.
  • Project name: The tool was renamed Selenium because the name contrasted humorously with a competing product called Mercury.
  • Selenium RC contributors: Paul Gross and others helped expand Selenium into a remote browser-control system known as Selenium Remote Control.
  • WebDriver origin: Simon Stewart developed WebDriver to provide more direct and reliable browser automation.
  • Project merger: Selenium WebDriver and Selenium RC were combined around 2009, forming the basis of Selenium 2.
  • Current development: Selenium is maintained as an open-source project by contributors and governed through the Selenium project community.

B. Selenium Components

This subsection explains the major parts of the Selenium ecosystem and their responsibilities.

  • Selenium WebDriver: Provides language bindings and APIs for controlling a browser. Common bindings include Java, Python, C#, JavaScript, and Ruby.
  • Browser drivers: Translate WebDriver commands into browser-specific actions.
    • ChromeDriver: Controls Google Chrome.
    • GeckoDriver: Controls Mozilla Firefox.
    • EdgeDriver: Controls Microsoft Edge.
    • SafariDriver: Controls Safari, with configuration controlled by macOS security settings.
  • Selenium IDE: A browser extension for recording and replaying interactions. It is useful for learning and quick prototypes but is less flexible than coded tests.
  • Selenium Grid: Runs tests across multiple machines, browsers, operating systems, or versions. A test can specify capabilities such as browser name and platform.
  • WebDriver protocol: Defines commands such as creating a session, locating an element, sending keys, clicking, and retrieving page information.
  • Test framework integration: Selenium itself is not a complete test framework. JUnit, TestNG, NUnit, PyTest, or similar frameworks provide test discovery, assertions, fixtures, and reports.

III. Selenium WebDriver Test Development

A Selenium test normally creates a browser session, opens the application under test, locates elements, performs actions, verifies results, and closes the session.

A. Creating your First Selenium script

This subsection demonstrates the basic structure of a Java Selenium script.

  • Driver creation: WebDriver represents the browser session, while ChromeDriver provides Chrome-specific implementation.
  • Navigation: driver.get(url) loads the specified URL.
  • Element location: By.id("q") searches for an element whose HTML id attribute is q.
  • User action: sendKeys("Selenium") enters text, and submit() submits the associated form.
  • Resource cleanup: quit() closes every browser window and ends the WebDriver session.
JAVA
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class FirstSeleniumScript {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();

        try {
            driver.get("https://www.google.com");
            driver.findElement(By.name("q")).sendKeys("Selenium");
            driver.findElement(By.name("q")).submit();

            System.out.println(driver.getTitle());
        } finally {
            driver.quit();
        }
    }
}
  • WebDriver: The interface used for browser operations.
  • driver: A variable referring to the active browser session.
  • By.name("q"): A locator that searches for name="q".
  • getTitle(): Returns the title of the current page.
  • Practical condition: The browser driver must be available through Selenium Manager, a configured executable path, or a compatible driver-management solution.

B. Creating and Running Tests

This subsection distinguishes a reusable automated test from a one-time script.

  • Test structure: A test usually contains setup, test actions, verification, and teardown.
    • Setup: Start the browser and open the required application.
    • Action: Enter data, click controls, or navigate through pages.
    • Verification: Compare actual behavior with an expected result.
    • Teardown: Close the browser even when a test fails.
  • JUnit example: The @Test annotation identifies an executable test method, while @AfterEach performs cleanup after each test.
JAVA
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.*;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

class TitleTest {
    private WebDriver driver;

    @BeforeEach
    void setUp() {
        driver = new ChromeDriver();
    }

    @Test
    void pageTitleContainsExpectedText() {
        driver.get("https://example.com");
        assertTrue(driver.getTitle().contains("Example"));
    }

    @AfterEach
    void tearDown() {
        driver.quit();
    }
}
  • Assertion: assertTrue(condition) fails the test when the condition is false.
  • Isolation: A new browser session per test prevents cookies, state, and navigation from contaminating other tests.
  • Repeatability: Tests should use stable data, deterministic locators, and explicit waits instead of arbitrary delays.
  • Execution: Tests can run from Eclipse, Maven, Gradle, a command line, or a continuous integration server.

IV. Selenium Installation and Legacy Comparison

A working Selenium environment requires a programming language, Selenium libraries, a browser, and a compatible browser driver.

A. Installing Selenium

This subsection describes the normal Java installation process.

  • Java requirement: Install a compatible JDK and verify it with java -version; the JDK supplies the compiler and runtime needed for Java tests.
  • Build dependency: Add Selenium Java to Maven through pom.xml.
XML
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.x.x</version>
    <scope>test</scope>
</dependency>
  • Version selection: Replace 4.x.x with the current stable Selenium 4 version used by the project.
  • Browser requirement: Install Chrome or Firefox separately; Selenium does not install the browser itself.
  • Driver management: Selenium 4 commonly uses Selenium Manager to obtain or locate a compatible driver automatically.
  • Manual configuration: If required, configure a driver explicitly with the system property webdriver.chrome.driver or webdriver.gecko.driver.
  • Validation: Run a small script that opens a page and calls quit(). A browser opening and closing successfully confirms the basic setup.
  • Common failures: Incompatible browser and driver versions, blocked driver downloads, incorrect PATH settings, and missing Java dependencies are frequent installation problems.

B. Comparison with Selenium RC

This subsection compares the historical Selenium Remote Control architecture with WebDriver.

  1. Selenium RC

    • Architecture: The test communicated with an RC server, which injected JavaScript into the browser to perform actions.
    • Browser limitation: JavaScript security restrictions limited how closely RC could control browser behavior.
    • Advantages: RC supported several languages and browsers before WebDriver became widespread.
    • Status: Selenium RC is obsolete and should not be selected for new projects.
  2. Selenium WebDriver

    • Architecture: WebDriver communicates with a browser through a browser-specific driver using native browser automation mechanisms.
    • Control quality: It supports more realistic actions, including navigation, cookies, windows, frames, alerts, and keyboard input.
    • API style: The API is object-oriented and exposes browser and element objects directly.
    • Current use: WebDriver is the standard choice for modern Selenium automation.
  • Concrete distinction: RC required a separate RC server process, whereas a current WebDriver test typically creates new ChromeDriver() or new FirefoxDriver() directly.
  • Migration implication: Existing RC suites should be rewritten or migrated rather than extended, because RC APIs and server architecture are no longer maintained.

V. Application Under Test and Browser Inspection

The application under test, or AUT, is the web application whose behavior is being examined through automated browser actions.

A. Launching AUT and Inspecting properties of Elements

This subsection explains how testers connect visible controls to reliable Selenium locators.

  • Launching AUT: Use driver.get("https://test-site.example/login") to open the application’s entry URL.
  • Inspecting elements: Right-click an element in the browser and choose the developer-tools inspection command to view its HTML.
  • HTML properties: Important attributes include id, name, class, type, value, href, aria-label, and custom data-* attributes.
  • Preferred locator: Use a unique, stable id, such as By.id("login-email"), when one is available.
  • Alternative locator: Use By.cssSelector("[data-testid='login-email']") when the application supplies a stable test attribute.
  • XPath: By.xpath("//button[@type='submit']") can express relationships, but long absolute XPath expressions are fragile.
  • Uniqueness check: A locator should identify the intended element and preferably only one element.
  • Dynamic properties: Auto-generated classes or IDs may change between executions; stable semantic attributes are safer.
  • Element state: Before interaction, verify that the element is present, visible, and enabled.
  • Synchronization: Use explicit waits when the AUT loads content asynchronously.
JAVA
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement email = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.id("login-email"))
);
email.sendKeys("user@example.com");
  • WebDriverWait: Waits up to a specified duration.
  • Duration.ofSeconds(10): Sets the maximum wait to 10 seconds.
  • ExpectedConditions: Supplies a condition that must become true before continuing.

VI. Browser Launch and Development Environment

Browser-specific launching allows the same test design to be executed against different browser engines.

A. Launching AUT in Firefox and Chrome

This subsection shows how to start the AUT in the two commonly used browsers.

  • Chrome launch: new ChromeDriver() creates a Chrome WebDriver session.
JAVA
WebDriver chrome = new ChromeDriver();
chrome.get("https://example.com");
chrome.quit();
  • Firefox launch: new FirefoxDriver() creates a Firefox WebDriver session.
JAVA
WebDriver firefox = new FirefoxDriver();
firefox.get("https://example.com");
firefox.quit();
  • Browser options: ChromeOptions and FirefoxOptions configure arguments, preferences, download behavior, and headless execution.
  • Headless execution: A headless browser runs without displaying a visible window, which is useful on CI servers.
  • Cross-browser comparison: Use the same test steps and locators, but execute them with separate browser drivers.
  • Compatibility condition: The browser, Selenium library, and driver must support compatible versions.
  • Cleanup requirement: Call quit() rather than only close(); quit() ends the complete WebDriver session.

B. Downloading and Configuring latest Eclipse IDE

This subsection covers Eclipse setup for writing and executing Java Selenium tests.

  • Download source: Obtain Eclipse IDE for Java Developers from the official Eclipse distribution site.
  • JDK configuration: Start Eclipse with a supported JDK, then select the project’s installed JDK under Window > Preferences > Java > Installed JREs.
  • Workspace: Choose a workspace directory where Eclipse stores project metadata and source files.
  • Maven project: Create a Maven project so Selenium and test-framework dependencies are declared in pom.xml and downloaded automatically.
  • Project structure: Place production utilities under src/main/java and test classes under src/test/java.
  • Dependency refresh: Use Maven > Update Project after changing pom.xml; Eclipse then resolves the declared Selenium artifacts.
  • Running tests: Right-click a test class or method and select Run As > JUnit Test.
  • Classpath role: Eclipse and Maven place Selenium libraries, JUnit, and transitive dependencies on the test classpath.
  • Configuration check: Confirm that the project compiles, the browser starts, the AUT opens, and the test report records pass or failure.
  • Maintainability: Keep URLs, credentials, locators, and browser configuration separate from test logic where possible, so changes in the AUT do not require rewriting every test.