Selenium
Selenium is the common language of browser automation. It gives test code a W3C WebDriver session, then lets that code navigate, find elements, interact with the page, collect evidence, and close the browser in a predictable way.
This tutorial starts with the framework itself and then maps the same ideas to webmate. Use it when you already have a web application, need a reliable cross-browser smoke test, and want the option to run the same test against browsers managed outside your laptop.
Goal
By the end of this tutorial you will have a small Selenium test that opens a browser, uses stable locators, waits for page state instead of sleeping, captures a screenshot, and closes the session cleanly. You will also understand the difference between a local driver and a remote Selenium Hub, which is the key concept behind running Selenium on webmate.
The examples use Java because Selenium’s Java bindings are common in webmate examples. The same structure applies to Python, JavaScript, C#, Ruby, and Kotlin: create browser options, start a driver, perform interactions, assert the result, and quit the session.
Before You Start
You need a working test project, a reachable application URL, and a decision about where the browser will run. For a local first test, install the Selenium binding for your language and make sure a supported browser is installed. For remote execution, you need the hub URL and the capabilities that describe the browser, platform, and any vendor-specific options.
Selenium 4 expects W3C-compatible capabilities. Browser-specific options such as ChromeOptions or FirefoxOptions are the normal place to set browserName, browserVersion, platformName, and provider-specific extension capabilities. For webmate, those extension capabilities include webmate-specific keys such as the API key and project information described in the existing Web Testing documentation.
Project Setup
A minimal Java project needs Selenium WebDriver and a test runner such as JUnit. Keep the first test deliberately small. Large Selenium suites fail in confusing ways when the first version mixes authentication, fixtures, data creation, browser configuration, and assertions in one place.
| |
The important choice is where the driver is created. Local execution uses a browser-specific driver class. Remote execution uses RemoteWebDriver and a hub URL. Keep all configuration close to driver creation so it is easy to switch between local and remote runs.
Step 1: Start With a Local Browser
Local execution is the fastest way to prove that selectors and assertions are correct. It also gives developers a simple loop while writing tests.
| |
There are three habits worth keeping from the first test. First, create one browser session per test or per tightly controlled fixture. Second, use explicit waits for observable page state. Third, always quit the driver in a finally block or test cleanup hook. Remote browsers are real resources; leaving sessions open makes later test failures harder to understand.
Step 2: Use Stable Locators
Most Selenium maintenance cost comes from selectors that describe the current markup instead of the user-facing contract. Prefer attributes that the team treats as stable, such as data-testid, accessible names, labels, or form names. Use CSS selectors for simple DOM relationships and XPath when you need text or tree traversal that CSS cannot express cleanly.
Avoid selectors that depend on generated class names, nth-child chains, or layout-only wrappers. A locator should survive a visual redesign when the user interaction has not changed.
Step 3: Wait for Behavior, Not Time
Hard sleeps hide race conditions and slow the suite down. Selenium’s explicit waits poll until a condition is true or a timeout is reached. Use them for navigation, element visibility, enabled states, text updates, and asynchronous UI results.
Set timeouts according to the application and environment. A local development server may respond quickly, while a remote browser running through a real device cloud may need more time for startup and network traffic. The goal is not to make waits large; it is to wait for the right signal.
Step 4: Capture Evidence
Screenshots are useful when a failure happens in a browser that is not visible on your desk. Selenium exposes screenshots through TakesScreenshot.
In a mature suite, capture screenshots only on failure and name them with the test, browser, platform, and timestamp. On webmate, also use the Test Lab and session views to inspect the remote execution context. The existing webmate Selenium pages describe capabilities that can enrich the recorded session with names, tags, and automatic screenshots.
Step 5: Move to Remote WebDriver
Remote execution changes driver creation, not the intent of the test. The test still navigates, finds elements, clicks, types, waits, and asserts. The difference is that Selenium sends WebDriver commands to a remote endpoint, and the remote service starts the browser.
| |
For a local Selenium Grid, the URL might be http://localhost:4444/. For webmate, use the Selenium endpoint documented in the Web Testing section. The pattern is the same: configure browser options, add capabilities, create RemoteWebDriver, then run the test.
Step 6: Add webmate Capabilities
webmate-specific configuration belongs in capabilities because it describes the requested environment and how the session should be organized. Existing webmate docs show capabilities for the API key, project, browser, platform, browser version, test naming, tags, and screenshot behavior.
| |
Keep secrets in environment variables or CI secret storage. Do not commit API keys to the repository. When a capability is optional, start without it and add it only when it improves scheduling, reporting, or debugging.
Run in CI
CI should run the same command developers run locally, with environment variables injected by the pipeline. A simple job needs the application under test, the test dependencies, and the WebDriver target.
Separate smoke tests from long compatibility suites. Run a small browser set on every merge request and a broader browser or platform matrix nightly. That keeps feedback fast without losing coverage.
Debugging Checklist
When a Selenium test fails before the first assertion, inspect session creation first. Check the hub URL, credentials, project identifier, browser name, platform name, and browser version. A capability typo can fail before the application ever loads.
When the test reaches the page but cannot find an element, inspect the locator and the wait condition. Confirm that the element exists in the rendered DOM, that it is not inside a different frame, and that the test is not racing an asynchronous update.
When a click does nothing, check whether another element overlays the target, whether the target is disabled, and whether the application requires scrolling or a different user gesture. Avoid forcing JavaScript clicks until you understand why a real click failed.
When failures appear only remotely, compare the local and remote browser versions, viewport, operating system, network path, and test data. Remote execution is valuable because it exposes those differences; treat them as signals rather than noise.
Verify the Result
A good first Selenium tutorial outcome is modest: the test starts a session, reaches the target page, interacts through stable locators, waits for an observable result, records evidence on failure, and always quits the session. Once that is reliable, extend the suite with page objects or screen objects, test data helpers, and a browser matrix.
Next Steps
Continue with the existing webmate Selenium getting-started guide for product-specific setup. Use Selenium capabilities when you need detailed environment configuration, and Using the SDK when you want to connect automated sessions with broader webmate workflows.