看WebDriverWait(self.driver, wait_time).until(EC.visibility_of_element_located((by, locator)))
源码的时候,不太明白visibility_of_element_located((by, locator))
内为什么是两层括号,因为源码是这样写的:
class visibility_of_element_located(object):
""" An expectation for checking that an element is present on the DOM of a
page and visible. Visibility means that the element is not only displayed
but also has a height and width that is greater than 0.
locator - used to find the element
returns the WebElement once it is located and visible
"""
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
try:
return _element_if_visible(_find_element(driver, self.locator))
except StaleElementReferenceException:
return False
__call__()
的作用是,让实例对象也像函数一样作为可调用对象来使用,正常来讲visibility_of_element_located(locator)(driver)
才对,直到看了下until
的源码,才发现有这一层:value = method(self._driver)
,其中这个method
就是EC.visibility_of_element_located((by, locator))
的实例对象,method(self._driver)就是EC.visibility_of_element_located((by, locator))(self._driver)
,也就是把实例对象作为参数一样传了个参数self._driver
。其实前者((by, locator))
是__init__()
做初始化,只不过参数是个元组(by, locator)
,这个元组作为实例对象的属性self.locator
,而后者(self._driver)
就是__call__()
的作用
def until(self, method, message=''):
"""Calls the method provided with the driver as an argument until the \
return value is not False."""
screen = None
stacktrace = None
end_time = time.time() + self._timeout
while True:
try:
value = method(self._driver)
if value:
return value
except self._ignored_exceptions as exc:
screen = getattr(exc, 'screen', None)
stacktrace = getattr(exc, 'stacktrace', None)
time.sleep(self._poll)
if time.time() > end_time:
break
raise TimeoutException(message, screen, stacktrace)
当使用EC.visibility_of_element_located((by, locator))(self._driver)
时,总共进行了以下的步骤:
-
实例化一个
EC.visibility_of_element_located
,传入参数(by, locator)
,将其赋值给属性self.locator
-
通过
__call__()
,将参数self._driver
(实际上这个self.drive
r就是WebDriverWait
中的self.driver
传进来的)和self.locator
传给内层方法_find_element()
2.1 这个find_element(self._driver, self.locator)
对应着源码中的driver
和by
,再通过*by
解包(by, locator)
,使其这样调用driver.find_element(by, locator)
def _find_element(driver, by):
"""Looks up an element. Logs and re-raises ``WebDriverException``
if thrown."""
try:
return driver.find_element(*by)
except NoSuchElementException as e:
raise e
except WebDriverException as e:
raise e
2.2 然后driver.find_element(by, locator)
找到元素对象并返回给_find_element()
方法
2.3 _find_element()
方法拿到元素对象,此时作为参数传递给_element_if_visisble()
方法,element_if_visisble()
方法通过判断元素是否可见,返回True
或False
until
作为一个判断条件,来决定是否继续寻找可见元素,主要有这几种情况:如果EC.visibility_of_element_located((by, locator))(self._driver)
返回为True
,则返回对应的True
;如果已超时,则抛出超时异常
欢迎来到testingpai.com!
注册 关于