skip to content

In Selenium, why does waiting on invisibilityOfElementLocated get slow once the session also has an implicit wait?

level: middleimportance: should knowfreq 47%

answer

  1. Success here means the lookup failed
  2. The slow answer is the wanted answer
  3. Positive conditions return early, negative ones cannot
  4. The remote end retries before saying not-found
  5. findElements empty list pays on every poll

basics

~20 s

Selenium's invisibility condition succeeds by catching a not-found error from findElement. With an implicit wait set, the remote end retries the lookup for the whole implicit timeout before reporting not-found, so every success pays that cost.

solid answer

~40 s

`ExpectedConditions.invisibilityOfElementLocated(By)` calls `driver.findElement(locator)`, negates `isDisplayed()`, and catches `NoSuchElementException` or `StaleElementReferenceException` to return `true`. Its happy path is therefore a *failed* find — and a failed find is exactly what an implicit wait makes expensive, because the W3C find algorithm keeps re-running the location strategy while the result is empty until the implicit timer fires. With a 10-second implicit wait, a check that the booked badge has gone cannot finish in under 10 seconds even when the badge vanished instantly. `numberOfElementsToBe(By, 0)` is worse: `findElements` returns an empty list rather than throwing, so every poll pays the full implicit wait. The fix is to leave the implicit wait at `Duration.ZERO`, its default, and let the explicit wait do the polling.

go deeper

for a junior

Recall that a Selenium condition proving something is absent has to ask for the element first, and that an implicit wait makes every unsuccessful lookup slow.

for a middle

Be ready to explain the asymmetry: positive conditions return as soon as the element appears, while negative ones can only conclude once the remote end has exhausted its implicit-wait retry budget.

for a senior

An interviewer expects you to spot this in a green run rather than a failing one — minutes of wall clock spent in assertions that pass, and the profiling reasoning that leads from run time to the implicit wait setting.

for a principal

Own the guidance that suites prefer positive readiness signals over absence checks where the application can provide one, and the reasoning about what a suite's total waiting time should be spent on.

## Absence is proved by an exception `ExpectedConditions.invisibilityOfElementLocated(By)` in Selenium's Java support library is written like this: it calls `driver.findElement(locator)`, returns the negation of `isDisplayed()`, and catches `NoSuchElementException` and `StaleElementReferenceException`, returning `true` for either. In other words, the **happy path of a negative condition is a failed find**. The condition does not have a way to observe "nothing is there" cheaply; it observes it by asking for the element and being told there is none. That is fine when the session's implicit wait is at its default of zero. It becomes the slowest thing in a suite the moment an implicit wait is also set. ## What the remote end does before it says "not found" With `implicitlyWait(Duration.ofSeconds(10))` on the session, every find follows the W3C **find** algorithm: 1. The remote end starts a timer with the session's implicit wait timeout. 2. It runs the location strategy against the start node. 3. While the result list is empty and the timer has not fired, it runs the strategy again. 4. Only when the timer fires does **Find Element** return `no such element`. So the answer the condition is hoping for — the error — is the answer the remote end is least willing to give. It spends the whole 10 seconds trying not to have to give it. ## The asymmetry between positive and negative conditions | Condition | How it succeeds | Cost per poll with a 10 s implicit wait | Cost per poll at `Duration.ZERO` | |---|---|---|---| | `presenceOfElementLocated` | the find returns an element | one round trip, as soon as the element exists | one round trip | | `visibilityOfElementLocated` | the find returns an element that is displayed | one round trip once it exists | one round trip | | `invisibilityOfElementLocated` | the find throws, or the element is not displayed | the full 10 s on the poll that finally succeeds | one round trip | | `numberOfElementsToBe(By, 0)` | `findElements` returns an empty list | the full 10 s on every poll | one round trip | Positive conditions get *faster* as the application gets faster, because the find returns the instant the element appears. Negative conditions do not: they can only conclude after the remote end has exhausted its retry budget, and that budget is a constant. ## What this costs an ice-rink booking suite Take a cancellation test. It clicks **Cancel** on the Friday 18:30 public-skate slot and then asserts the booked badge is gone: ```java new WebDriverWait(driver, Duration.ofSeconds(15)) .until(ExpectedConditions.invisibilityOfElementLocated( By.cssSelector("[data-slot='friday-1830'] .booked-badge"))); ``` If the badge is removed from the DOM instantly, this assertion still cannot finish in under 10 seconds, because the poll that would prove it needs a full implicit wait to produce the error it is waiting for. Multiply that by every "the slot is released", "the waitlist entry is gone", "the error message cleared" assertion in the suite and a mixed configuration adds minutes of pure waiting to a green run — waiting that no amount of application speed can recover. The same trap sits under `numberOfElementsToBe(By.cssSelector(".slot-row"), 0)` for an empty search result, which is worse still: `findElements` returns an empty list rather than throwing, and the W3C loop keeps retrying while it is empty, so **every** poll pays 10 seconds, not just the last one. ## Making the negative check fast again - Set the implicit wait to `Duration.ZERO`, its documented default, in the driver factory. Nothing else in this picture changes, and every negative check becomes one round trip per poll. - Confirm what the session actually holds with `driver.manage().timeouts().getImplicitWaitTimeout()` rather than trusting the setup code; the value can also arrive through the `timeouts` capability's `implicit` member at new-session time. - Once the implicit wait is zero, let the explicit wait's own polling interval — 500 ms by default — be the only thing between checks, and keep the negative condition as the readable statement of intent. - Where a negative check is genuinely hot, prefer a positive signal the application already gives you: waiting for a "Slot released" confirmation to be present is a positive condition and returns immediately, whereas waiting for the badge to be absent can only ever conclude by exhaustion. The rule that falls out of this is narrow and worth remembering: **a negative Selenium condition and a non-zero implicit wait multiply**, and the multiplication is invisible in a passing run because nothing fails — the suite is simply, permanently slow.

  • Which is more expensive with an implicit wait set, invisibilityOfElementLocated or numberOfElementsToBe with zero?
    The count condition. `invisibilityOfElementLocated` pays the full implicit wait on the poll that finally succeeds, but can return early on earlier polls when the element is present and not displayed. `numberOfElementsToBe(By, 0)` calls `findElements`, whose empty result keeps the remote-end loop running, so every poll pays.
  • How can you avoid a negative condition altogether in a booking flow?
    Wait on a positive signal the application already emits — a "Slot released" confirmation being present, or the slot row's state text changing to "Available". A positive condition returns the instant the element appears, so it costs one round trip instead of an exhausted retry budget.
  • Does shortening the explicit wait's polling interval help a slow negative check?
    Barely. The cost sits inside each poll, in the blocking find, not in the sleep between polls. Dropping the interval from 500 ms to 100 ms saves fractions of a second while each poll still spends the entire implicit wait on the remote end.

It is like proving a rink has no free Friday slot by phoning the desk and waiting through ten seconds of hold music every time, when the only answer you want is silence.

saying these in an interview costs you the question

  • Thinks the condition can detect absence without performing a lookup
  • Blames the application for a check that is slow by configuration
  • Raises the explicit timeout to make the slow negative check pass
  • Believes findElements is unaffected by the implicit wait
  • Assumes a passing but slow assertion means the waits are configured correctly