expected_conditions 模块的源码分析

from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoSuchFrameException
from selenium.common.exceptions import StateElementReferenceException
from selenium.common.exceptions import WebDriverException
from selenium.common.exceptions import NoAlertPresentException

导入异常处理模块。

title_is
class title_is(object):
    def __init__(self, title)
        self.title = title

    def __call__(self, driver)
        return self.title == driver.title

说明:用于检查页面的标题,title是期望的标题,必须是完全匹配,如果标题匹配则返回True,否则返回false。

用法:比如判断标题是否为"hi | word", title_is("hi | word")

title_contains
class title_contains(object):
    def __init__(self, title):
        self.title = title

    def __call__(self, driver):
        return self.title in driver.title

说明:检查页面的标题是否包含指定的字符,如果包含返回True,否则返回false。

用法:判断标题是否包含"hi", title_is("hi")

presence_of_element_located
class presence_of_element_located(object):
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        return _find_element(driver, self.locator)

说明:检查页面的DOM上是否存在指定元素。该元素并不需要是可见的。 locator - 用于找到元素的元组,包括找到元素的方式和值. 返回找到元素。

用法:例如判断当前页面是否存在id为“kw"的元素,presence_of_located((By.ID, "kw"))

By中包含ID、XPATH、LINK_TEXT、 PARTIAL_LINK_TEXT、NAME、TAG_NAME、CLASS_NAME、CSS_SELECTOR

_find_elemnt()用于查找元素,简单看一下_find_elment()方法的实现:

def _find_element(driver, by)
    try:
        return driver.find_element(*by)
    except NoSuchElementException as e:
        raise e
    except WebDriverException as e:
        raise e
visibility_of_element_located
class visibility_of_element_located(object):
    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

说明:期望检查元素是否出现在页面的DOM上并可见。 可见性意味着元素不仅显示,而且具有大于0的高度和宽度。 locator - 用于找到元素的元组,包括找到元素的方式和值. 返回找到的元素

方法:例如判断当前页面是否存在name为“wd"的元素,并且该元素可视,visibility_of_element_located((By.NAME, "wd"))

调用_element_if_visible()方法检查元素是否存在并可视

def _element_if_visible(element, visibility=True):
    retrun element if element.is_displayed() == visibility else False

_element_if_visible通过调用element.is_displayed()判断元素是否可视。element.is_displayed不再描述,以后的文章会再着重说明。

visibility_of
class visibility_of(object):
    def __init__(self, element):
        self.element = element

    def __call__(self, ignored):
        return _element_if_visible(self,element)

说明:该类和visibility_of_element_located类似,不同的地方是该类直接传入要判断的元素。

如果存在返回True,如果不存在返回False

presence_of_all_elements_located(object):
def __init__(sel, locator):
    self.locator = locator

def __call__(self, driver):
    retrun _find_elments(driver, self.locator)

说明:该类和presence_of_element_located类似。该类检查页面是否存在至少一个符合要求的元素,返回符合要求的列表。

visibility_of_any_elements_located(object):
class visibility_of_any_elements_located(object):
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        retrun [element for element in _find_elements(driver, self.locator) if _element_if_visible(element)]

说明:期望页面中至少出现一个符合条件的元素。符合定位方式并且可视。 方法:方法同 visibility_of_element_located 简单看一下_find_elements()和_find_element()类似

def _find_elements(driver, by):
    try:
        return driver.find_elements(*by)
    except WebDriverException as e:
        raise e
text_to_be_present_in_element
class text_to_be_present_in_element(object):
    def __init__(self, locator, text_):
        self.locator = locator
        self.text = text_

    def __call__(self, driver):
        try:
            element_text = _find_element(driver, self.locator).text
            return self.text in element_text
        except StaleElementReferenceException:
            return False

说明: 期望检查给定的文本是否存在于指定的element.locator的text中。存在返回True,不存在返回false. 用法: 例如检查名称为”tj_trhao123"的元素文本中是否包含"hao123",((By.NAME, "tj_trhao123"), "hao123"))

text_to_be_present_in_element_value
class text_to_be_present_in_element_value(object):
    def __init__(self, locator, text_):
        self.locator = locator
        self.text = text_

    def __call__(self, driver):
        try:
            element_text = _find_element(driver,
                                         self.locator).get_attribute("value")
            if element_text:
                return self.text in element_text
            else:
                return False
        except StaleElementReferenceException:
            return False

说明: 期望检查给定文本是否存在于元素的定位器定位到元素的文本中。存在返回True,不存在返回false。 用法: 判断"百度一下“,是否存在于id为su的元素的”value"属性值中,text_to_be_present_in_element_value((By.ID, "su"), "百度一下"))

从代码中可以看到同样是通过_find_element找到元素,并且通过get_attribute获取元素值。

frame_to_be_available_and_switch_to_it
class frame_to_be_available_and_switch_to_it(object):
    def __init__(self, locator):
        self.frame_locator = locator

    def __call__(self, driver):
        try:
            if isinstance(self.frame_locator, tuple):
                driver.switch_to.frame(_find_element(driver,
                                                     self.frame_locator))
            else:
                driver.switch_to.frame(self.frame_locator)
            return True
        except NoSuchFrameException:
            return False

说明:检查给定的frame是否可切换。 如果帧可用,则将给定的webdriver切换到指定的frame.如果切换成功,返回True,否则返回false。 用法:参数locator可以为定位frame的元组,也可以是frame元素。

isinstance首先判断给点的locator是否为元组(包含定位方式和对应值),如果是,先通过_find_element获取元素,然后再通过switch_to.frame切换。

简单看一下switch_to.frame的实现代码片段

@property
def switch_to(self):
    retrun self._switch_to

self._switch_to = SwitchTo(self)

class SwitchTo:

    def frame(self, frame_reference):
        self._driver.execute(Command.SWITCH_TO_FRAME, {'id': frame_reference})
invisibility_of_element_located
class invisibility_of_element_located(object):
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        try:
            return _element_if_visible(_find_element(driver, self.locator), False)
        except (NoSuchElementException, StaleElementReferenceException):
            return True

说明:检查一个元素是不可见的或不存在于DOM中.

用法:传入定位元素的locator

try表示元素存在,但调用_element_if_visible判断元素是否可视,传入判断的值为False,也就是如果可见则返回False.

except中NoSuchElementException表示指定元素没有在DOM中。StaleElementReferenceException表示是元素状态是不可见的。

element_to_be_clickable
class element_to_be_clickable(object):
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        element = visibility_of_element_located(self.locator)(driver)
        if element and element.is_enabled():
            return element
        else:
            return False

说明:检查元素是可用的,意思就是可以点击或操作的。

用法:传入locator定位元素,如果可用返回元素,如果不可用返回false.

简单看一下is_enabled,

def is_enabled(self):
    return self.execute(Command.IS_ELEMENT_ENABLED)['value']
staleness_of
class staleness_of(object):
    def __init__(self, element):
        self.element = element

    def __call__(self, ignored):
        try:
            self.element.is_enabled()
            return False
        except StaleElementReferenceException:
            return True

说明:等待元素不再附着在DOM中,传入的element是要等待的元素。如果元素仍然可用,则返回false, 如果不可用则返回True.

element_to_be_selected
class element_to_be_selected(object):
    def __init__(self, element):
        self.element = element

    def __call__(self, ignored):
        return self.element.is_selected()

说明:检查元素的选择框是否选中。

用法:传入要验证的元素

is_selected 用于检查是否选中了复选框或单选按钮

def is_selected(self):
    return self._execute(Command.IS_ELEMENT_SELECTED)['value']
element_located_to_be_selected
class element_located_to_be_selected(object):
    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        return _find_element(driver, self.locator).is_selected()

说明:和element_to_be_selected类似,传入的参数不同,这个是传入locator,先定位元素再判断。

element_selection_state_to_be
class element_selection_state_to_be(object):
    def __init__(self, element, is_selected):
        self.element = element
        self.is_selected = is_selected

    def __call__(self, ignored):
        return self.element.is_selected() == self.is_selected

说明: 给定元素和是否选中的状态(布尔值如True或False) 用法: 传入判定的元素和状态,如果和输入状态一致返回True,否则返回false。

element_located_selection_state_to_be
class element_located_selection_state_to_be(object):
    def __init__(self, locator, is_selected):
        self.locator = locator
        self.is_selected = is_selected

    def __call__(self, driver):
        try:
            element  = _find_element(driver, self.locator(
            return element.is_selected() == self.is_selected
        except StaleElementReferenceException:
            return false

说明:和element_selection_state_to_be类似,不同的是该类需要传入定位方法和状态。 返回值,如果和输入状态一致返回True,如果不一致返回false。另外,如果元素没找到,返回false。

alert_is_present
class alert_is_present(object):
    def __init__(self):
        pass

    def __call__(self, driver):
        try:
            alert = driver.switch_to.alert
            alert.text
            return alert
        except NoAlertPresentException:
            return False

说明:判断是否有弹窗(一般为警告信息)。有返回alert,没有返回False.

by 李鹏