作者:Gakki
前言
- 在瀏覽器加載一個頁面時,頁面內(nèi)得元素可能是在不同的時間載入的锈拨,這會加大定位元素的困難程度砌庄,因為元素不在DOM里,會拋出
ElementNotVisibleException
異常奕枢,使用waits娄昆,我們就可以解決這個問題了。 - 超時的情況大致區(qū)分兩類:
- 頁面加載出現(xiàn)的超時
- 獲取頁面元素的超時
等待方式
- Thread.sleep()方法
- 隱式等待
- 它允許您將
WebDriver
暫停特定的時間缝彬,直到WebDriver
在網(wǎng)頁上找到所需的元素為止萌焰。
- 它允許您將
- 顯示等待
- 但是如果我們不知道在加載時該元素是可見/可點擊的,該怎么辦谷浅?正如它出現(xiàn)的時候一樣扒俯,元素是動態(tài)的,并且可能會不時地變化一疯。在這種情況下陵珍,顯式等待將幫助解決此問題。讓我們看一下顯示等待的細節(jié)违施。
-
顯式等待是動態(tài)
Selenium
等待的另外一種類型。顯式等待幫助可在特定時間段內(nèi)根據(jù)特定條件停止腳本的執(zhí)行瑟幕。時間到了以后磕蒲,腳本將拋出ElementNotVisibleException
異常。在測試人員不確定要等待的時間的情況下只盹,顯式等待會派上大用場辣往。使用elementToBeClickable()
或textToBePresentInElement()
之類的條件,可以等待指定的持續(xù)時間殖卑≌鞠鳎可以結(jié)合使用WebDriverWait
和ExpectedConditions
類來使用這些預(yù)定義方法。
預(yù)期條件的類型
以下是在使用Selenium執(zhí)行自動化測試時通常使用的幾種預(yù)期條件孵稽。
- visibleOfElementLocated():驗證給定元素是否存在
- alertIsPresent():驗證是否存在警報许起。
- elementToBeClickable():驗證給定元素是否在屏幕上存在/可單擊
- textToBePresentInElement():驗證給定元素是否具有必需的文本
- titlels():驗證條件十偶,等待具有給定標(biāo)題的頁面
還有更多可用的預(yù)期條件,您可以通過Selenium
官方GitHub
頁面進行引用园细。與隱式等待一樣惦积,顯式等待也會在每500毫秒后繼續(xù)輪詢。
顯式等待與隱式等待區(qū)別
隱式等待 | 顯式等待 |
---|---|
默認情況下應(yīng)用于腳本中的所有元素猛频。 | 僅適用于特定條件的特定元素狮崩。 |
不能基于指定條件(例如元素選擇/可點擊)而不是顯式地等待。 | 可以根據(jù)特定條件指定等待時間鹿寻。 |
確定該元素在特定時間內(nèi)可能可見時睦柴,通常使用它 | 不知道元素可見性的時間時,通常使用它毡熏。它具有動態(tài)性質(zhì)坦敌。 |
強制等待:sleep()
- 定義:設(shè)置固定休眠時間,單位為秒招刹。缺點是不智能恬试,使用太多的sleep會影響腳本運行速度。
- 代碼展示:
from selenium import webdriver from time import sleep driver = webdriver.Chrome() driver.get("http://www.reibang.com/") sleep(5) print(driver.current_url) driver.quit()
隱式等待:implicitly_wait
- 由webdriver提供的方法疯暑。
一旦設(shè)置這個隱式等待會在WebDriver對象實例的整個生命周期起作用训柴,只需要設(shè)置一次即可
。它不針對某一個元素妇拯,是全局元素等待幻馁,即在定位元素時,需要等待頁面全部元素加載完成越锈,才會執(zhí)行下一個語句仗嗦。如果超出了設(shè)置時間則拋出異常。 - 注意: 當(dāng)同時使用隱式等待和顯式等待時甘凭,超時時間取二者中較大的
driver.implicitly_wait(10) #隱式等待10秒
- 代碼展示:
from selenium import webdriver driver = webdriver.Chrome() driver.implicitly_wait(10) # 隱性等待稀拐,最長等10秒 driver.get("http://www.reibang.com/") print(driver.current_url) driver.quit()
顯式等待:WebDriverWait
- 定義:
- 等待某個條件成立時繼續(xù)執(zhí)行,否則在達到最大時長時拋出異常(TimeoutException)
- WebDriverWait類是由webdriver提供的等待方法丹弱,配合該類提供的until()和until_not()方法一起使用德撬,就可以根據(jù)判斷條件靈活的進行等待。
from selenium.webdriver.support.wait import WebDriverWait
- 調(diào)用方法:
- WebDriverWait(driver, 超時時長, 調(diào)用頻率, 忽略異常).until(可執(zhí)行方法, 超時時返回的信息)
- WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None).until()
- 參數(shù):
- driver:傳入WebDriver實例躲胳,瀏覽器驅(qū)動
- timeout:超時時間蜓洪,等待的最長時間
- poll_frequency:調(diào)用until或until_not中的方法間隔時間,默認是0.5秒
- ignored_exceptions:忽略的異常坯苹,如果在調(diào)用until或until_not的過程中拋出這個元組中的異常隆檀,則不中斷代碼,繼續(xù)等待。如果拋出的是這個元組外的異常恐仑,則中斷代碼泉坐,拋出異常。默認中有NoSuchElementException菊霜。
- until與until_not
- until:當(dāng)某元素出現(xiàn)或什么條件成立則繼續(xù)執(zhí)行
- until_not:當(dāng)某元素消失或什么條件不成立則繼續(xù)執(zhí)行
- until與until_not里面的兩個參數(shù)
- method:在等待期間坚冀,每隔一段時間調(diào)用這個傳入的方法,直到返回值為True;
- message:如果超時鉴逞,拋出TimeoutException记某,將message傳入異常
- method的設(shè)置
- 必須是含有call的可執(zhí)行方法。因此我們引用selenium提供的一個模塊
from selenium.webdriver.support import expected_conditions as EC
- expected_conditions類提供的預(yù)期條件判斷方法:
- title_is:判斷當(dāng)前頁面的title是否完全等于(==)預(yù)期字符串构捡,返回布爾值
from selenium import webdriver from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait driver = webdriver.Chrome() driver.get("http://www.reibang.com/") locator = (By.CLASS_NAME, 'logo') title = WebDriverWait(driver, 10).until(EC.title_is('簡書 - 創(chuàng)作你的創(chuàng)作')) print(title)
- title_contains:判斷當(dāng)前頁面的title是否包含預(yù)期字符串液南,返回布爾值
WebDriverWait(driver, 10).until(EC.title_contains('創(chuàng)作你的創(chuàng)作'))
- presence_of_element_located:判斷某個元素是否被加到了dom樹里,并不代表改元素一定可見勾徽,如果定位到就返回WebElement
WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'logo')))
- visibility_of_element_located:判斷某個元素是否可見滑凉,可見代表元素非隱藏,并且元素的寬和高都不等于0喘帚,如果可見就返回這個元素畅姊。
WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CLASS_NAME, 'write-btn')))
- visibility_of:如4一樣,只是4需要傳入locator吹由,而5直接傳所定位到的元素element就可以了若未。
WebDriverWait(driver, 10).until(EC.visibility_of(driver.find_element(by=By.CLASS_NAME, value='write-btn')))
- presence_of_all_elements_located:判斷是否至少有1個元素存在于dom樹中。如:某個頁面上含有N個元素的class都是'title'倾鲫,那么只要有1個元素存在就返回列表
WebDriverWait(driver, 10).until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'title')))
- visibility_of_any_elements_located:判斷是否至少有一個元素在頁面中可見粗合,存在就返回列表
WebDriverWait(driver, 10).until(EC.visibility_of_any_elements_located((By.CLASS_NAME, 'title')))
- text_to_be_present_in_element:判斷某個元素中的text是否包含了預(yù)期的字符串,返回布爾值
WebDriverWait(driver, 10).until(EC.text_to_be_present_in_element((By.ID, 'sign_in'), '登錄'))
- text_to_be_present_in_element_value:判斷某個元素中的value屬性是否包含了預(yù)期的字符串乌昔,返回布爾值
WebDriverWait(driver, 10).until(EC.text_to_be_present_in_element_value((By.NAME, 'utf8'), '?'))
- frame_to_be_available_and_switch_to_it:判斷該frame是否可以switch進去隙疚。如果可以,返回True并且switch進去磕道,否則返回False供屉。(很少使用)
- invisibility_of_element_located:判斷某個元素中是否不存在于dom樹中或不可見,如果可見返回False溺蕉,不可見返回這個元素
WebDriverWait(driver, 10).until(EC.invisibility_of_element_located((By.CLASS_NAME, 'popver'))) # popver在此頁面中是一個隱藏元素
- element_to_be_clickable:判斷某個元素中是否可見并且是enable的伶丐,這樣的話才叫clickable,才可以點擊
WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'sign_up'))).click()
- staleness_of:等某個元素從dom樹中移除焙贷,返回True。否則返回false
- element_to_be_selected:判斷某個元素是否別選中了贿堰,一般用在下拉列表
- element_selection_state_to_be:判斷某個元素的選中狀態(tài)是否符合預(yù)期
- element_located_selection_state_to_be:跟上面的方法作用一樣辙芍,只是上面的方法傳入定位到的element,而這個方法傳入locator。
- alert_is_present:判斷頁面上是否存在alert
alert = WebDriverWait(driver, 10).until(EC.alert_is_present()) # 如果有就切換到alert并返回alert的內(nèi)容