Friday, November 25, 2011

WebDriverWait and SauceLabs

If you've used the WebDriverWait class with SauceLabs, you may have noticed that it actually will run beyond the designated timeout period. I first noticed this issue when seeing that this function took 40 minutes to complete with a 20 second implicit wait time and a 60 second timeout w/ .5 poll frequency! (60 / .5 = 120 loops * 20 seconds/implicit wait = 2400 seconds total)

The problem appears to be that WebDriverWait attempts to run self._timeout / self._poll times before returning a Timeout Exception:

for _ in xrange(max(1, int(self._timeout/self._poll))):

Since this code could wait until an ElementNotFound exception is found (and if the implicit wait time is increased), then the total time this routine takes is a function of the total # of loops * poll frequency * the implicit wait time.

The correct patch appears to be recording the start time and looping until the maximum timeout period has been exceeded:

--- a/selenium/webdriver/support/
+++ b/selenium/webdriver/support/
@@ -24,7 +24,7 @@ class WebDriverWait(object):

def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY):
"""Constructor, takes a WebDriver instance and timeout in seconds.
- driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote)
- timeout - Number of seconds before timing out
@@ -43,7 +43,8 @@ class WebDriverWait(object):
def until(self, method):
"""Calls the method provided with the driver as an argument until the \
return value is not Falsy."""
- for _ in xrange(max(1, int(self._timeout/self._poll))):
+ end_time = time.time() + self._timeout
+ while(time.time() < end_time):
value = method(self._driver)
if value:

The bug report is filed here:

No comments:

Post a Comment