最近忙于其他事情,博客就没那么多时间来写。原本想先分享下三种等待方式,但是隐式等待我还有点不太懂。这次先分享显式等待。
个人博客:https://blog.csdn.net/zyooooxie
显示等待,是针对于某个特定的元素设置的等待时间。
源码:
POLL_FREQUENCY = 0.5 # How long to sleep inbetween calls to the method
IGNORED_EXCEPTIONS = (NoSuchElementException,) # exceptions ignored during calls to the method
class WebDriverWait(object):
def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
"""Constructor, takes a WebDriver instance and timeout in seconds.
:Args:
- driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote)
- timeout - Number of seconds before timing out
- poll_frequency - sleep interval between calls
By default, it is 0.5 second.
- ignored_exceptions - iterable structure of exception classes ignored during calls.
By default, it contains NoSuchElementException only.
Example:
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())
"""
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)
通过注释了解到:ignored_exceptions:调用方法时忽略的异常;poll_frequency:在调用方法之间睡多久;
init()方法需要传参 driver、timeout、poll_frequency、ignored_exceptions;
driver:webdriver的驱动;
timeout:最长超时时间,默认以秒为单位;
poll_frequency:休眠时间(步长)的间隔,检测间隔时间,默认0.5s;
ignored_exceptions: 超时后的异常信息,默认情况下抛 “NoSuchElementException"异常;
在设置时间timeout内,每隔一段时间poll_frequency(默认0.5秒) 检测一次当前页面,元素是否存在,如果超过设置时间还检测不到则抛出异常ignored_exceptions,如果元素存在则立即反馈。
那要怎么用呢?
看下官方的举例: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())
WebDriverWait 一般是配合until() 或 until_not()方法,就能够根据判断条件而灵活地等待了。主要的意思就是:程序每隔xx秒看一眼,如果条件成立了,则执行下一步;否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException异常。
格式:
WebDriverWait(driver, timeout).until(method, message=’’)
WebDriverWait(driver, timeout).until_not(method, message=’’)
【until_not() 我没用过,本篇就分享until()】
源码:
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)
def until_not(self, method, message=''):
"""Calls the method provided with the driver as an argument until the \
return value is False."""
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)
until(method,message=’’) 的注释:Calls the method provided with the driver as an argument until the return value is not False 将驱动提供的方法作为参数调用,直到返回值不为False;
好绕啊,要疯啦,
我觉得就是在说:调用method作为一个参数,直到返回值为True;
那这个参数(或者叫条件) value = method(self._driver) 到底是什么,要怎样用呢?
不妨回到起点,显式等待到底是什么?
显式等待会让WebDriver等待满足一定的条件以后再进一步的执行。 这 满足一定的条件 是不是value?我觉得 就是。
在自动化测试中,最基本的、最重要的 要满足的条件就是查找到元素,find element;
所以value 应该可以写成driver.find_element(),对吧?
def test_56(self):
""" 可执行方法method参数,很多人传入了WebElement对象 这是错误的"""
from selenium.webdriver.support.wait import WebDriverWait
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.implicitly_wait(5)
self.driver.get("https://www.baidu.com")
WebDriverWait(self.driver, 10).until(self.driver.find_element_by_id('kw')) # 错误
time.sleep(2)
self.driver.quit()
但 报错了。
File "D:\oss_1\Common\yidu.py", line 3900, in test_56
WebDriverWait(self.driver, 10).until(self.driver.find_element_by_id('kw')) # 错误
File "C:\Users\admin\AppData\Local\Programs\Python\Python36-32\lib\site-packages\selenium\webdriver\support\wait.py", line 71, in until
value = method(self._driver)
TypeError: 'WebElement' object is not callable
说的是 ‘WebElement’ object is not callable;所以 这里的参数一定要是可以调用的,即这个对象一定有 call() 方法,否则会抛出异常。
如何处理呢? 一般采用匿名函数lambda 。
lambda driver:driver.find_element(<定位元素>)
【当定位到元素时返回为WebElement,找不到元素时为显式等待 报错】(这儿后面会继续深入分享)
def test_57z3(self):
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://www.baidu.com")
print('0', time.ctime())
# TypeError: 'WebElement' object is not callable
try:
WebDriverWait(driver, 10).until(driver.find_element_by_id('kw'), '失败')
except Exception as e11:
print(e11)
print('1', time.ctime())
# 成功
try:
WebDriverWait(driver, 10).until(lambda the_driver: the_driver.find_element_by_id('kw'), '失败')
except Exception as e33:
print(e33)
print('3', time.ctime())
time.sleep(1)
driver.quit()
这个用例就说明了 显式等待和until()结合后,可以智能查找元素;但是在web中有些元素是隐藏的,确实是存在;只不过不显示,那就不方便执行操作,要怎么做一个可以判断元素显示与否的显式等待呢?
用WebElement的 is_displayed() 、is_enabled()、is_selected() 方法
WebDriverWait(driver, 10).until(lambda the_driver: the_driver.find_element_by_id(‘kw’).is_displayed())
def test_57z5(self):
from selenium.webdriver.support.wait import WebDriverWait
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("https://www.12306.cn/index/")
print('开始', time.ctime())
#
# 这个元素默认是隐藏的
# selenium.common.exceptions.TimeoutException: Message: 失败
try:
WebDriverWait(self.driver, 10).until(lambda the_driver: the_driver.find_element_by_id('toStation').is_displayed(), '失败')
except Exception as e33:
print(e33) # 显式等待的10秒 Message: 失败
print('0', time.ctime())
# 成功
try:
WebDriverWait(self.driver, 10).until(lambda the_driver: the_driver.find_element_by_id('toStation'), '失败')
except Exception as e33:
print(e33)
print('1', time.ctime())
time.sleep(1)
self.driver.quit()
结果很明显:
Launching unittests with arguments python -m unittest yidu.Test_yidu.test_57z5 in D:\oss_1\Common
开始 Tue Nov 27 10:12:12 2018
Message: 失败
0 Tue Nov 27 10:12:23 2018
1 Tue Nov 27 10:12:23 2018
Ran 1 test in 21.744s
OK
所以一种很简单的 把元素查找作为条件的 显式等待就出来了,这是可以直接用到自动化脚本中。起码比起强制等待time.sleep()要智能很多的。
下一次分享 显式等待(二)expected_conditions类
交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.csdn.net/zyooooxie