python|Selenium 高阶应用之WebDriverWait 和 expected_conditions

【python|Selenium 高阶应用之WebDriverWait 和 expected_conditions】Seleniium 是相当不错的一个第三方测试框架,可惜目前国内已经无法访问其官网(FQ可以)。
不知道大家是否有认真查看过selenium 的api,我是有认真学习过的。selenium 的api中包含有WebDriverWait和 expected_conditions这两个高级应用。
下面先看WebDriverWait :
python|Selenium 高阶应用之WebDriverWait 和 expected_conditions
文章图片

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): 10def __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 17By default, it is 0.5 second. 18- ignored_exceptions - iterable structure of exception classes ignored during calls. 19By default, it contains NoSuchElementException only. 20 21Example: 22from selenium.webdriver.support.ui import WebDriverWait \n 23element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n 24is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n 25until_not(lambda x: x.find_element_by_id("someId").is_displayed()) 26""" 27self._driver = driver 28self._timeout = timeout 29self._poll = poll_frequency 30# avoid the divide by zero 31if self._poll == 0: 32self._poll = POLL_FREQUENCY 33exceptions = list(IGNORED_EXCEPTIONS) 34if ignored_exceptions is not None: 35try: 36exceptions.extend(iter(ignored_exceptions)) 37except TypeError:# ignored_exceptions is not iterable 38exceptions.append(ignored_exceptions) 39self._ignored_exceptions = tuple(exceptions) 40 41def until(self, method, message=''): 42"""Calls the method provided with the driver as an argument until the \ 43return value is not False.""" 44screen = None 45stacktrace = None 46 47end_time = time.time() + self._timeout 48while True: 49try: 50value = https://www.it610.com/article/method(self._driver) 51if value: 52return value 53except self._ignored_exceptions as exc: 54screen = getattr(exc,'screen', None) 55stacktrace = getattr(exc, 'stacktrace', None) 56time.sleep(self._poll) 57if time.time() > end_time: 58break 59raise TimeoutException(message, screen, stacktrace) 60 61def until_not(self, method, message=''): 62"""Calls the method provided with the driver as an argument until the \ 63return value is False.""" 64end_time = time.time() + self._timeout 65while True: 66try: 67value = https://www.it610.com/article/method(self._driver) 68if not value: 69return value 70except self._ignored_exceptions: 71return True 72time.sleep(self._poll) 73if time.time()> end_time: 74break 75raise TimeoutException(message)

python|Selenium 高阶应用之WebDriverWait 和 expected_conditions
文章图片
哈哈,我始终相信贴出来总会有人看。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:

python|Selenium 高阶应用之WebDriverWait 和 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. 13title is the expected title, which must be an exact match 14returns True if the title matches, false otherwise.""" 15def __init__(self, title): 16self.title = title 17 18def __call__(self, driver): 19return self.title == driver.title 20 21 class title_contains(object): 22""" An expectation for checking that the title contains a case-sensitive 23substring. title is the fragment of title expected 24returns True when the title matches, False otherwise 25""" 26def __init__(self, title): 27self.title = title 28 29def __call__(self, driver): 30return 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 34of a page. This does not necessarily mean that the element is visible. 35locator - used to find the element 36returns the WebElement once it is located 37""" 38def __init__(self, locator): 39self.locator = locator 40 41def __call__(self, driver): 42return _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 46page and visible. Visibility means that the element is not only displayed 47but also has a height and width that is greater than 0. 48locator - used to find the element 49returns the WebElement once it is located and visible 50""" 51def __init__(self, locator): 52self.locator = locator 53 54def __call__(self, driver): 55try: 56return _element_if_visible(_find_element(driver, self.locator)) 57except StaleElementReferenceException: 58return False 59 60 class visibility_of(object): 61""" An expectation for checking that an element, known to be present on the 62DOM of a page, is visible. Visibility means that the element is not only 63displayed but also has a height and width that is greater than 0. 64element is the WebElement 65returns the (same) WebElement once it is visible 66""" 67def __init__(self, element): 68self.element = element 69 70def __call__(self, ignored): 71return _element_if_visible(self.element) 72 73 def _element_if_visible(element, visibility=True): 74return 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 78on a web page. 79locator is used to find the element 80returns the list of WebElements once they are located 81""" 82def __init__(self, locator): 83self.locator = locator 84 85def __call__(self, driver): 86return _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 90specified element. 91locator, text 92""" 93def __init__(self, locator, text_): 94self.locator = locator 95self.text = text_ 96 97def __call__(self, driver): 98try : 99element_text = _find_element(driver, self.locator).text 100return self.text in element_text 101except StaleElementReferenceException: 102return False 103 104 class text_to_be_present_in_element_value(object): 105""" 106An expectation for checking if the given text is present in the element's 107locator, text 108""" 109def __init__(self, locator, text_): 110self.locator = locator 111self.text = text_ 112 113def __call__(self, driver): 114try: 115element_text = _find_element(driver, 116self.locator).get_attribute("value") 117if element_text: 118return self.text in element_text 119else: 120return False 121except StaleElementReferenceException: 122return 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 126switch to.If the frame is available it switches the given driver to the 127specified frame. 128""" 129def __init__(self, locator): 130self.frame_locator = locator 131 132def __call__(self, driver): 133try: 134if isinstance(self.frame_locator, tuple): 135driver.switch_to.frame(_find_element(driver, 136self.frame_locator)) 137else: 138driver.switch_to.frame(self.frame_locator) 139return True 140except NoSuchFrameException: 141return False 142 143 class invisibility_of_element_located(object): 144""" An Expectation for checking that an element is either invisible or not 145present on the DOM. 146 147locator used to find the element 148""" 149def __init__(self, locator): 150self.locator = locator 151 152def __call__(self, driver): 153try: 154return _element_if_visible(_find_element(driver, self.locator), False) 155except (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. 161return True 162 163 class element_to_be_clickable(object): 164""" An Expectation for checking an element is visible and enabled such that 165you can click it.""" 166def __init__(self, locator): 167self.locator = locator 168 169def __call__(self, driver): 170element = visibility_of_element_located(self.locator)(driver) 171if element and element.is_enabled(): 172return element 173else: 174return False 175 176 class staleness_of(object): 177""" Wait until an element is no longer attached to the DOM. 178element is the element to wait for. 179returns False if the element is still attached to the DOM, true otherwise. 180""" 181def __init__(self, element): 182self.element = element 183 184def __call__(self, ignored): 185try: 186# Calling any method forces a staleness check 187self.element.is_enabled() 188return False 189except StaleElementReferenceException as expected: 190return True 191 192 class element_to_be_selected(object): 193""" An expectation for checking the selection is selected. 194element is WebElement object 195""" 196def __init__(self, element): 197self.element = element 198 199def __call__(self, ignored): 200return self.element.is_selected() 201 202 class element_located_to_be_selected(object): 203"""An expectation for the element to be located is selected. 204locator is a tuple of (by, path)""" 205def __init__(self, locator): 206self.locator = locator 207 208def __call__(self, driver): 209return _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. 213element is WebElement object 214is_selected is a Boolean." 215""" 216def __init__(self, element, is_selected): 217self.element = element 218self.is_selected = is_selected 219 220def __call__(self, ignored): 221return self.element.is_selected() == self.is_selected 222 223 class element_located_selection_state_to_be(object): 224""" An expectation to locate an element and check if the selection state 225specified is in that state. 226locator is a tuple of (by, path) 227is_selected is a boolean 228""" 229def __init__(self, locator, is_selected): 230self.locator = locator 231self.is_selected = is_selected 232 233def __call__(self, driver): 234try: 235element = _find_element(driver, self.locator) 236return element.is_selected() == self.is_selected 237except StaleElementReferenceException: 238return False 239 240 class alert_is_present(object): 241""" Expect an alert to be present.""" 242def __init__(self): 243pass 244 245def __call__(self, driver): 246try: 247alert = driver.switch_to.alert 248alert.text 249return alert 250except NoAlertPresentException: 251return False 252 253 def _find_element(driver, by): 254"""Looks up an element. Logs and re-raises ``WebDriverException`` 255if thrown.""" 256try : 257return driver.find_element(*by) 258except NoSuchElementException as e: 259raise e 260except WebDriverException as e: 261raise e 262 263 def _find_elements(driver, by): 264try : 265return driver.find_elements(*by) 266except WebDriverException as e: 267raise e

python|Selenium 高阶应用之WebDriverWait 和 expected_conditions
文章图片
哈哈,我相信这个py文件大家一看就能懂。这无非就是一些预期条件。
结合上面的WebDriverWait,我们可以这么用:
python|Selenium 高阶应用之WebDriverWait 和 expected_conditions
文章图片
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC''' 10秒钟等待浏览器弹出的对话框,如果出现,就点击确定按钮 ''' WebDriverWait(chromedriver,10).until(EC.alert_is_present()).accept()

python|Selenium 高阶应用之WebDriverWait 和 expected_conditions
文章图片
我们的自动化脚本跑得快慢或者出现异常,很大程度上取决于我们设定的等待时间,如果你还是习惯于time.sleep(5)这种方式的话,这将会浪费很多


时间。

根据expected_conditions.py文件的写法,我们也可以定义一些自己的期待类,例如:

python|Selenium 高阶应用之WebDriverWait 和 expected_conditions
文章图片
from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as ECclass must_get_url(object): ''' 必须到达的URL 参数: url- 必须到达的地址 ''' def __init__(self, url): self.url = urldef __call__(self, driver): driver.get(self.url) return self.url == driver.current_urloptions = webdriver.ChromeOptions() options.add_argument("--test-type") chromedriver =webdriver.Chrome(r"E:\MyProject\WebDriver\chromedriver.exe",chrome_options=options) WebDriverWait(chromedriver,10).until(must_get_url("https://www.baidu.com"))

python|Selenium 高阶应用之WebDriverWait 和 expected_conditions
文章图片

    推荐阅读