python

Selenium для Python. Глава 3. Навигация

  • четверг, 19 февраля 2015 г. в 02:11:47
http://habrahabr.ru/post/250947/

Продолжение перевода неофициальной документации Selenium для Python.
Перевод сделан с разрешения автора Baiju Muthukadan.
Оригинал можно найти здесь.

Содержание:


1. Установка
2. Первые Шаги
3. Навигация
4. Поиск Элементов
5. Ожидания
6. Объекты Страницы
7. WebDriver API
8. Приложение: Часто Задаваемые Вопросы

3. Навигация


Предположительно, первое, что вы захотите сделать с помощью WebDriver, будет переход по ссылке. Обычно для таких целей используют метод get:

driver.get("http://www.google.com")

Метод driver.get перенаправляет к странице URL, поданной в параметре. WebDriver будет ждать пока страница не загрузится полностью (то есть, событие “onload” игнорируется), прежде чем передать контроль вашему тесту или скрипту. Стоит отметить, что если страница использует много AJAX-кода при загрузке, то WebDriver может не распознать, загрузилась ли она полностью. Если необходимо гарантировать полную загрузку страниц, вы можете использовать ожидания (англ. waits).

3.1. Взаимодействие со страницей


Сама по себе возможность переходить по ссылке не так уж полезна. Что действительно хочется сделать, так это взаимодействовать со страницей, или, если быть точным, с элементами HTML на странице. Прежде всего необходимо найти их. WebDriver предоставляет ряд способов для поиска элементов. К примеру, на странице есть элемент, определенный таким образом:

<input type="text" name="passwd" id="passwd-id" />

Его можно найти, используя любой из следующих методов:

element = driver.find_element_by_id("passwd-id")
element = driver.find_element_by_name("passwd")
element = driver.find_element_by_xpath("//input[@id='passwd-id']")

Также вы можете искать адрес гиперссылки по тексту гиперссылки, но будьте бдительны: текст должен совпадать в точности. Также будьте внимательны при использовании XPATH в WebDriver. Если существует больше одного элемента, удовлетворяющего условиям запроса, вернется только первый найденный. Если ничего не будет найдено, будет возбуждено исключение NoSuchElementException.

WebDriver имеет “Объекто-ориентированное” API [Интерфейс прикладного программирования (c англ. application programming interface) — набор готовых методов и свойств, предоставляемых приложением (библиотекой, сервисом) для использования во внешних программных продуктах. API позволяет пользоваться функционалом исходного приложения (библиотеки, сервиса), не вникая в тонкости реализации этого функционала. — Прим. пер.]; мы представляем все типы элементов используя один и тот же интерфейс. Это означает, что хоть вы и видите множество доступных методов, которые можно выбрать при нажатии комбинации клавиш автозаполнения в вашем IDE [Интегрированная среда разработки (англ. Integrated Development Environment) — система программных средств, используемая программистами для разработки программного обеспечения. — Прим. пер.], не все из них будут иметь для вас смысл или не все будут действующими. Не беспокойтесь! WebDriver попытается все исправить, так что если вы вызовете метод, используя его неправильно (например, используете “setSelected()” для “мета” тэга [Мета-теги (англ. meta tags) — HTML-теги, предназначенные для предоставления структурированных метаданных о веб-странице. Как правило, указываются в заголовке HTML-документа. — Прим. пер.]), WebDriver возбудит исключение.

Итак, мы получили элемент. Что вы можете с ним сделать? Первым делом вы захотите ввести какой-нибудь текст в текстовое поле:

element.send_keys("some text")

Также вы можете имитировать нажатие клавиш-стрелок клавиатуры с помощью класса “Keys”:

element.send_keys(" and some", Keys.ARROW_DOWN)

Метод send_keys можно вызвать для любого элемента, который позволяет проверить сочетания клавиш, такие как те, что используются в GMail. Существует побочный эффект, заключающийся в том, что ввод в текстовое поле не очищает его автоматически. Вместо этого то, что вы набираете на клавиатуре, будет дописываться к уже вписанному в поле. Очистить содержимое тектового поля или текстовой области textarea легко — с помощью метода clear:

element.clear()

3.2. Заполнение форм


Мы уже рассмотрели ввод текста в текстовую область или текстовое поле, а как быть с другими элементами? Вы можете попробовать раскрыть раскрывающийся список, после чего можно использовать “setSelected” для выделения тэгов вроде OPTION. Работать с тэгами SELECT не так уж сложно:

element = driver.find_element_by_xpath("//select[@name='name']")
all_options = element.find_elements_by_tag_name("option")
for option in all_options:
    print("Value is: %s" % option.get_attribute("value"))
    option.click()

Такой код найдет первый элемент “SELECT” на странице, и в цикле пройдет по всем тэгам OPTION поочередно, сообщая их значения и поочередно выделяя их.

Как можно заметить, это не самый быстрый способ работы с элементами SELECT. Поддерживаемые вебдрайвером классы содержат один, называющийся “Select”, он предоставляет более удобные способы взаимодействия:

from selenium.webdriver.support.ui import Select
select = Select(driver.find_element_by_name('name'))
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)

Также WebDriver предоставляет возможность снятия выделения со всех элементов выпадающего списка:

select = Select(driver.find_element_by_id('id'))
select.deselect_all()

Этот код снимает выделение со всех тегов OPTION первого тега SELECT на странице.

Допустим, для теста вам необходим список всех выделенных по умолчанию опций. Класс Select предоставляет такое свойство (возвращает список):

select = Select(driver.find_element_by_xpath("xpath"))
all_selected_options = select.all_selected_options

Для получения всех доступных опций используйте:

options = select.options

После того как с заполнением формы будет покончено, вы, вероятно, захотите “сохранить” изменения [submit — отправить, передать, подтвердить — Прим. пер.]. Одним из способов сделать это — найти кнопку “submit” и кликнуть по ней:

# Предположим, ID кнопки равен "submit" :)
driver.find_element_by_id("submit").click()

В качестве альтернативы первому методу можно использовать метод “submit”, доступный для каждого элемента. Если вызвать его для элемента внутри формы, WebDriver пробежится по всей структуре DOM, пока не найдет закрывающийся тег формы, и затем вызовет для нее submit. Если элемент находится не в форме, тогда возбудится исключение NoSuchElementException:

element.submit()

3.3. Перетаскивание


Есть два варианта «перетаскивания» элементов: перемещение элемента на определенную величину, либо перетаскивание его на другой элемент:

element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")

from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element, target)

3.4. Переключение между окнами и фрэймами


Современные веб-приложения редко обходятся без фреймов (frame) и редко когда ограничиваются одним окном. WebDriver поддерживает переключение между именованными окнами с помощью метода “switch_to_window”:

driver.switch_to_window("windowName")

Все вызовы, начинающиеся с driver теперь будут истолкованы как обращенные к полученному окну. Но откуда вам знать имя окна? Взгляните на код javascript или ссылку, которые открывают окно:

<a href="кое_где.html" target="имяОкна">Нажмите сюда, чтобы открыть новое окно</a>

Также вы можете послать “дескриптор окна” методу “switch_to_window()”. Пользуясь этой особенностью, вы можете использовать цикл для перебора всех открытых окон, к примеру, так:

for handle in driver.window_handles:
    driver.switch_to_window(handle)

Еще вы можете переходить между фрэймами (frame или iframes):

driver.switch_to_frame("frameName")

Можно получить доступ к подчиненным фреймам, подавая путь, разделяемый точкой, или можно получить фрейм по индексу:

driver.switch_to_frame("frameName.0.child")

Следующий код перенаправит к фрейму с именем “child”, который в свою очередь принадлежит первому подчиненному фрейму фрейма “frameName”. Пути к фреймам описываются полностью — от верхнего уровня:

driver.switch_to_frame("frameName.0.child")

Когда работа с фреймами будет завершена, необходимо переключиться обратно, к главному фрейму, что может быть сделано следующим образом:

driver.switch_to_default_content()

3.5. Всплывающие окна


Selenium WebDriver из упаковки поддерживает управление всплывающими диалоговыми окнами. После того как вы инициируете запуск, откроется окно, управлять им можно так:

alert = driver.switch_to_alert()

Код вернет объект текущего открытого окна. С этим объектом вы можете принять, отклонить вопрос окна, прочитать его содержимое или даже ввести текст по приглашению окна. Интерфейс взаимодействия со всплывающими окнами работает одинаково хорошо как для предупреждений (alerts), так и для запросов к подтверждению (confirms) и приглашений к вводу (prompts). За дополнительной информацией обратитесь к документации API.

3.6. Навигация: история и локация


Чуть раньше мы упомянули о навигации по ссылке с ипользованием комманды “get” ( driver.get(«www.example.com») ). Как вы уже могли заметить, WebDriver для отдельных случаев предоставляет узконаправленные, специализированные интерфейсы взаимодействия, и навигация не исключение. Чтобы перейти по ссылке, вы можете воспользоваться методом get:

driver.get("http://www.example.com")

Чтобы перейти вперед или назад по истории вкладки:

driver.forward()
driver.back()

Имейте в виду, что этот функционал полностью зависит от используемого драйвера. Вы можете получить непредвиденный результат, если привыкли к поведению какого-либо конкретного браузера, а работаете с другим.

3.7. Куки (cookies)


Прежде, чем мы завершим эту главу, вам возможно будет интересно узнать как использовать куки. Прежде всего, вам необходим домен, использующий куки:

# Перейти на необходимый домен
driver.get("http://www.example.com")

# Установить куки. Следующий cookie действителен для всего домена
cookie = {"ключ": "значение"})
driver.add_cookie(cookie)

# И теперь получим все доступные куки для текущего адреса URL
all_cookies = driver.get_cookies()
for cookie_name, cookie_value in all_cookies.items():
    print("%s -> %s", cookie_name, cookie_value)