Python Selenium WebDriver. Написание моего собственного ожидаемого состояния
Я пытаюсь написать свое собственное ожидаемое состояние. Что мне нужно... У меня есть iframe. и у меня также есть изображение в этом. Я хочу продолжить обработку, когда изменится изображение. Что я сделал:
class url_changed_condition(object):
'''
Checks whether url in iframe has changed or not
'''
def __init__(self, urls):
self._current_url, self._new_url = urls
def __call__(self, ignored):
return self._current_url != self._new_url
и позже в коде у меня есть:
def process_image(self, locator, current_url):
try:
WebDriverWait(self.driver, 10).until(ec.presence_of_element_located((By.TAG_NAME, u"iframe")))
iframe = self.driver.find_element(*locator)
if iframe:
print "Iframe found!"
self.driver.switch_to_frame(iframe)
WebDriverWait(self.driver, 10).until(ec.presence_of_element_located((By.XPATH, u"//div")))
# WebDriverWait(self.driver, 10).until(
# url_changed_condition(
# (current_url, self.driver.find_element(By.XPATH, u"//a/img").get_attribute(u"src"))))
img_url = self.driver.find_element(By.XPATH, u"//a/img").get_attribute(u"src")
print img_url
self.search_dict[self._search_item].append(img_url)
self.driver.switch_to_default_content()
except NoSuchElementException as NSE:
print "iframe not found! {0}".format(NSE.msg)
except:
print "something went wrong"
import traceback
import sys
type_, value_, trace_ = sys.exc_info()
print type_, value_
print traceback.format_tb(trace_)
finally:
return current_url
Этот код работает, но возвращает один и тот же URL несколько раз. Проблема в том, когда я раскомментирую url_changed_condition
это падает с TimeoutException
в(current_url, self.driver.find_element(By.XPATH, u"//a/img").get_attribute(u"src"))
Строка под ним работает нормально... Я не понимаю.
3 ответа
Похоже, в этой теме отсутствует пример ожидаемого пользовательского условия.
Это на самом деле довольно легко. Прежде всего, что такое ожидаемое условие в привязках селена Python:
- это новый стиль
class
(на основеobject
) - она имеет
__call__()
определен магический метод, который возвращает логическое значение
Существует большой набор встроенных классов ожидаемых условий.
Давайте работать через пример. Допустим, мы хотим подождать, пока текст элемента не начнется с желаемого текста:
from selenium.webdriver.support import expected_conditions as EC
class wait_for_text_to_start_with(object):
def __init__(self, locator, text_):
self.locator = locator
self.text = text_
def __call__(self, driver):
try:
element_text = EC._find_element(driver, self.locator).text
return element_text.startswith(self.text)
except StaleElementReferenceException:
return False
Использование:
WebDriverWait(driver, 10).until(wait_for_text_to_start_with((By.ID, 'myid'), "Hello, World!"))
Используя технику, описанную @alecxe, но немного измененную, чтобы справиться с ожидаемыми условиями, которые принимают элемент вместо локатора:
(В этом случае, так как нет selenium.webdriver.support.expected_conditions.invisibility_of(element)
Я жду is_displayed()
способ подать сигнал Ложь)
class wait_for_element_to_be_invisible(object):
def __init__(self, element):
self.element = element
def __call__(self, driver):
return not(self.element.is_displayed())
def test_collapsible_blocks_expand_or_collapse(self):
self.browser.get(self.server_url+'/courses/1/')
shadables = self.browser.find_elements_by_class_name('shade')
for shadable in shadables:
## parent, then sibling element (*)
shady_bit = shadable.find_element_by_xpath('../following-sibling::*')
element = WebDriverWait(self.browser, 10).until(
EC.visibility_of(shady_bit))
shadable.click()
element = WebDriverWait(self.browser, 10).until(
self.wait_for_element_to_be_invisible(shady_bit))
Фрагмент HTML с соответствующими битами DOM:
<h4 class="shadable"><span class="shade" title="Show/Hide">↓</span>
<a href="/link/to/uri">Title of Section</a>
</h4>
<article class="abstract">
<p>Descriptive part which is shadable
</p>
</article>`
Согласно документации:
По умолчанию WebDriverWait вызывает ExpectedCondition каждые 500 миллисекунд, пока не завершится успешно. Успешное возвращение для типа ExpectedCondition - логическое возвращаемое значение true или не нулевое возвращаемое значение для всех других типов ExpectedCondition.
Тот факт, что вы получаете один и тот же URL несколько раз, если вы закомментируете пользовательское ожидание, должен подсказывать вам.
В __call__()
ты всегда возвращаешься False
так как URL никогда не меняются. Так как ты возвращаешься False
, ожидаемое условие никогда не выполняется, и вы получаете TimeoutException
,
Поэтому либо переопределите логику ExpectedCondition, либо протестируйте другой случай.