細說selenium的等待條件

selenium的顯示等待

在進行UI自動化測試的時候,咱們爲了保持用例的穩定性,每每要設置顯示等待,顯示等待就是說明確的要等到某個元素的出現或者元素的某些條件出現,好比可點擊、可見等條件,若是在規定的時間以內都沒有找到,那麼就會拋出Exception.python

image-20200801172302493

上面是我用selenium寫的一個測試用例,展現了selenium中顯示等待的使用方式,其中會使用到expected_conditions模塊和WebDriverWait類,注意這裏expected_conditions是一個py文件的文件名,也就是一個模塊名,這個模塊下面有不少的條件類,而咱們用例中使用的title_is就是一個條件類。web

WebDriverWait是一個類,這個類的做用就是根據必定的條件,不斷的檢查這個條件是否被知足了。WebDriverWait類只有兩個方法,一個是until直到知足某個條件,另外一個是until_not直到不知足某個條件。chrome

class WebDriverWait(object):
    def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):

WebDriverWait有四個參數分別是, driver驅動, timeout超時時間, poll_frequency=POLL_FREQUENCY輪訓時間,也就是去判斷條件是否知足的時間間隔,默認是0.5秒, ignored_exceptions=None在等待的過程當中須要忽略的異常,是一個可迭代的異常類集合,好比咱們能夠設置一個list,裏面是[NoSuchElementException,NoSuchAttributeException,InvalidElementStateException....],默認狀況下,是一個元組,只包含一個NoSuchElementException,由於只有元素出現,才能去判斷條件是否知足,在不斷輪訓的過程當中,確定會發生NoSuchElementException,這個時候必須忽略掉這個異常,否則程序就會中斷。windows

其中drivertimeout是畢傳的位置參數,另外兩個是選擇傳遞的關鍵字參數,若是不傳都有指定的默認值。dom

下面就進入咱們今天的主題,selenium中的等待條件的討論函數

等待條件

條件類的實現原理

selenium.webdriver.support.expected_conditions這個模塊裏,存放着全部的等待條件,每一個條件類的結構都是同樣的一個__init__構造方法和一個__call__方法。測試

在python中,若是想把類型的對象當作函數來使用,那麼就能夠給這個類實現__call__方法,以下:url

class TestCase:
    def __init__(self):
        self.driver = webdriver.Chrome(executable_path="./driver/chromedriver")
        self.driver.get('http://www.baidu.com')
        # sleep(2)

    def __call__(self):
        print(self.driver.title)

if __name__ == '__main__':
    case = TestCase()
    case()

case()對象的調用,就會執行__call__方法裏面的邏輯打印當前頁面的標題,咱們取一個selenium的實現類:spa

class presence_of_element_located(object):

    def __init__(self, locator):
        self.locator = locator

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

這個條件類的意思是判斷一個元素是否已經渲染到頁面當中,在使用這個條件的時候須要先實例化,傳入元素的定位,而後要進行判斷的時候須要對實例對象進行調用並傳入driver,對實例對象進行調用的時候就會執行__call__方法裏的條件判斷邏輯。code

WebDriverWait是如何進行條件判斷的

再回到文章開頭看一下咱們使用顯示等待的代碼:

wait = WebDriverWait(self.driver, 2)
wait.until(EC.title_is('百度一下,你就知道'))

先是實例化一個WebDriverWait對象,而後再調用until方法而且傳遞一個條件的實例對象,until方法裏就會不斷的去輪訓條件是否知足。

def until(self, method, message=''):
    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)

method這個參數就是咱們傳遞進來的條件的實例對象,value = method(self._driver)這裏就是進行對象的調用,也就是執行了__call__方法裏的邏輯。

selenium裏都有哪些條件

  • title_is 判斷title是否出現
  • title_contains 判斷title頁面標題是否包含某些字符
  • presence_of_element_located 判斷某個元素是否被加載到了dom樹裏,可是並不表明這個元素可見
  • url_contains 判斷當前url是否包含某個url
  • url_matches 判斷當前url是否符合某種格式
  • url_to_be 判斷當前url是否出現
  • url_changes 判斷當前url是否已經發生了變化
  • visibility_of_element_located 判斷某個元素是否被添加到了dom樹裏,且寬高都大於0
  • visibility_of 判斷看某個元素是否可見
  • presence_of_all_elements_located 判斷至少有一個元素存在於dom樹中,返回全部定位到的元素
  • visibility_of_any_elements_located 判斷至少有一個元素在頁面中可見
  • visibility_of_all_elements_located 判斷是否全部元素都在頁面中可見
  • text_to_be_present_in_element 判斷指定的元素中是否包含了預期的字符串
  • text_to_be_present_in_element_value 判斷指定的元素屬性值中是否包含了預期的字符串
  • frame_to_be_available_and_switch_to_it 判斷iframe是否能夠switch進去
  • invisibility_of_element_located 判斷某個元素是否在dom中不可見
  • element_to_be_clickable 判斷某個元素是否可見而且是enable的,也就是說是是否能夠點擊
  • staleness_of 等待某個元素從dom中刪除
  • element_to_be_selected 判斷某個元素是否被選中了,通常用於下拉列表中
  • element_located_to_be_selected 與上面的意思同樣,只不過上面實例化的時候傳入的是元素對象,這個傳入的是定位
  • element_selection_state_to_be 判斷某個元素的選中狀態是否符合預期
  • element_located_selection_state_to_be 與上面同樣,只不過傳值不一樣而已
  • number_of_windows_to_be 判斷當前窗口數是否等於預期
  • new_window_is_opened 判斷是否有窗口增長
  • alert_is_present 判斷頁面是否有彈窗

以上就是selenium支持的全部條件。

而後就是自定義了

說了那麼多條件,其實咱們也能夠本身實現一個條件類,

class page_is_load:
    
    def __init__(self, expected_title, expected_url):
        self.expected_title = expected_title
        self.expected_url = expected_url
    
    def __call__(self, driver):
        is_title_correct = driver.title == self.expected_title
        is_url_correct = driver.current_url == self.expected_url
        return is_title_correct and is_url_correct

上面是本身實現的一個條件類,根據頁面的url和標題來判斷頁面是否被正確加載,

class TestCase:
    def __init__(self):
        self.driver = webdriver.Chrome(executable_path="./driver/chromedriver")
        self.driver.get('http://www.baidu.com/')
        # sleep(2)

    def __call__(self):
        print(self.driver.title)

    def test_wait(self):
        wait = WebDriverWait(self.driver, 2)
        wait.until(page_is_load("百度一下,你就知道", "http://www.baidu.com/"))

<img src="https://zyjblog.oss-cn-beijing.aliyuncs.com/1593947944.jpg" style="zoom: 25%;" />

歡迎你們去 個人博客 瞅瞅,裏面有更多關於測試實戰的內容哦!!
相關文章
相關標籤/搜索