webdriver支持顯式和隱式的同步。本節主要內容如下:
-
顯式和隱式等待
-
何時使用顯式和隱式的等待
-
使用預期條件
-
創建自定義的等待狀態
使用隱式等待
隱式等待提供了通用的方法同步測試和步驟。適用於網絡響應時間不一致或者使用Ajax調用渲染元素的時候。
隱式等待的默認超時時間是0,對整個webdriver生效。這個功能我們在第2章就有使用,現在我們把當時實例的隱式等待時間從30秒改成10秒。
import unittest
from selenium import webdriver
class SearchProductTest(unittest.TestCase):
def setUp(self):
# create a new Firefox session
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(10)
self.driver.maximize_window()
# navigate to the application home page
self.driver.get('http://demo-store.seleniumacademy.com/')
def test_search_by_category(self):
# get the search textbox
self.search_field = self.driver.find_element_by_name('q')
self.search_field.clear()
# enter search keyword and submit
self.search_field.send_keys('phones')
self.search_field.submit()
# get all the anchor elements which have product names displayed
# currently on result page using find_elements_by_xpath method
products = self.driver\
.find_elements_by_xpath("//h2[@class='product-name']/a")
# check count of products shown in results
self.assertEqual(3, len(products))
def tearDown(self):
# close the browser window
self.driver.quit()
if __name__ == '__main__':
unittest.main(verbosity=2)
針對具體案例,顯式案例通常隱式案例要好。
explicit_wait_tests.py
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
import unittest
class ExplicitWaitTests(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.get('http://demo-store.seleniumacademy.com/')
def test_account_link(self):
WebDriverWait(self.driver, 10)\
.until(lambda s: s.find_element_by_id('select-language').get_attribute('length') == '3')
account = WebDriverWait(self.driver, 10)\
.until(expected_conditions.visibility_of_element_located((By.LINK_TEXT, 'ACCOUNT')))
account.click()
def test_create_new_customer(self):
# click on Log In link to open Login page
self.driver.find_element_by_link_text('ACCOUNT').click()
# wait for My Account link in Menu
my_account = WebDriverWait(self.driver, 10)\
.until(expected_conditions.visibility_of_element_located((By.LINK_TEXT, 'My Account')))
my_account.click()
# get the Create Account button
create_account_button = WebDriverWait(self.driver, 10)\
.until(expected_conditions.element_to_be_clickable((By.LINK_TEXT, 'CREATE AN ACCOUNT')))
# click on Create Account button. This will displayed new account
create_account_button.click()
WebDriverWait(self.driver, 10)\
.until(expected_conditions.title_contains('Create New Customer Account'))
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main(verbosity=2)
expected_conditions類
完整的屬性和方法參見:selenium.webdriver.support.expected_conditions
該類的常見方法如下:
Method | Description | Argument | Example |
element_to_be_clickable(locator) | This will wait for an element to be located and be visible and enabled so that it can be clicked. This method returns the element that is located back to the test. | locator: This is a tuple of (by, locator). | WebDriverWait?(self.driver, 10).until(expected_conditions.element_to_be_clickable((By.NAME,“is_subscribed”))) |
element_to_be_selected(element) | This will wait until a specified element is selected. | element: This is the WebElement?. | subscription = self.driver.find_element_by_name(“is_subscribed”) WebDriverWait?(self.driver, 10).until(expected_conditions.element_to_be_selected(subscription)) |
invisibility_of_element_located(locator) | This will wait for an element that is either invisible or is not present on the DOM. | locator: This is a tuple of (by, locator). | WebDriverWait?(self.driver, 10).until(expected_conditions.invisibility_of_element_located((By.ID,“loading_banner”))) |
presence_of_all_elements_located(locator) | This will wait until at least one element for the matching locator is present on the web page. This method returns the list ofWebElements? once they are located. | locator: This is a tuple of (by, locator). | WebDriverWait?(self.driver,10).until(expected_conditions.presence_of_all_elements_located((By.CLASS_NAME,“input-text”))) |
presence_of_element_located(locator) | This will wait until an element for the matching locator is present on a web page or available on the DOM. This method returns an element once it is located. | locator: This is a tuple of (by, locator). | WebDriverWait?(self.driver, 10).until(expected_conditions.presence_of_element_located((By.ID,“search”))) |
text_to_be_present_in_element(locator, text_) | This will wait until an element is located and has the given text. | locator: This is a tuple of (by, locator). text: This is the text to be checked. | WebDriverWait?(self.driver,10).until(expected_conditions.text_to_be_present_in_element((By.ID,“sele language”),“English”)) |
title_contains(title) | This will wait for the page tile to contain a casesensitive substring.This method returns true if the tile matches, false otherwise。 | title: This is the substring of the title to check. | WebDriverWait?(self.driver, 10).until(expected_conditions.title_contains(“Create New Customer Account”)) |
title_is(title) | This will wait for the page tile to be equal to the expected title. This method returns true if the tile matches, false otherwise. | title: This is the title of the page. | WebDriverWait?(self.driver, 10).until(expected_conditions.title_is(“Create New Customer Account -Magento Commerce Demo Store”)) |
visibility_of(element) | This will wait until an element is present in DOM, is visible, and its width and height are greater than zero. This method returns the (same)WebElement? once it becomes visible. | element: This is the WebElement?. | first_name = self.driver.find_element_by_id(“firstname”) WebDriverWait?(self.driver,10).until(expected_conditions.visibility_of(first_name)) |
visibility_of_element_located(locator) | This will wait until an element to be located is present in DOM, is visible, and its width and height are greater than zero. This method returns theWebElement? once it becomes visible. | locator: This is a tuple of (by, locator). | WebDriverWait?(self.driver,10).until(expected_conditions.visibility_of_element_located((By.ID,“firstname”))) |
前一章的彈出窗口處理得不夠好,現在我們修改下:comparetests.py
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
import unittest
class CompareProducts(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.get('http://demo-store.seleniumacademy.com/')
def test_compare_products_removal_alert(self):
# get the search textbox
search_field = self.driver.find_element_by_name('q')
search_field.clear()
# enter search keyword and submit
search_field.send_keys('phones')
search_field.submit()
# click the Add to compare link
self.driver.\
find_element_by_link_text('Add to Compare').click()
# wait for Clear All link to be visible
clear_all_link = WebDriverWait(self.driver, 10)\
.until(expected_conditions.visibility_of_element_located((By.LINK_TEXT, 'Clear All')))
# click on Clear All link,
# this will display an alert to the user
clear_all_link.click()
# wait for the alert to present
alert = WebDriverWait(self.driver, 10)\
.until(expected_conditions.alert_is_present())
# get the text from alert
alert_text = alert.text
# check alert text
self.assertEqual('Are you sure you would like to remove all products from your comparison?',
alert_text)
# click on Ok button
alert.accept()
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main(verbosity=2)
參考資料
-
作者:Unmesh Gundecha
-
評審:Adil Imroz:alam.adil12#gmail.com Twitter at @adilimroz
-
評審: Walt Stoneburner: wls#wwco.com Walt.Stoneburner#gmail.com 博客