17

My two scenarios -

1) First

@driver.manage.timeouts.implicit_wait = 30
@wait = Selenium::WebDriver::Wait.new(:timeout => 45) # Time greater than implicit
@wait.until {@driver.find_element(:tag_name => "body").text.include?("hey")}

Which gives the driver 45 seconds to search for the text(which is expected)

2) Second

@driver.manage.timeouts.implicit_wait = 30
@wait = Selenium::WebDriver::Wait.new(:timeout => 5) # Time less than implicit
@wait.until {@driver.find_element(:tag_name => "body").text.include?("hey")}

This now gives the driver 30 seconds to search for the text(not expected)

Is there a way to make selenium wait only for the explicit wait time and not for the greater of the two?

Note - Not declaring the implicit wait time is not an option, cause I cannot afford to let selenium hang each time the driver is unable to find something.

Using Selenium version 30, windows, ff

Louis
  • 146,715
  • 28
  • 274
  • 320
Amey
  • 8,470
  • 9
  • 44
  • 63
  • `The default setting is 0` according to the implicit wait docs, so what exactly is the problem here? – phoet Mar 01 '13 at 21:41
  • Why not just set the implicit wait to 5 also? – BlackHatSamurai Mar 01 '13 at 23:51
  • Implicit wait helps me keep a default wait on each and every element, so don't want to keep it as low as 5 seconds. I want to use a shorter time period wait (say "wait_to_fail") to check for elements *not* present. – Amey Mar 03 '13 at 11:37
  • 2
    The default is not 0. The default is 30 and you can see that on line #60 in the com.thoughtworks.selenium.webdriven.WebDriverCommandProcessor.java class. Where do lemmings get '0' from? – djangofan Jan 08 '15 at 02:23
  • possible duplicate of [selenium web driver - explicit wait vs implicit wait](http://stackoverflow.com/questions/10404160/selenium-web-driver-explicit-wait-vs-implicit-wait) – Lesmana Jan 21 '15 at 12:42
  • While coding in Java, if we give an WebElement(driver.findElement(By.xpath("\\xpath_string"));) as the argument to the methods of ExpectedConditions class then both ImplicitWait time and ExplicitWait times are cosidered. Otherwise, if a locator(By.xpath("")) is provided as the argument then only the Explicit wait time is considered. – Bharath Nadukatla Jul 16 '19 at 22:38

2 Answers2

61

Don't mix implicit and explicit waits. Part of the problem is that implicit waits are often (but may not always be!) implemented on the "remote" side of the WebDriver system. That means they're "baked in" to IEDriverServer.exe, chromedriver.exe, the WebDriver Firefox extension that gets installed into the anonymous Firefox profile, and the Java remote WebDriver server (selenium-server-standalone.jar). Explicit waits are implemented exclusively in the "local" language bindings. Things get much more complicated when using RemoteWebDriver, because you could be using both the local and remote sides of the system multiple times.

This is how that would work: local code -> Java remote server -> local Java language bindings on the remote server -> "remote" component like the Firefox extension, chromedriver.exe or IEDriverServer.exe. It's even more complex in the grid case, since there could be other hops in between.

Thus, when you try to mix implicit and explicit waits, you've strayed into "undefined behavior". You might be able to figure out what the rules of that behavior are, but they'll be subject to change as the implementation details of the drivers change. So don't do it.

You shouldn't be experiencing "hangs" when an element can't be found if you're not using implicit waits. The driver should throw a NoSuchElement exception immediately.

JimEvans
  • 27,201
  • 7
  • 83
  • 108
  • Thanks for your response. So the problem is indeed with the fact that my script hangs as compared to failing immediately. Would this be a selenium webdriver ruby issue? – Amey Mar 03 '13 at 11:39
  • Do you mean to say that when implicit waits are not set (or set to zero), your WebDriver code hangs indefinitely? There was an issue with exactly those symptoms using Firefox, but it was fixed in 2.30.0. If you're setting implicit waits to anything other than zero, then yes, of course WebDriver will "hang" until the timeout if the element does not exist. What happens when you use other browsers? What about updating to 2.31? – JimEvans Mar 03 '13 at 12:56
  • I posted a [related question](http://stackoverflow.com/questions/20268396/mixing-implicit-and-explicit-waits) (I'm confused about this) – KnewB Nov 28 '13 at 14:18
  • @JimEvans, wonderful explanation. Could you help me find resources which talks more detail regarding Implicit & explicit waits & their implementation? I could find only basic documentation on this topic until now. – praneel Feb 06 '14 at 08:40
  • Great info, I'm submitting an update to the docs since it's not clear: https://code.google.com/p/selenium/issues/detail?id=7639&sort=-id&colspec=ID%20Stars%20Type%20Status%20Priority%20Milestone%20Owner%20Summary – agmin Jul 22 '14 at 20:02
  • But... Explicit waits can make use of ExpectedConditions, which in turn contain an implicit wait (FindElement). Aren't you mixing them then? – FDM Apr 27 '16 at 06:05
  • @FDM The only time you'd be using implicit waits, is if you specifically set the implicit wait timeout. By itself, `FindElement` doesn't use implicit waits unless the timeout is set. – JimEvans Apr 28 '16 at 12:41
  • @JimEvans - could you please review my answer for a similar question? thanks. https://stackoverflow.com/a/60746530/6648326 – MasterJoe Mar 18 '20 at 19:48
  • is this (Don't mix implicit and explicit waits) still true now ? (answer was almost 10 years ago). Thanks – vicovicovico Aug 07 '23 at 12:12
-2

The best practice is to set implicitlyWait() at the beginning of each test, and use WebDriverWait() for waiting an element, or AJAX element to load.

However, implicitlyWait() and WebDriverWait() do not work well together in the same test. You would have to nullify implicitlyWait() before calling WebDriverWait because implicitlyWait() also sets the "driver.findElement()" wait time.

Whenever you are using WebDriverWait() with implicitlyWait() already set some initial value, follow the steps -

  1. nullifying implicitlyWait()
  2. executing WebDriverWait (), and return element
  3. reset implicitlyWait() again

Example Java code -

driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //nullify implicitlyWait() 

WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); 
element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));

driver.manage().timeouts().implicitlyWait(DEFAULT_WAIT_4_PAGE, TimeUnit.SECONDS);