skip to content

In Selenium 4, how do you point a test at a Grid endpoint instead of starting a local browser?

level: juniorimportance: must knowfreq 76%

answer

  1. one constructor, two arguments
  2. an address plus what you want
  3. the browser is not on your machine
  4. a URL and a Capabilities value
  5. typed options such as ChromeOptions

basics

~20 s

Build a RemoteWebDriver with two arguments: the Grid's URL and an options object such as ChromeOptions. Those options become the session request the Grid routes, and every line of test code after that is unchanged.

solid answer

~50 s

Selenium 4's `RemoteWebDriver` takes a `URL` pointing at the Grid and a `Capabilities` value, in practice a typed options object such as `ChromeOptions` or `FirefoxOptions`. Constructing it sends a new-session request carrying those capabilities to that endpoint; the Grid picks a node whose slot matches, the node starts the browser, and the client gets back a session id it repeats on every later command. What you hold is a `WebDriver`, so navigation, finds and assertions in a survey-builder canvas suite are written exactly as they are locally. Two consequences catch people out: the browser runs on the node, so `localhost` inside `driver.get(...)` means the node's loopback rather than your machine's, and the options object is now a routing key as well as a browser configuration, so ask only for a browser the Grid actually offers.

code

java · 14 lines
java
import java.net.URI;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;

public final class SurveyCanvasSession {

    public static RemoteWebDriver open(String gridEndpoint, String canvasUrl) throws Exception {
        ChromeOptions options = new ChromeOptions();
        RemoteWebDriver driver = new RemoteWebDriver(URI.create(gridEndpoint).toURL(), options);
        System.out.println("grid session " + driver.getSessionId());
        driver.get(canvasUrl);
        return driver;
    }
}

go deeper

for a junior

Be ready to write the constructor from memory: a URL for the Grid and an options object. Know that what comes back is a WebDriver and that the rest of the test does not change.

for a middle

Explain what construction actually sends: a new-session request carrying your capabilities, answered with a session id that every later command repeats over the same endpoint.

for a senior

Show the operational consequences: the browser lives on the node, so addresses, files and screen size belong to that machine, and the endpoint must be reachable from wherever the suite runs.

for a principal

Own where the endpoint value comes from across environments, so one suite runs on a laptop and against a Grid with no code branch and no per-environment fork of the test.

## What a Grid endpoint changes, and what it does not Selenium 4 has one client class for driving a browser that is not on your machine: `RemoteWebDriver`, in `org.openqa.selenium.remote`. It implements the same `WebDriver` interface a local driver does, so pointing a suite at a **Grid** is a change to one line of construction and nothing else. A survey-builder canvas test that drags a rating block onto the canvas, opens the branching-logic panel and asserts that the preview redraws is written identically either way. The constructor takes exactly two things: - a `java.net.URL` — the address the Grid answers on, for example `http://grid.internal:4444`; - a `Capabilities` value — in practice a typed options object such as `ChromeOptions`, `FirefoxOptions` or `EdgeOptions`, because those classes already build a valid W3C capability map. `WebDriver driver = new RemoteWebDriver(endpoint, new ChromeOptions());` is the whole of the wiring. ## What construction actually does 1. The client serialises your options into a **new-session request** and sends it over HTTP to the endpoint you handed it. 2. The Grid reads the requested capabilities and looks for a slot that can serve them. 3. The node holding that slot starts a real browser and creates a session. 4. The Grid answers with a **session id** and with the capabilities the session actually got. 5. Every later command — navigate, find, click, `quit()` — is another HTTP call to that same endpoint carrying the session id. Two facts fall out of steps 3 and 5. First, the browser runs on the node, so everything the browser resolves — host names, ports, the file system, the clock, the screen size — belongs to the node's machine and not to yours. Second, the endpoint is not contacted once at start-up; it sits on the path of every single command, so the latency between client and Grid is paid per command rather than per test. ## Local and remote, side by side | | local driver | `RemoteWebDriver` at a Grid | |---|---|---| | what the constructor needs | an options object | an endpoint URL and an options object | | where the browser runs | the machine running the test | whichever node the Grid picked | | what `localhost` means inside `driver.get(...)` | the machine running the test | the node's own loopback address | | what the options object decides | how the browser is configured | that, plus which slot can serve you | | the type you hold afterwards | `WebDriver` | `WebDriver` | ## The options object now has two jobs Locally an options object configures a browser. Against a Grid it does that **and** acts as the routing key: the Grid compares what you asked for against what its nodes advertise. Ask for a `browserName` and you land on a node offering that browser; pin a version or a platform that no node advertises and there is nothing to land on. The working discipline is to send the least the test genuinely needs. The same object is also where Grid-directed metadata goes, in Selenium's own `se:` capability namespace — a session label, for instance. Those keys are addressed to the Grid and its nodes rather than to the browser. ## What the client can read back `RemoteWebDriver` exposes two things worth logging on the first line of every Grid run: - `getSessionId()` — the identifier the Grid issued, which is how anyone looking at the Grid afterwards finds your session; - `getCapabilities()` — what the session actually received, which is not always what you asked for: an unpinned `browserVersion` comes back filled in with the build that really started. ## Where the endpoint value should live The endpoint is environment data, not test data. Read it from a system property or an environment variable and the same canvas suite runs against a Grid or against a local browser with no code edit and no branch inside the test. Hard-coding it is the most common reason a suite becomes runnable in exactly one place. ## Mistakes on a first Grid run - Navigating to `localhost` and wondering why the canvas never loads: the node's loopback is not yours, and the application under test has to be reachable **from the node**. - Passing the address of one node instead of the address the Grid answers on, so no routing ever happens. - Assuming a file path, a download or a screen size in the test refers to the machine running the test. - Treating a failure to construct as a flaky test and retrying it, instead of reading whether the Grid answered at all. - Expecting the client to be told which node served it; you get a session id and the granted capabilities, and the Grid's own view is where the node is named. None of these are protocol subtleties. They are one fact seen from several angles: the browser is somewhere else, and the URL you passed is the only route to it.

  • What does RemoteWebDriver.getSessionId() give you, and why log it on a Grid run?
    It returns the identifier the Grid issued for that session. Logging it is what lets anyone looking at the Grid afterwards match a failing canvas test to the session that produced it; without it, a shared Grid full of anonymous sessions has to be correlated by timestamp and guesswork.
  • A canvas test navigates to http://localhost:5173 and passes locally but shows a blank page on the Grid. Why?
    The browser is on the node, so `localhost` resolves to the node's own loopback address, where nothing is listening. The application under test has to be reachable from the node: a host name or address the node can resolve, not one that only exists on the machine running the test.

saying these in an interview costs you the question

  • Thinks a Grid run needs a different API than a local WebDriver
  • Assumes localhost in a test URL still means the machine running the test
  • Believes the Grid endpoint is contacted once at start-up only
  • Treats the options object as browser configuration with no routing effect
  • Passes one node's address instead of the address the Grid answers on