skip to content

Ecosystem and Positioning

Where Selenium sits among the other browser tools and its five client languages: what is genuinely portable, what a rival runner buys, and what a version jump breaks.

on this pageshow

explore

questions

22

In Selenium 4, what replaces the Selenium 3 DesiredCapabilities object when you start a local Chrome session?

level: juniorimportance: must knowfreq 78%

answer

  1. Selenium 4 configures sessions per browser
  2. One object per browser, not a shared bag
  3. The class name ends in Options
  4. ChromeOptions, FirefoxOptions, EdgeOptions
  5. Pass it straight to the driver constructor

basics

~10 s

A browser Options object. In Selenium 4 you build ChromeOptions, FirefoxOptions or EdgeOptions and pass it to the driver constructor; DesiredCapabilities is no longer how a local session is configured.

solid answer

~40 s

In Selenium 4 you configure a session with a browser `Options` object: `ChromeOptions`, `FirefoxOptions`, `EdgeOptions` or `SafariOptions`. You build one, set what the test needs on it — `addArguments("--window-size=1440,900")` for a switch, `setAcceptInsecureCerts(true)`, `setPageLoadStrategy(...)` — and hand it straight to the driver with `new ChromeDriver(options)`. Each Options class implements `Capabilities`, so the same object satisfies any API that asks for capabilities, and the browser-specific parts are serialised under the right prefixed key without you spelling it out. `DesiredCapabilities` still exists as a plain capability bag and Selenium 3 code that builds one still compiles, which is why the old shape survives an upgrade and only fails when the session starts. If a standard capability arrives from configuration, merge it with `options.merge(caps)` and pass the Options object on.

code

java · 22 lines
java
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

public class ListingFilterTest {

    public static void main(String[] args) {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--window-size=1440,900");
        options.setAcceptInsecureCerts(true);
        WebDriver driver = new ChromeDriver(options);
        try {
            driver.get("https://homes.example.com/search");
            driver.findElement(By.id("min-bedrooms")).sendKeys("3");
            driver.findElement(By.id("apply-filters")).click();
            System.out.println(driver.findElements(By.className("listing-card")).size());
        } finally {
            driver.quit();
        }
    }
}

go deeper

for a junior

Recall the three names you will meet daily, ChromeOptions, FirefoxOptions and EdgeOptions, and that one of them goes into the driver constructor. Being able to write six lines that start a configured Chrome session is the bar here.

for a middle

Explain that each Options class is a Capabilities implementation, what its typed setters produce in the session request, and why Selenium 3 DesiredCapabilities code still compiles yet fails the moment a session starts.

for a senior

Show that you would centralise session configuration in one factory the whole suite calls, and that you can migrate capabilities arriving from configuration files without leaving invalid key names behind in them.

for a principal

Be ready to argue what belongs in code versus configuration for browser setup across several teams, and how you prevent each team inventing its own capability keys that only fail in someone else's pipeline.

## What an Options object is In **Selenium 4** you configure a browser session with a browser-specific **Options** object rather than a generic capability bag. `ChromeOptions`, `FirefoxOptions`, `EdgeOptions` and `SafariOptions` are ordinary Java objects with typed setters; you build one, set what the session needs, and pass it to the driver constructor. For a **real-estate listing-filter** test that means the window size, the certificate policy and any browser switch live in one object built once, not in a map of strings assembled per test. Each of these classes is also a `Capabilities` implementation. `ChromeOptions` extends `ChromiumOptions`, which extends `AbstractDriverOptions`, which extends `MutableCapabilities` — so anywhere the Selenium API asks for capabilities, an Options object satisfies it. That is the shape of the whole migration: a typed builder that is still usable through the untyped interface. ## The ones you will actually use | Browser | Options class | Prefixed bucket it produces | |---|---|---| | Chrome | `ChromeOptions` | `goog:chromeOptions` | | Firefox | `FirefoxOptions` | `moz:firefoxOptions` | | Edge | `EdgeOptions` | `ms:edgeOptions` | | Safari | `SafariOptions` | `safari:` prefixed keys | You never write those bucket names yourself. Adding a Chrome switch with `options.addArguments("--window-size=1440,900")` is what puts it in the Chrome bucket; that is the value of the typed API over hand-assembled strings. ## What the setters give you - **Typed standard setters** — `setAcceptInsecureCerts(boolean)`, `setPageLoadStrategy(...)`, `setBrowserVersion(String)` — write the standard W3C capability names, and cannot misspell them. - **`addArguments(String...)`** on `ChromeOptions`, `FirefoxOptions` and `EdgeOptions` passes command-line switches to the browser process itself. A switch is not a capability; it is browser configuration carried inside the browser-specific bucket. - **`FirefoxOptions.addPreference(String, Object)`** does the equivalent job for Firefox preferences. - **`setBinary(...)`** points at a specific browser executable when the default is not the one you want. - **`setCapability(String, Object)`** is still there for anything with no typed setter, and it is the one call in this list that can produce an invalid name. ## Doing the migration 1. Find the driver factory. A Selenium 3 suite almost always has one place that builds capabilities and constructs the driver; that is the only file most upgrades need to touch. 2. Replace the `DesiredCapabilities` bag with the Options class for the browser it starts. 3. Move each key onto a typed setter, one at a time. Browser switches become `addArguments`; standard capabilities become their typed setter. 4. Pass the object to the constructor: `new ChromeDriver(options)`. 5. Run one listing-filter test, then delete the now-unused `DesiredCapabilities` import so nobody copies the old shape back in. ```java ChromeOptions options = new ChromeOptions(); options.addArguments("--window-size=1440,900"); options.setAcceptInsecureCerts(true); WebDriver driver = new ChromeDriver(options); driver.get("https://homes.example.com/search?minBeds=3&maxPrice=450000"); ``` ## What happened to DesiredCapabilities It still exists. `DesiredCapabilities` in Selenium 4 is a mutable capability bag, and Selenium 3 code that builds one compiles unchanged against the Selenium 4 client. What is gone is its **role**: it is no longer how you configure and start a browser session. That distinction matters during an upgrade, because it explains a confusing symptom — the build is green and every test still fails at the session request. The check moved out of the compiler and into the new-session call. If a legitimate standard capability arrives from outside your code — a value read from configuration, say — you do not have to abandon the typed object to carry it. Build the Options object, then merge the bag into it and pass the Options object on: - `options.merge(caps);` folds the entries of a `Capabilities` instance into the Options object. - After merging, the Options object is still the thing you construct the driver with. - Anything in that bag with a non-standard, unprefixed name will still be refused, so merging is a way to carry values across, not a way to keep old key names alive. ## Mistakes that survive compilation - Setting a Chrome switch with `setCapability("chromeOptions", ...)` instead of `ChromeOptions.addArguments(...)`. It compiles; it does not start a session. - Assuming one Options class covers every browser. `EdgeOptions` and `ChromeOptions` are both Chromium-based, but Firefox and Safari have their own classes, and a suite that runs several browsers needs a factory that returns the right one. - Treating the upgrade as a dependency bump. Changing the version in the build file is the smallest part; the driver factory is where the actual work is. - Building a fresh Options object per test and drifting between them, so two listing-filter tests quietly run with different window sizes.

  • Why can a ChromeOptions object be used anywhere the Selenium API asks for capabilities?
    Because `ChromeOptions` extends `MutableCapabilities` and therefore implements `Capabilities`. The typed builder and the untyped interface are the same object, which is what makes the migration cheap: you build configuration once with setters that cannot misspell a key, and pass it wherever capabilities are wanted.
  • A Selenium 3 suite reads capability names out of a properties file. What changes at upgrade?
    That file becomes a source of invalid keys no compiler can check. Map each entry onto a typed Options setter, keep only genuinely standard capability names as free-form strings, and move anything browser-specific into the Options object. Otherwise the suite fails at the session request with a key that never appears in code.
  • Does DesiredCapabilities still exist in Selenium 4?
    Yes, as an ordinary mutable capability bag, and old code that builds one compiles unchanged. What is gone is its role as the way to configure a browser session. Keys it carries are validated when the session request is made, so the failure moves from build time to run time.

saying these in an interview costs you the question

  • Believes DesiredCapabilities was deleted from Selenium 4 entirely
  • Sets Chrome switches with setCapability rather than ChromeOptions.addArguments
  • Thinks one Options class covers every browser the suite drives
  • Says the upgrade only needs a new dependency version and no code change
  • Confuses browser command-line switches with W3C capabilities
open as a page

After upgrading to Selenium 4.6 or later, which driver-binary setup code can you delete, and why?

level: juniorimportance: must knowfreq 66%

basics

~20 s

The driver-path setup. Selenium 4.6 and later bundle Selenium Manager, which locates or downloads a matching browser driver when no driver path is set, so the webdriver.chrome.driver property and any third-party driver-manager bootstrap can be deleted.

open as a page

In Selenium 4, why can one test body drive Chrome, Firefox, Edge and Safari without a rewrite?

level: juniorimportance: must knowfreq 76%

basics

~20 s

Because every one of those browsers is automated through the same W3C WebDriver command set. Only the driver and options objects built at start-up differ; finding elements, clicking, reading text and waiting are identical calls.

open as a page

Which languages does the Selenium project itself ship client bindings for at Selenium 4?

level: juniorimportance: must knowfreq 68%

basics

~10 s

Selenium 4 ships official clients for Java, Python, C#/.NET, Ruby and JavaScript. Other languages such as PHP, R and Rust are covered by community bindings maintained outside the project, which speak the same protocol.

open as a page

In Selenium 4's JavaScript client, why must nearly every driver call be awaited?

level: middleimportance: must knowfreq 58%

basics

~20 s

Because every command returns a promise rather than a value, and Selenium 4 removed the old control flow that ordered commands for you. Without await you hold a promise, which is always truthy, so conditions silently pass.

open as a page

Why does Selenium 3 code calling implicitlyWait(10, TimeUnit.SECONDS) fail to compile against Selenium 4, and what replaces it?

level: middleimportance: must knowfreq 55%

basics

~10 s

Selenium 4 dropped the number-plus-TimeUnit overloads. Timeouts now take a java.time.Duration, so the call becomes implicitlyWait(Duration.ofSeconds(10)), and pageLoadTimeout, scriptTimeout and the WebDriverWait constructor changed the same way.

open as a page

In Selenium 4, what does driving the browser out of process over the W3C WebDriver protocol buy a team?

level: middleimportance: must knowfreq 68%

basics

~20 s

A standard contract. The same test body drives the real Chrome, Firefox, Edge or Safari a user has installed, through drivers the browser vendors ship, on this machine or on a remote one, from five official languages.

open as a page

Selenium 4 ships no test runner or reporter of its own — what does that unbundling gain and cost?

level: middleimportance: must knowfreq 60%

basics

~20 s

You gain a browser layer that drops into the runner, assertion library and report a team already uses, in five languages. You pay by assembling and maintaining that harness yourself: setup, waits, failure evidence and parallelism are your code.

open as a page

In Selenium 4, what breaks when a Java wait helper for a report-card page is hand-ported to Python?

level: seniorimportance: must knowfreq 48%

basics

~20 s

Four surfaces change: method names go snake_case, the single By object becomes two arguments (a tuple inside condition helpers), the Duration timeout becomes a bare number of seconds, and text is read as a property.

open as a page

After upgrading a Selenium 3 real-estate listing-filter suite to Selenium 4, every new session fails with an invalid argument error — how do you diagnose and fix it?

level: seniorimportance: must knowfreq 50%

basics

~20 s

Selenium 4 sends only W3C capabilities, and the remote end rejects any top-level key that is neither a standard capability nor vendor-prefixed. Find the leftover Selenium 3 keys, rename them, and move browser-specific ones into a browser Options object.

open as a page

In Selenium's Python client, why must a locator given to expected_conditions be wrapped in a tuple?

level: juniorimportance: should knowfreq 50%

basics

~20 s

Because those helpers take one locator argument, while find_element takes two. The pair goes in as a single value, and a single value holding two things is a tuple, which is why the call shows double parentheses.

open as a page

What does Selenium IDE record into a .side project file as you click through a page?

level: juniorimportance: should knowfreq 52%

basics

~10 s

Selenium IDE writes each interaction as a row of three fields - command, target and value - into a JSON project file with a .side extension, grouped into named tests and suites.

open as a page

Why does Selenium's Python client write find_element(By.ID, "x") where Java writes findElement(By.id("x"))?

level: middleimportance: should knowfreq 55%

basics

~20 s

Java's By is a factory that returns one locator object holding both the strategy and the value. Python's By is a set of strategy constants, so the strategy and the value stay two separate arguments.

open as a page

In Selenium 4, what is identical across the official Java, Python, C#, Ruby and JavaScript clients?

level: middleimportance: should knowfreq 58%

basics

~20 s

Everything that crosses the wire is identical: the W3C command set, the capability key names and the error codes. What differs is the local package around them, including class names, method spelling and which support helpers ship.

open as a page

A Selenium IDE recording replays green against a solar-panel yield report - what must be added before it is a regression test?

level: middleimportance: should knowfreq 58%

basics

~20 s

Assertions, because a recording only replays actions and never checks results. Then conditional waitFor commands in place of pause, steadier locators than the recorder's positional XPath fallbacks, variables in place of recorded literals, and a defined starting state.

open as a page

In Selenium 4, how do you cover a Safari and Internet Explorer mode sign-off for a festival lineup planner?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Treat it as a host-placement problem. Safari is driven by safaridriver on macOS, Internet Explorer mode by the Internet Explorer driver on Windows, so one unchanged suite runs against a self-hosted Grid with a node on each platform.

open as a page

What do you weigh before writing a Selenium suite in a community-maintained language binding?

level: seniorimportance: should knowfreq 30%

basics

~20 s

Capability is rarely the problem: a community client speaks the same protocol and drives the same drivers and self-hosted Grid. The risks are stewardship ones, including release lag behind Selenium, incomplete command coverage and no project support.

open as a page

How does Selenium's shared W3C error code help you triage a failure another language's client reported?

level: seniorimportance: should knowfreq 38%

basics

~20 s

The remote end names every failure with the same fixed code whatever client asked, so mapping both reports back to that code tells you immediately whether two suites hit one browser-side condition or two different problems.

open as a page

Your Selenium page classes use Java's @FindBy; what must change when the suite moves to the Python client?

level: seniorimportance: should knowfreq 40%

basics

~20 s

The annotated fields have no equivalent, so they become explicit find calls. Locator strings, locator strategies and the page structure port unchanged; the real risk is resolving elements in the constructor and changing when the lookup happens.

open as a page

When you export a Selenium IDE recording to JUnit code and then edit it, what have you given up?

level: seniorimportance: should knowfreq 42%

basics

~10 s

The recording, in practice. Export is one-way with no import back into the .side project, so the first hand edit makes the two artefacts diverge and re-recording silently overwrites your work.

open as a page

How does Selenium's Ruby client spell a locator such as an id, compared with Java's By?

level: juniorimportance: nice to knowfreq 28%

basics

~10 s

Ruby passes a hash whose key names the strategy: find_element(id: 'term-average'). There is no locator object to build, unlike Java's By.id, and the two-positional form find_element(:id, 'term-average') also works.

open as a page

What does the selenium-side-runner command line let you do with a .side project that Selenium IDE cannot?

level: middleimportance: nice to knowfreq 34%

basics

~20 s

It runs a recorded .side project without the browser extension, from a script or pipeline, choosing the browser and target environment by flag, running tests in parallel or on a remote Grid, and exiting non-zero when one fails.

open as a page