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:
@@ -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)
The bug report is filed here: