Why does Selenium 3 code calling implicitlyWait(10, TimeUnit.SECONDS) fail to compile against Selenium 4, and what replaces it?
answer
- The break happens at compile time
- Selenium 4 uses one time type everywhere
- java.time replaced the unit argument
- Duration.ofSeconds is the new spelling
- The WebDriverWait constructor changed too
basics
~10 sSelenium 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.
solid answer
~40 sSelenium 4 removed the `(long, TimeUnit)` timeout overloads in favour of `java.time.Duration`, so a Selenium 3 suite does not misbehave at run time — it fails to build, which is the cheapest kind of migration error. `driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS)` becomes `implicitlyWait(Duration.ofSeconds(10))`; `pageLoadTimeout(long, TimeUnit)` becomes `pageLoadTimeout(Duration)`; the script timeout was retyped and renamed to `scriptTimeout(Duration)`; and `new WebDriverWait(driver, 10)` becomes `new WebDriverWait(driver, Duration.ofSeconds(10))`. The rewrite is mechanical and safe: the numbers and their meaning are unchanged, only the way the unit is expressed. `Duration` carries the unit inside the value, so a number read from configuration can no longer arrive with its unit sitting in a separate argument somebody forgot to update.
go deeper
Know that Selenium 4 timeouts take a Duration, as in implicitlyWait(Duration.ofSeconds(10)). Recognising Duration.ofSeconds and Duration.ofMillis when you read them in an existing test is what is expected at this level.
Explain that the number-plus-TimeUnit overloads were removed, list the calls that changed including the WebDriverWait constructor, and state clearly that the rewrite changes types rather than waiting behaviour.
Show that you treat the compile break as an asset: let the build enumerate the call sites, rewrite mechanically in one reviewable commit, and resist retuning timeout values while you are in those lines.
Frame the tradeoff between an API change that breaks the build and one that changes behaviour quietly, and describe how you sequence such an upgrade so several teams can absorb it without a shared outage.
## Why the signatures changed **Selenium 4** expresses every timeout as a `java.time.Duration`. The Selenium 3 shape — a number plus a `TimeUnit` constant — has been removed from the client, having been deprecated during the 4.0 transition and dropped from current Selenium 4 releases. So a **real-estate listing-filter** suite carrying `driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS)` does not misbehave when you upgrade: it does not build at all. That is the good case. A migration error that the compiler catches costs you one afternoon of mechanical edits; a migration error that changes behaviour silently costs you weeks of watching test runs. `Duration` also puts the unit inside the value, so a number that travels from a properties file to a timeout call can no longer arrive with its unit attached in a separate argument that somebody forgot to update. ## The exact rewrites | Selenium 3 call | Selenium 4 call | |---|---| | `manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS)` | `manage().timeouts().implicitlyWait(Duration.ofSeconds(10))` | | `manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS)` | `manage().timeouts().pageLoadTimeout(Duration.ofSeconds(30))` | | `manage().timeouts().setScriptTimeout(5, TimeUnit.SECONDS)` | `manage().timeouts().scriptTimeout(Duration.ofSeconds(5))` | | `new WebDriverWait(driver, 10)` | `new WebDriverWait(driver, Duration.ofSeconds(10))` | Note the third row: the script timeout was both retyped and renamed, so a blind find-and-replace on the argument alone leaves that one broken. ## Doing the rewrite safely 1. Build the suite against Selenium 4 and let the compiler produce the list of call sites. That error list is your work queue and it is exhaustive — no grep needed. 2. Rewrite each one by wrapping the existing number in the factory that matches the unit it already used: `Duration.ofSeconds(...)` for a `TimeUnit.SECONDS` argument, `Duration.ofMillis(...)` for a `TimeUnit.MILLISECONDS` one. 3. Change nothing else in the same commit. Do not retune a value because you happen to be editing the line; a mechanical change you can review in one pass is worth far more than a clever one. 4. Build again. A clean build means every timeout call site is migrated, which is a much stronger guarantee than any manual review would give you. ## Where Duration turns up beyond the three timeouts - `new WebDriverWait(driver, Duration)` — the wait constructor takes a `Duration` in Selenium 4, so a bare `10` no longer compiles there either. - `FluentWait.withTimeout(Duration)` and `FluentWait.pollingEvery(Duration)` take `Duration` values, so a helper that built waits from raw numbers needs the same treatment. - `Duration.ZERO` is the spelling for switching a timeout off, which is tidier than passing a literal zero with a unit that no longer means anything. - `Duration.ofSeconds`, `Duration.ofMillis` and `Duration.ofMinutes` are the factories you will use; `Duration` is a standard Java type, not a Selenium one, so it needs no Selenium-specific knowledge to read. - A helper of your own that accepted a number and a `TimeUnit` and passed both through to Selenium now has a signature that lies about what it can do. Change it to accept a `Duration` as well, or it becomes the last place in the suite where a unit and a number travel apart. - Anything that stored a timeout as a field — a page object holding a wait, a base class holding a configured number of seconds — is worth retyping to `Duration` in the same pass, so the whole harness speaks one time type rather than converting at every boundary. ## What the change does not do The meaning of each timeout is untouched. `Duration.ofSeconds(10)` expresses exactly what `10, TimeUnit.SECONDS` expressed, and the browser waits for the same length of time it always did. This is worth stating explicitly in an interview, because the obvious follow-up thought — "so did the waiting behaviour change too?" — is a trap. If a listing-filter test starts timing out after the upgrade, the `Duration` rewrite is not the cause; look at what else moved in the same change. Two practical consequences follow from that: - You can review the diff on shape alone. Every hunk should be one call whose numeric literal is unchanged and whose unit is preserved. Any hunk where the number changed deserves a question. - You can migrate the timeout call sites independently of anything else in the upgrade, and land that commit on its own. ## A worked fragment from the listing-filter suite ```java Duration pageLoad = Duration.ofSeconds( Integer.parseInt(System.getProperty("listings.pageLoadSeconds", "30"))); driver.manage().timeouts().pageLoadTimeout(pageLoad); driver.manage().timeouts().implicitlyWait(Duration.ZERO); driver.manage().timeouts().scriptTimeout(Duration.ofSeconds(10)); WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); ``` Read that against the Selenium 3 original and the pattern is clear: the configuration value is still a plain integer where it is read, and the unit is decided exactly once, at the boundary where the number becomes a `Duration`. That is the habit the API change is nudging a suite towards, and it is why the rewrite is worth doing properly rather than with a regular expression.
- Why is a compile break a better migration outcome than a silently changed default?Because the compiler enumerates every call site for you and the list is exhaustive. A removed signature turns a whole class of upgrade risk into a build failure fixed once, whereas a silent behaviour change has to be discovered by watching test runs, sometimes for weeks.
- A timeout arrives from a properties file as the number 30. What do you do with it now?Parse it and wrap it once at the boundary: `Duration.ofSeconds(30)`. Decide the unit where the value is read rather than passing a bare number around the harness. That is the point of `Duration` — the unit travels with the value instead of living in a second argument.
- Does switching to Duration change how long anything waits?No. `Duration.ofSeconds(10)` expresses exactly what `10, TimeUnit.SECONDS` expressed, so the browser waits the same length of time. It is a type change, not a behaviour change. If a test starts timing out after the upgrade, look for something else that moved in the same commit.
saying these in an interview costs you the question
- Claims the Duration change also altered how long each timeout waits
- Thinks TimeUnit still works if you add a cast
- Rewrites seconds as milliseconds and multiplies the value by mistake
- Says the failure appears at run time rather than at compile time
- Leaves WebDriverWait constructed with a bare number argument