一、顯示等待(有條件等待)
常見問題:
- 定位明明是對的,爲什麼運行代碼沒找到定位。
- 定位明明是對的,找到定位了,文本信息爲什麼取到是空的?
分析原因:
- 沒有處理frame
- 頁面渲染速度比自動化測試的代碼慢,頁面還沒渲染出來就定位了
- 異步請求,後端還未返回給前端,自動化測試代碼就去獲取頁面文本數據
一些同學的解決解決方案:
- 加上time.sleep()
- 設置全局隱式等待,dr.implicitly_wait()
分析解決方案:
- 解決方案一,我們不能夠確定準確的強制等待時間(代碼休眠時間),導致自動化代碼不穩定性大大增加,尤其是網絡波動的影響,會導致頁面加載速度變慢
- 全局等待雖可以解決一部分定位問題,例如需要定位的標籤屬性顯現,但是如果像異步請求,需等待帶有文本信息的相應,並渲染在頁面上,不能確定在自動化代碼執行獲取文本信息的時候,頁面已經渲染好所需要的文本信息
什麼是顯示等待?
- 條件滿足後,不再等待
二、顯示等待相關類
Wait.py
class WebDriverWait(object):
def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
"""構造函數,需要一個WebDriver實例並以秒爲單位超時
:參數:
- driver - 傳入webdriver實例對象
- timeout - 超時時間,單位 秒
- poll_frequency - 程序休眠時間,默認0.5秒
- ignored_exceptions - 忽略的異常,如果在調用until或until_not的過程中拋出這個元組中的異常,
則不中斷代碼,繼續等待,如果拋出的是這個元組外的異常,則中斷代碼,拋出異常。默認只有NoSuchElementException。
使用例子:
from selenium.webdriver.support.ui import WebDriverWait \n
element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n
is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n
until_not(lambda x: x.find_element_by_id("someId").is_displayed())
"""
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)
def until_not(self, method, message=''):
"""與unitl方法相反,不多解釋,項目中基本用不到"""
end_time = time.time() + self._timeout
while True:
try:
value = method(self._driver)
if not value:
return value
except self._ignored_exceptions:
return True
time.sleep(self._poll)
if time.time() > end_time:
break
raise TimeoutException(message)
expected_conditions.py
常用
每個類的具體用法查看源碼,寫的非常清楚
/Python/Python36/Lib/site-packages/selenium/webdriver/support
# 判斷頁面title等於預期值
title_is
# 判斷頁面title包含預期字符串
title_contains
# 判斷當前url等於預期url
url_to_be
# 判斷當前url包含預期字符串
url_matches # 正則匹配 re
url_contains # 包含 in
# 判斷當前url不等於預期url
url_changes
# 判斷元素顯現並定位成功
visibility_of_element_located
# 判斷元素顯現(不一定能定位,能定位的元素大小需大於0)
visibility_of
# 判斷獲取文本信息包含預期的文本信息
text_to_be_present_in_element
# 判斷獲取屬性值的信息包含預期的文本信息
text_to_be_present_in_element_value
# 判斷iframe可以切換,如果爲真則切換,反之返回False
frame_to_be_available_and_switch_to_it
# 判斷元素可以點擊
element_to_be_clickable
# 判斷元素被選中
element_to_be_selected
element_located_to_be_selected
# 判斷窗口數量
number_of_windows_to_be
# 判斷新窗口打開
number_of_windows_to_be
# 警告框顯現
alert_is_present
不常用
presence_of_element_located
presence_of_all_elements_located
visibility_of_any_elements_located
visibility_of_all_elements_located
invisibility_of_element_located
invisibility_of_element(invisibility_of_element_located)
staleness_of
element_selection_state_to_be
element_located_selection_state_to_be
三、顯示等待使用
demo.py
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
# 輸入框定位器
locator_of_search = (By.CSS_SELECTOR,'#kw')
# 元素顯現並定位成功後,不再等待,反則拋出超時異常
WebDriverWait(driver=driver,timeout=10,poll_frequency=0.5).until(EC.visibility_of_element_located(locator_of_search))
driver.find_element(*locator_of_search).send_keys('測試顯示等待')