skip to content

Why can a Selenium WebDriverWait with a 10-second timeout take noticeably longer than 10 seconds to fail?

level: middleimportance: should knowfreq 45%

answer

  1. Roughly two attempts every second
  2. The clock is read between attempts
  3. A command in flight cannot be cancelled
  4. Add the cost of the last attempt
  5. A floor on failing, not a ceiling

basics

~20 s

The wait checks the clock only between attempts, never during one. It evaluates the condition first, so an attempt that starts just before the deadline runs to completion, and total elapsed time is the timeout plus that final attempt.

solid answer

~40 s

A `WebDriverWait` polls every 500 milliseconds by default, and each cycle is an attempt followed by a clock check followed by a sleep — so the deadline is only ever observed *between* attempts. Once an attempt starts, the wait is committed to letting it finish, because a WebDriver command in flight cannot be cancelled. Elapsed time for a failing wait is therefore roughly the timeout **plus the duration of the final attempt**, and anything that makes one evaluation expensive shows up as overrun: a long XPath over a large document, a condition issuing several commands, a busy browser, or network latency to a remote driver. Treat the configured timeout as the earliest moment the wait may give up, not as a ceiling on how long `until()` blocks.

go deeper

for a junior

Be ready to state that a WebDriverWait polls about twice a second by default and that its timeout is a deadline for giving up rather than a promise about exactly how long the call blocks.

for a middle

Explain the cycle order — evaluate, then check the clock, then sleep — and derive from it why elapsed time equals the timeout plus the cost of the final attempt.

for a senior

Show that you would measure the overrun rather than guess at it, and that you can point at an expensive condition, a large document or a remote driver as the concrete source of the extra seconds.

for a principal

Own the framing that a wait's real cost is the price of one evaluation multiplied by the attempts a deadline permits, so condition expense deserves as much design attention as the deadline itself.

## The number people ask for `WebDriverWait` polls every **500 milliseconds** by default — the constant it inherits as its sleep between attempts. A ten-second wait therefore makes roughly twenty attempts rather than one long blocking call, and each attempt is a real command sent from the test process to the driver. - The interval is a **sleep between attempts**, not a scheduled cadence. Nothing tries to fire an attempt exactly every 500 ms. - The interval is configurable, but the number above is what you get from `new WebDriverWait(driver, Duration.ofSeconds(10))` with nothing else specified. - The timeout and the interval are independent: shortening one does not adjust the other. ## Why the arithmetic does not come out even The loop does three things per cycle, in this order: 1. Apply the condition, which blocks for as long as the underlying commands take. 2. Compare the clock to the deadline, and give up if it has passed. 3. Sleep for the polling interval. The clock is only ever consulted at step 2 — **between** attempts, never during one. So the moment an attempt begins, the wait is committed to letting it finish, however long that takes. | Quantity | What people assume | What actually happens | |---|---|---| | the polling interval | a fixed 500 ms cadence | a 500 ms sleep *added to* each attempt's own cost | | the number of attempts | timeout ÷ interval, so 20 in 10 seconds | fewer, because every attempt spends time of its own | | the timeout | an upper bound on how long `until()` blocks | the earliest moment at which the wait is allowed to give up | ## Where the extra seconds come from Elapsed wall-clock time for a wait that fails is approximately **the timeout plus the duration of the final attempt**. Anything that makes a single evaluation expensive shows up directly as overrun: - A condition whose locator is a long XPath evaluated over a large document — a bakery pre-order page rendering a hundred slot rows, say — costs real milliseconds on every single poll. - A condition that performs several commands (locate, then read a property, then compare) pays for all of them, twenty times over. - A command issued while the browser is busy laying out or scripting can take far longer than the same command on a settled page. - A remote driver adds network latency to each attempt, so the same wait overruns further against a distant endpoint than against a local one. None of this is a bug. A deadline that could interrupt an in-flight command would mean abandoning a request whose response is already on the wire, and the driver's command interface has no notion of cancellation. ## Measuring it rather than guessing ```java WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10)); long start = System.nanoTime(); try { wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("preorder-confirmation"))); } catch (TimeoutException e) { long elapsedMs = (System.nanoTime() - start) / 1_000_000; System.out.println("gave up after " + elapsedMs + " ms"); } ``` If that prints something close to 10,000 ms, the condition is cheap and the page really was not ready. If it prints 14,000 ms, roughly four seconds went into evaluating the condition, and the condition — not the deadline — is what deserves attention. ## What this changes in practice - Treat a configured timeout as a **floor** on failure time, not a ceiling on blocking time, when reasoning about how long a run can take. - A wait that succeeds is usually far cheaper than its timeout suggests, because success exits on the first satisfying attempt. - The reverse is also true and is the trap: a suite full of waits that mostly *fail* pays the full deadline plus overrun for every one of them. - Two waits with identical timeouts can differ in real cost by seconds purely because one condition is more expensive to evaluate than the other. The mechanism is worth internalising because it reframes the question. The interesting property of a wait is not only the deadline written in the constructor; it is how much a single evaluation costs, multiplied by how many evaluations the deadline allows.

  • How many times does a 10-second WebDriverWait actually evaluate its condition?
    Fewer than twenty. The 500 ms interval is a sleep added to each attempt's own cost, so a cycle lasts 500 ms plus however long the evaluation takes. With cheap conditions the count approaches twenty; with an expensive condition it can fall to a handful, because each attempt consumes a large slice of the budget itself.
  • Why does a successful wait usually cost far less than its timeout?
    Because the loop applies the condition before it ever checks the clock and returns on the first usable result. A page already in the required state satisfies the condition on attempt one, so the wait costs a single round trip. The timeout only becomes relevant when the condition keeps failing.
  • Would a shorter polling interval make a failing wait finish sooner?
    Not materially. The deadline still governs when the wait may give up, and the overrun comes from the final attempt's own duration, which a shorter sleep does not change. A shorter interval mainly increases the number of commands sent, and therefore the load on the driver and browser, during the same window.

saying these in an interview costs you the question

  • Claims the timeout is a hard ceiling on how long the call blocks
  • Computes the attempt count as timeout divided by interval exactly
  • Thinks the interval is a fixed cadence independent of attempt cost
  • Says the wait checks its clock during an in-flight command
  • Guesses the default polling interval is one second