visibility_of_element_located源碼解析


看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)時,總共進行了以下的步驟:

1. 實例化一個EC.visibility_of_element_located,傳入參數(by, locator),將其賦值給屬性self.locator

2. 通過__call__(),將參數self._driver(實際上這個self.driver就是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;如果已超時,則拋出超時異常

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM