元素等待:如今很多web都在使用AJAX技术,运用这种技术的软件当浏览器加载页面时,页面上的元素可能不会被同步加载完成,如此一来,定位元素时就会出现困难,我们可以通过设置元素等待来改善这类问题导致的测试脚本不稳定。
WebDriver脚本开发中可以使用三种种元素等待方式:
一、强制等待:
time.sleep(5),单位是s,就是直接让线程休眠,这几秒啥事也不用干
import time #导入时间模块
time.sleep(5) #休眠5s钟
二、隐式等待:
在脚本创建driver对象之后,给driver设置一个全局的等待时间,对driver的整个生命周期(创建到关闭)都起效。如果在设置等待时间(超时时间)内,定位到了页面元素,则不再等待,继续执行下面的代码如果超出了等待时间,则抛出异常TimeoutException。
driver.implicity_wait(10):默认是0s等待,设置之后的值是最大超时时间
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(‘http://www.baidu.com’)
隐式等待,设置10s的超时时间
driver.implicitly_wait(10)
注意:在使用隐式等待的时候,实际上浏览器会在你自己设定的时间内部不断的刷新页面去寻找我们需要的元素,在使用AJAX技术的页面自动化测试中,建议使用。
三、显式等待:
就是明确的要等到某个元素的出现或者是某个元素的可点击等条件,等到就可以返回元素对象;在超时时间到达之后仍未等到,那么就抛出TimeoutException。(简而言之,就是直到元素出现才去操作,如果超时则报异常)。
先来看一下显式等待的语法,然后我们在分别解析:
element = WebDriverWait(driver,10,0.5,ignored_exceptions=None).until(EC.presence_of_element_located((By.ID,“kw”)),“找不到”)
1、WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
使用的话需要先导包:from selenium.webdriver.support.ui import WebDriverWait
class WebDriverWait(object):
def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
self._driver = driver
self._timeout = timeout
self._poll = poll_frequency
# avoid the divide by zero
if self._poll == 0:
self._poll = POLL_FREQUENCY
exceptions = list(IGNORED_EXCEPTIONS)
if ignored_exceptions is not None:
try:
exceptions.extend(iter(ignored_exceptions))
except TypeError: # ignored_exceptions is not iterable
exceptions.append(ignored_exceptions)
self._ignored_exceptions = tuple(exceptions)
driver:浏览器驱动
timeout:最长超时时间,默认以秒为单位
poll_frequency:检测的间隔(步长)时间,默认为0.5S
ignored_exceptions:超时后的异常信息,默认情况下抛NoSuchElementException异常
该WebDriverWait类中提供两个方法用于处理等待的条件:
until(method, message=’ ‘):调用该方法提供的驱动程序作为一个参数,直到返回值为True
until_not(method, message=’ ‘):调用该方法提供的驱动程序作为一个参数,直到返回值为False
2、until(method, message=’ ')
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)
直到满足某一个条件method,返回method返回的结果,否则就抛出TimeoutException。
该method参数,我们采用Expected Conditions 类提供的预期条件判断方法。
3、Expected Conditions()
需要先导包:from selenium.webdriver.support import expected_conditions as EC
该类提供的预期条件判定方法,常见的有:
title_is:判断当前页面的title是否等于预期
title_contains:判断当前页面的title是否包含预期字符串
presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表该元素一定可见
visibility_of_element_located:判断某个元素是否可见.可见代表元素非隐藏,并且元素的宽和高都不等于0
alert_is_present:判断页面上是否存在alert
text_to_be_present_in_element:判断某个元素中的text是否包含了预期的字符串
text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串
element_to_be_selected:判断某个元素是否被选中了,一般用在下拉列表
我们以presence_of_element_located()讲解,他需要一个元素定位器参数locator
class presence_of_element_located(object):
class presence_of_element_located(object):
""" An expectation for checking that an element is present on the DOM
of a page. This does not necessarily mean that the element is visible.
locator - used to find the element
returns the WebElement once it is located
"""
def __init__(self, locator):
self.locator = locator
def __call__(self, driver):
return _find_element(driver, self.locator)
元素定位器参数locator,比如(By.ID,“kw”),外层小括号不能丢
4、By()
需要导包:from selenium.webdriver.common.by import By
By类中提供了常见的定位器
class By(object):
"""
Set of supported locator strategies.
"""
ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"
5、隐式等待的案例
需求,等待百度首页百度一下是否被加载(加载到DOM),成功则返回元素对象并执行点击操作,否则抛出异常。
from selenium import webdriver
#ui--模块,WebDriverWait是个类
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
# driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
try:
driver.find_element_by_id("kw").send_keys("selenium")
element = WebDriverWait(driver,10,0.5,ignored_exceptions=None).until(EC.presence_of_element_located((By.ID,"su")),"找不到")
element.click()
time.sleep(3)
except Exception as e:
print(e)
driver.quit()
四、总结一下吧
若同时设置了隐式等待和显示等待,则以隐式等待为第一优先级,也就是说,若隐式等待时间大于显示等待,显示等待时间设置无效,因为driver若找不到元素,会先等待隐式等待的时间
time.sleep()是强制休眠,只要执行到这句代码,就会等待