Selenium自動化測試----智能等待


 implicitly_wait():是 webdirver 提供的一個超時等待。隱的等待一個元素被發現,或一個命令完成。

如果超出了設置時間的則拋出異常。

需要特別說明的是:隱性等待對整個driver的周期都起作用,所以只要設置一次即可,我曾看到有人把隱性等待當成了sleep在用,走哪兒都來一下…

WebDriverWait()
詳細格式如下:
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver -
WebDriver 的驅動程序(Ie, Firefox, Chrome 或遠程)
timeout - 最長超時時間,默認以秒為單位
poll_frequency -
休眠時間的間隔(步長)時間,默認為 0.5 秒
ignored_exceptions -
超時后的異常信息,默認情況下拋 NoSuchElementException 異常。

實例:

from selenium.webdriver.support.ui import WebDriverWait
....
element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id(“someId”))
is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).
until_not(lambda x: x.find_element_by_id(“someId”).is_displayed())

 

WebDriverWai()一般由 unit()或 until_not()方法配合使用,下面是 unit()和 until_not()方法的說明。
until(method, message=’ ’)
調用該方法提供的驅動程序作為一個參數,直到返回值不為 False。
until_not(method, message=’ ’)
調用該方法提供的驅動程序作為一個參數,直到返回值為 False。

第三種辦法就是顯性等待,WebDriverWait,配合該類的until()和until_not()方法,就能夠根據判斷條件而進行靈活地等待了。它主要的意思就是:程序每隔xx秒看一眼,如果條件成立了,則執行下一步,否則繼續等待,直到超過設置的最長時間,然后拋出TimeoutException。

先看個代碼實例:

# -*- coding: utf-8 -*-
fromselenium importwebdriver
fromselenium.webdriver.support.wait importWebDriverWait
fromselenium.webdriver.support importexpected_conditions as EC
fromselenium.webdriver.common.by importBy
driver=webdriver.Firefox()
driver.implicitly_wait(10)# 隱性等待和顯性等待可以同時用,但要注意:等待的最長時間取兩者之中的大者
driver.get('https://huilansame.github.io')
locator=(By.LINK_TEXT, 'CSDN')
try:
WebDriverWait(driver,20,0.5).until(EC.presence_of_element_located(locator))
printdriver.find_element_by_link_text('CSDN').get_attribute('href')
finally:
driver.close()

上例中,我們設置了隱性等待和顯性等待,在其他操作中,隱性等待起決定性作用,在WebDriverWait..中顯性等待起主要作用,但要注意的是:最長的等待時間取決於兩者之間的大者,此例中為20,如果隱性等待時間 > 顯性等待時間,則該句代碼的最長等待時間等於隱性等待時間。  

看了以上內容基本上很清楚了,調用方法如下:

WebDriverWait(driver, 超時時長, 調用頻率, 忽略異常).until(可執行方法, 超時時返回的信息)

這里需要特別注意的是until或until_not中的可執行方法method參數,很多人傳入了WebElement

對象,如下:

WebDriverWait(driver, 10).until(driver.find_element_by_id('kw')) # 錯誤

 

這是錯誤的用法,這里的參數一定要是可以調用的,即這個對象一定有 __call__() 方法,否則會拋出異常:

TypeError: 'xxx' object is not callable

 

在這里,你可以用selenium提供的 expected_conditions 模塊中的各種條件,也可以用WebElement的 is_displayed() 、is_enabled()、is_selected() 方法,或者用自己封裝的方法都可以,那么接下來我們看一下selenium提供的條件有哪些:

expected_conditions

expected_conditions是selenium的一個模塊,其中包含一系列可用於判斷的條件:

  • title_is : 判斷當前頁面的title是否精確等於預期

  • title_contains : 判斷當前頁面的title是否包含預期字符串

  • presence_of_element_located : 判斷某個元素是否被加到了dom樹里,並不代表該元素一定可見

  • visibility_of_element_located : 判斷某個元素是否可見. 可見代表元素非隱藏,並且元素的寬和高都不等於0

  • visibility_of : 跟上面的方法做一樣的事情,只是上面的方法要傳入locator,這個方法直接傳定位到的element就好了

  • presence_of_all_elements_located : 判斷是否至少有1個元素存在於dom樹中。舉個例子,如果頁面上有n個元素的class都是'column-md-3',那么只要有1個元素存在,這個方法就返回True

  • text_to_be_present_in_element : 判斷某個元素中的text是否 包含 了預期的字符串

  • text_to_be_present_in_element_value : 判斷某個元素中的value屬性是否 包含 了預期的字符串

  • frame_to_be_available_and_switch_to_it : 判斷該frame是否可以switch進去,如果可以的話,返回True並且switch進去,否則返回False

  • invisibility_of_element_located : 判斷某個元素中是否不存在於dom樹或不可見

  • element_to_be_clickable : 判斷某個元素中是否可見並且是enable的,這樣的話才叫clickable

  • staleness_of : 等某個元素從dom樹中移除,注意,這個方法也是返回True或False

  • element_to_be_selected : 判斷某個元素是否被選中了,一般用在下拉列表

  • element_selection_state_to_be : 判斷某個元素的選中狀態是否符合預期

  • element_located_selection_state_to_be : 跟上面的方法作用一樣,只是上面的方法傳入定位到的element,而這個方法傳入locator

  • alert_is_present : 判斷頁面上是否存在alert

上面是所有17個condition,與until、until_not組合能夠實現很多判斷,如果能自己靈活封裝,將會大大提高腳本的穩定性。

 

分析

以title_is為例

class title_is(object): """An expectation for checking the title of a page. title is the expected title, which must be an exact match returns True if the title matches, false otherwise.""" def __init__(self, title): self.title = title def __call__(self, driver): return self.title == driver.title

可以看到 title_is 實際上是1個class,其 __call__ 方法被定義成是返回1個bool值。因此,一般的用法就是

# 實例化 the_instance = title_is('expected') # 直接在實例上調用__call__ the_instance(dr) #return True or False


免責聲明!

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



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