1. 程式人生 > >Selenium 高階應用之WebDriverWait 和 expected_conditions

Selenium 高階應用之WebDriverWait 和 expected_conditions

 Seleniium 是相當不錯的一個第三方測試框架,可惜目前國內已經無法訪問其官網(FQ可以)。

      不知道大家是否有認真檢視過selenium 的api,我是有認真學習過的。selenium 的api中包含有WebDriverWait  和 expected_conditions這兩個高階應用。

  下面先看WebDriverWait :

複製程式碼
 1 import time
 2 from selenium.common.exceptions import NoSuchElementException
 3 from selenium.common.exceptions import
TimeoutException 4 5 POLL_FREQUENCY = 0.5 # How long to sleep inbetween calls to the method 6 IGNORED_EXCEPTIONS = (NoSuchElementException,) # exceptions ignored during calls to the method 7 8 9 class WebDriverWait(object): 10 def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
11 """Constructor, takes a WebDriver instance and timeout in seconds. 12 13 :Args: 14 - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote) 15 - timeout - Number of seconds before timing out 16 - poll_frequency - sleep interval between calls
17 By default, it is 0.5 second. 18 - ignored_exceptions - iterable structure of exception classes ignored during calls. 19 By default, it contains NoSuchElementException only. 20 21 Example: 22 from selenium.webdriver.support.ui import WebDriverWait \n 23 element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n 24 is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n 25 until_not(lambda x: x.find_element_by_id("someId").is_displayed()) 26 """ 27 self._driver = driver 28 self._timeout = timeout 29 self._poll = poll_frequency 30 # avoid the divide by zero 31 if self._poll == 0: 32 self._poll = POLL_FREQUENCY 33 exceptions = list(IGNORED_EXCEPTIONS) 34 if ignored_exceptions is not None: 35 try: 36 exceptions.extend(iter(ignored_exceptions)) 37 except TypeError: # ignored_exceptions is not iterable 38 exceptions.append(ignored_exceptions) 39 self._ignored_exceptions = tuple(exceptions) 40 41 def until(self, method, message=''): 42 """Calls the method provided with the driver as an argument until the \ 43 return value is not False.""" 44 screen = None 45 stacktrace = None 46 47 end_time = time.time() + self._timeout 48 while True: 49 try: 50 value = method(self._driver) 51 if value: 52 return value 53 except self._ignored_exceptions as exc: 54 screen = getattr(exc, 'screen', None) 55 stacktrace = getattr(exc, 'stacktrace', None) 56 time.sleep(self._poll) 57 if time.time() > end_time: 58 break 59 raise TimeoutException(message, screen, stacktrace) 60 61 def until_not(self, method, message=''): 62 """Calls the method provided with the driver as an argument until the \ 63 return value is False.""" 64 end_time = time.time() + self._timeout 65 while True: 66 try: 67 value = method(self._driver) 68 if not value: 69 return value 70 except self._ignored_exceptions: 71 return True 72 time.sleep(self._poll) 73 if time.time() > end_time: 74 break 75 raise TimeoutException(message)
複製程式碼

 哈哈,我始終相信貼出來總會有人看。WebDriverWait 類位於selenium.webdriver.support.ui下面的例子很簡單,

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())

WebDriverWait 裡面主要有兩個方法,一個是until和until_not

那麼我們可以這樣用:
WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("某個按鈕")).click()

  意思就是在10秒內等待某個按鈕被定位到,咱們再去點選。就是每隔0.5秒內呼叫一下until裡面的表示式或者方法函式,要麼10秒內表示式執行成功,要麼10秒後

丟擲超時異常。

然後我們再看expected_conditions:
複製程式碼
  1 from selenium.common.exceptions import NoSuchElementException
  2 from selenium.common.exceptions import NoSuchFrameException
  3 from selenium.common.exceptions import StaleElementReferenceException
  4 from selenium.common.exceptions import WebDriverException
  5 from selenium.common.exceptions import NoAlertPresentException
  6 
  7 """
  8  * Canned "Expected Conditions" which are generally useful within webdriver
  9  * tests.
 10 """
 11 class title_is(object):
 12     """An expectation for checking the title of a page.
 13     title is the expected title, which must be an exact match
 14     returns True if the title matches, false otherwise."""
 15     def __init__(self, title):
 16         self.title = title
 17 
 18     def __call__(self, driver):
 19         return self.title == driver.title
 20 
 21 class title_contains(object):
 22     """ An expectation for checking that the title contains a case-sensitive
 23     substring. title is the fragment of title expected
 24     returns True when the title matches, False otherwise
 25     """
 26     def __init__(self, title):
 27         self.title = title
 28 
 29     def __call__(self, driver):
 30         return self.title in driver.title
 31 
 32 class presence_of_element_located(object):
 33     """ An expectation for checking that an element is present on the DOM
 34     of a page. This does not necessarily mean that the element is visible.
 35     locator - used to find the element
 36     returns the WebElement once it is located
 37     """
 38     def __init__(self, locator):
 39         self.locator = locator
 40 
 41     def __call__(self, driver):
 42         return _find_element(driver, self.locator)
 43 
 44 class visibility_of_element_located(object):
 45     """ An expectation for checking that an element is present on the DOM of a
 46     page and visible. Visibility means that the element is not only displayed
 47     but also has a height and width that is greater than 0.
 48     locator - used to find the element
 49     returns the WebElement once it is located and visible
 50     """
 51     def __init__(self, locator):
 52         self.locator = locator
 53 
 54     def __call__(self, driver):
 55         try:
 56             return _element_if_visible(_find_element(driver, self.locator))
 57         except StaleElementReferenceException:
 58             return False
 59 
 60 class visibility_of(object):
 61     """ An expectation for checking that an element, known to be present on the
 62     DOM of a page, is visible. Visibility means that the element is not only
 63     displayed but also has a height and width that is greater than 0.
 64     element is the WebElement
 65     returns the (same) WebElement once it is visible
 66     """
 67     def __init__(self, element):
 68         self.element = element
 69 
 70     def __call__(self, ignored):
 71         return _element_if_visible(self.element)
 72 
 73 def _element_if_visible(element, visibility=True):
 74     return element if element.is_displayed() == visibility else False
 75 
 76 class presence_of_all_elements_located(object):
 77     """ An expectation for checking that there is at least one element present
 78     on a web page.
 79     locator is used to find the element
 80     returns the list of WebElements once they are located
 81     """
 82     def __init__(self, locator):
 83         self.locator = locator
 84 
 85     def __call__(self, driver):
 86         return _find_elements(driver, self.locator)
 87 
 88 class text_to_be_present_in_element(object):
 89     """ An expectation for checking if the given text is present in the
 90     specified element.
 91     locator, text
 92     """
 93     def __init__(self, locator, text_):
 94         self.locator = locator
 95         self.text = text_
 96 
 97     def __call__(self, driver):
 98         try :
 99             element_text = _find_element(driver, self.locator).text
100             return self.text in element_text
101         except StaleElementReferenceException:
102             return False
103 
104 class text_to_be_present_in_element_value(object):
105     """
106     An expectation for checking if the given text is present in the element's
107     locator, text
108     """
109     def __init__(self, locator, text_):
110         self.locator = locator
111         self.text = text_
112 
113     def __call__(self, driver):
114         try:
115             element_text = _find_element(driver,
116                                          self.locator).get_attribute("value")
117             if element_text:
118                 return self.text in element_text
119             else:
120                 return False
121         except StaleElementReferenceException:
122                 return False
123 
124 class frame_to_be_available_and_switch_to_it(object):
125     """ An expectation for checking whether the given frame is available to
126     switch to.  If the frame is available it switches the given driver to the
127     specified frame.
128     """
129     def __init__(self, locator):
130         self.frame_locator = locator
131 
132     def __call__(self, driver):
133         try:
134             if isinstance(self.frame_locator, tuple):
135                 driver.switch_to.frame(_find_element(driver,
136                                                      self.frame_locator))
137             else:
138                 driver.switch_to.frame(self.frame_locator)
139             return True
140         except NoSuchFrameException:
141             return False
142 
143 class invisibility_of_element_located(object):
144     """ An Expectation for checking that an element is either invisible or not
145     present on the DOM.
146 
147     locator used to find the element
148     """
149     def __init__(self, locator):
150         self.locator = locator
151 
152     def __call__(self, driver):
153         try:
154             return _element_if_visible(_find_element(driver, self.locator), False)
155         except (NoSuchElementException, StaleElementReferenceException):
156             # In the case of NoSuchElement, returns true because the element is
157             # not present in DOM. The try block checks if the element is present
158             # but is invisible.
159             # In the case of StaleElementReference, returns true because stale
160             # element reference implies that element is no longer visible.
161             return True
162 
163 class element_to_be_clickable(object):
164     """ An Expectation for checking an element is visible and enabled such that
165     you can click it."""
166     def __init__(self, locator):
167         self.locator = locator
168 
169     def __call__(self, driver):
170         element = visibility_of_element_located(self.locator)(driver)
171         if element and element.is_enabled():
172             return element
173         else:
174             return False
175 
176 class staleness_of(object):
177     """ Wait until an element is no longer attached to the DOM.
178     element is the element to wait for.
179     returns False if the element is still attached to the DOM, true otherwise.
180     """
181     def __init__(self, element):
182         self.element = element
183 
184     def __call__(self, ignored):
185         try:
186             # Calling any method forces a staleness check
187             self.element.is_enabled()
188             return False
189         except StaleElementReferenceException as expected:
190             return True
191 
192 class element_to_be_selected(object):
193     """ An expectation for checking the selection is selected.
194     element is WebElement object
195     """
196     def __init__(self, element):
197         self.element = element
198 
199     def __call__(self, ignored):
200         return self.element.is_selected()
201 
202 class element_located_to_be_selected(object):
203     """An expectation for the element to be located is selected.
204     locator is a tuple of (by, path)"""
205     def __init__(self, locator):
206         self.locator = locator
207 
208     def __call__(self, driver):
209         return _find_element(driver, self.locator).is_selected()
210 
211 class element_selection_state_to_be(object):
212     """ An expectation for checking if the given element is selected.
213     element is WebElement object
214     is_selected is a Boolean."
215     """
216     def __init__(self, element, is_selected):
217         self.element = element