Explicit Waits 显式等待
An explicit wait is code you define to wait for a certain condition to occur before proceeding
further in the code
显式等待指的是需要明确指定一个等待的条件,如果这个条件成立,则结束等待,如果过了一定的时间后,等待条件还不成立则报超时
Implicit Waits 隐式等待
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time
when trying to find an element or elements if they are not immediately avaliable
隐式等待指的是当查找元素时默认等待一定的时间,如果在这段时间内找到了元素,则程序继续进行,不一定要等到所规定的时间结束
,如果过了这段时间还没有找到元素则返回超时错误
测试用例设计:
网页点击两个元素,一个元素出来的时间为3秒,另一个元素出来的时间为6秒
每当要找一个不能及时出现的元素时就会调用wait
implicit wait(driver,6)至少要设置6秒,因为第二个元素需要等6秒,但这并不影响性能,因为在等第一个元素时,实际只用了3秒
对于explicit wait(driver,3)针对第一个元素,explicit wait(driver,6)针对第二个元素设计
test_wait.py
#!/usr/bin/env python
#encoding:utf-8
import unittest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class Two_Ways_Wait(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
def test_implicit_wait(self):
driver = self.driver
driver.get("F:\\vim\\wait.html") #get web page
driver.implicitly_wait(10) #隐式等待设置10秒>6秒
driver.find_element_by_id("b").click() #点击click后过3秒会出现一个兰色的div
driver.find_element_by_css_selector(".blue_box") #当需要找兰色的div这个元素时,由于不是及时出现的,所以会调用implicitly_wait(10)(实际3秒)
driver.find_element_by_id("b").click() #再次点击click后6秒会出现一个红色的div
driver.find_element_by_css_selector(".red_box") #当需要找红色的div这个元素时,由于不是及时出现的,所以会调用implicitly_wait(10)(实际6秒)
print "test_implicit_wait"
def test_explicit_wait(self):
driver = self.driver
driver.get("F:\\vim\wait.html")
driver.find_element_by_id("b").click()
WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,".blue_box"))) #driver将会等待10秒直到兰色div出现结束(实际3秒)
driver.find_element_by_id("b").click()
WebDriverWait(driver,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,".red_box"))) #driver将会等待10秒直到红色div出现结束(实际6秒)
print "test_explicit_wait"
def tearDown(self):
self.driver.close()
if __name__=='__main__':
unittest.main()
-------------------------------------------------------------------------------------------
test_implicit_wait
.
----------------------------------------------------------------------
Ran 1 test in 17.124s #隐式等待单独执行用时17.124秒
OK
test_explicit_wait
.
----------------------------------------------------------------------
Ran 1 test in 17.643s #显式等待单独执行用时17.643秒,性能相差无己
OK
-------------------------------------------------------------------------
test_explicit_wait
.test_implicit_wait
.
----------------------------------------------------------------------
Ran 2 tests in 36.751s
OK
显式等待的expected condition
title is
title_contains
presence_of_element_located
visibility_of_element_located
visibility_of
presence_of_all_elements_located
text_to_be_present_in_element
text_to_be_present_in_element_value
frame_to_be_available_and_switch_to_it
invisibility_of_element_located
element_to_be_clickable
staleness_of
element_to_be_selected
element_to_be_located_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
alert_is_present
显式等待条件的实质
selenium webdriverwait 源码
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)
每隔0.5刷新,直到method返回为真,最后的时间为(当前时间+n*self.poll)
自定义expected_condition
def condition(self,driver): #值得注意的是这边要留一个参数给until,因为until中的method(self._driver)
element = driver.find_element(By.CSS_SELECTOR,".blue_box")
return element
调用:
WebDriverWait(driver,10).until(self.condition)
附测试前端代码
wait.html
<html>
<head>
<title>Set Timeout</title>
<style>
.blue_box {
background-color: blue;
width = 50%;
height: 100px;
border: none;}
.red_box {
background-color: red;
width = 50%;
height: 200px;
border: none;}
</style>
<script>
var i = 0;
function show_div(){
if (i==0)
{
setTimeout("create_div1()",5000);
i=1;
}
else
setTimeout("create_div2()",5000)
}
function create_div1(){
d = document.createElement('div');
d.className = "blue_box";
document.body.appendChild(d);
b = document.getElementById("b");
document.createElement(b)}
function create_div2(){
d = document.createElement('div');
d.className = "red_box";
document.body.appendChild(d);
b = document.getElementById("b");
document.createElement(b)}
</script>
</head>
<body>
<button id = "b" onclick = "show_div()">click</button>
</body>
</html
附EC
expected_conditions:
title_is
title_contains
presence_of_element_located
visibility_of_element_located
visibility_of_element_located
presence_of_all_elements_located
text_to_be_present_in_element
text_to_be_present_in_element_value
frame_to_be_available_and_switch_to_it
invisibility_of_element_located
element_to_be_selected
element_selection_state_to_be
element_located_selection_state_to_be
alert_is_present
总结:
网上一些资料说显式比隐式要好,隐式全局,查找每一个元素都要浪费时间,影响性能,但从测试结果上来说并没有相差太多,而且
隐式也是智能等待的,当所需要找的元素出现时立即下一步,而且不浪费时间
但显式等待与隐式等待有一些区别:
显示等待是更加有针对性的的某一个特定的元素,是局部的,易于理解
隐示等待是全局的,全局只要写一次,每当需要找元素时都会调用该隐式等待,如果元素出来的快则快,出来的慢就需要慢慢等
由于显示等待考虑的是个体,所以根据个体来考虑设置时间,而隐式等待需要考虑到的整个sessiion所有元素的时间,所以在设置时只能设置一个最大值,
否则有些需要等待的元素会报超时
从性能上说,相差无己
从设计上说,显示等待更加合理
从偷懒角度上说,隐式等待更加一劳永逸