понедельник, 4 марта 2013 г.

Работа с Selenium Web Driver

Структура статьи:
1 Введение
2 Предварительные настройки для использования Selenium WebDriver
3 Классы, их методы и свойства
    3.1 <class 'selenium.webdriver.firefox.webdriver.WebDriver'>
          3.1.1 Метод find_element_by_xpath() - поиск элемента web-страницы по xPath
          3.1.2 Метод get() - переход по URL
          3.1.3 Метод get_screenshot_as_file() - снятие скриншота web-страницы в .png-файл
          3.1.4 Метод switch_to_alert() - переключение на окно сообщения
    3.2 <class 'selenium.webdriver.remote.webelement.WebElement'>
           3.2.1 Свойство text  - возвращает текстовое значение элемента web-страницы
           3.2.2 Свойство tag_name - имя тега элемента web-страницы
           3.2.3 Метод clear() - очистка текстового содержимого элемента
           3.2.4 Метод get_attribute() - получить имя некоторого атрибута для тега элемента web-страницы
           3.2.5 Метод send_keys() - печать в поля ввода
           3.2.6 Метод click() - щелчок левой кнопки на элементе
           3.2.7 Метод is_displayed() - проверка видимости элемента
    3.3 <class 'selenium.webdriver.support.wait.WebDriverWait'>
           3.3.1 Метод until() - проверка выполнения логического условия
    3.4 <class 'selenium.webdriver.support.select.Select'>
          3.4.1 Метод select_by_index() - выбор строк в селекторе по индексу
          3.4.2 Метод select_by_value() - выбор строк в селекторе по значению
    3.5 <class 'selenium.webdriver.common.action_chains.ActionChains'>
          3.5.1 Метод move_to_element() - перемещение курсора мыши на элемент
          3.5.2 Метод perform() - выполнение сохраненных действий

Введение

Selenium Web Driver (далее WD), входящий в Selenium 2.0, - это библиотека, эмулирующая браузер и позволяющая работать с элементами web-форм. В отличие от Selenium Server не требует предварительного запуска сервера, обрабатывающего команды Selenium.
Для идентификации элементов на web-форме, чаще всего при работе с Selenium используют xPath, с примерами можно ознакомиться здесь:
http://forworktests.blogspot.ru/2013/03/xpath-web.html
Некоторые ссылки:

Предварительные настройки для использования Selenium WebDriver

Проверялось для Windows 7 x64, Python 3.2 x64. Патчи файлов касаются только Python 3.2, для Python 2.7 достаточно только первого шага.
  1. Для установки Selenium WebDriver для Python можно:
    a) либо скачать пакет selenium-*.*.*.tar.gz из http://pypi.python.org/pypi/selenium#downloads, распаковать, затем установить через setup:
    python setup.py install

    b) либо установить через pip (бинарники для pip под Windows можно скачать на http://www.lfd.uci.edu/~gohlke/pythonlibs/):
    pip install -U selenium
  2. Т.к. Selenium WD изначально написан для Python 2.* его нужно портировать на Python 3.*. Для этого можно воспользоваться инструкцией http://habrahabr.ru/post/143355/
    a) скачать скрипт pyselenium.py http://code.google.com/p/pyselenium/downloads/list
    b) в тот же каталог со скриптом скачать пакет пакет selenium-*.*.*.tar.gz из http://pypi.python.org/pypi/selenium#downloads
    c) выполнить команду (для версии файла selenium-2.25.0, аналогично для других):
    python pyselenium.py selenium-2.25.0.tar.gz
    Скрипт сначала скопирует файлы архива в каталоги Python, запустит утилиту 2to3.py для конвертации файлов, после чего вставит в нужные места encode() строки перед отправкой по сети и decode() в строку полученных данных. 
  3. Для проверки правильной установки Selenium WD:
    >>>from selenium.webdriver import Firefox
    >>>driver = Firefox()
    >>>driver.get('http://google.ru/')
    В результате должен открыться браузер ff и произойти переход на google.ru.
  4. Если при попытке открытия браузера будут возникать ошибки связанные с кодировкой, то значит, что скрипт pyselenium.py по какой-то причине отработал не до конца. В этом случае нужно вручную заменить в файле
    <Python32_Path>\Lib\site-packages\<selenium-*.*.*-py3.2.egg>\selenium\webdriver\remote\remote_connection.py
    все строки, указанные в скрипте pyselenium.py (в словаре для замены replace_dict):
    http://code.google.com/p/selenium/issues/attachmentText?id=2139&aid=21390005000&name=pyselenium.py
  5. Для использования функции WD снятия скриншотов в .png-файл, нужно заменить в файле
    <Python32_Path>\Lib\site-packages\<selenium-*.*.*-py3.2.egg>\selenium\webdriver\remote\webdriver.py,
    в методе get_screenshot_as_file из класса WebDriver, строку
    f.write(base64.decodestring(png))
    на строку
    f.write(base64.decodestring(png.encode())).

Классы, их методы и свойства

Основные импорты:
from selenium import webdriver # работа с браузером
from selenium.webdriver.support.ui import WebDriverWait # ожидания различных событий
from selenium.webdriver.support.ui import Select # работа со списками
from selenium.webdriver.common.action_chains import ActionChains # различные действия
Примеры запуска браузера:
ffp = webdriver.FirefoxProfile(ff_Profile) # Установка профиля мозиллы, где ff_Profile - это путь к каталогу с профилем.
page = webdriver.Firefox(firefox_profile=ffp, timeout=5)) # page - экземпляр класса <class 'selenium.webdriver.firefox.webdriver.WebDriver'>. Фактически - это окно браузера.
page.maximize_window() # разворачивание окна браузера во весь экран
Далее будут представлены некоторые часто встречающиеся в web-проектах команды Selenium WD из различных классов и примеры их использования.

<class 'selenium.webdriver.firefox.webdriver.WebDriver'>

Список методов и свойств:
['NATIVE_EVENTS_ALLOWED', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_unwrap_value', '_wrap_value', 'add_cookie', 'back', 'close', 'create_web_element', 'current_url', 'current_window_handle', 'delete_all_cookies', 'delete_cookie', 'desired_capabilities', 'execute', 'execute_async_script', 'execute_script', 'find_element', 'find_element_by_class_name', 'find_element_by_css_selector', 'find_element_by_id', 'find_element_by_link_text', 'find_element_by_name', 'find_element_by_partial_link_text', 'find_element_by_tag_name', 'find_element_by_xpath', 'find_elements', 'find_elements_by_class_name', 'find_elements_by_css_selector', 'find_elements_by_id', 'find_elements_by_link_text', 'find_elements_by_name', 'find_elements_by_partial_link_text', 'find_elements_by_tag_name', 'find_elements_by_xpath', 'firefox_profile', 'forward', 'get', 'get_cookie', 'get_cookies', 'get_screenshot_as_base64', 'get_screenshot_as_file', 'get_window_position', 'get_window_size', 'implicitly_wait', 'maximize_window', 'name', 'orientation', 'page_source', 'quit', 'refresh', 'save_screenshot', 'set_page_load_timeout', 'set_script_timeout', 'set_window_position', 'set_window_size', 'start_client', 'start_session', 'stop_client', 'switch_to_active_element', 'switch_to_alert', 'switch_to_default_content', 'switch_to_frame', 'switch_to_window', 'title', 'window_handles']

Метод find_element_by_xpath() - поиск элемента web-страницы по xPath

Примеры использования:
# Обращение к элементам страницы по xpath:
login = page.find_element_by_xpath("//input[@id='UserName']")
pwd = page.find_element_by_xpath("//input[@id='Password']")
# Печать в поля ввода:
login.send_keys(self.login)
pwd.send_keys(self.password)
# Или можно сразу:
page.find_element_by_xpath("//*[@type='submit']").click()

Метод get() - переход по URL

Примеры использования:
page = webdriver.Firefox(firefox_profile=ffp, timeout=5)) # открываем браузер
page.get('ya.ru') # Переходим на Яндекс.
# Переходим по ссылке, содержащейся в теге а, для которого есть текстовое описание 'Настройка синхронизации':
page.get(page.find_element_by_xpath("//a[contains(text(),'Настройка синхронизации')]").get_attribute('href'))

Метод get_screenshot_as_file() - снятие скриншота web-страницы в .png-файл

Примеры использования:
# Снять скриншот с текущего экземпляра браузера:
ffp = webdriver.FirefoxProfile(ff_Profile) # указываем профиль
page = webdriver.Firefox(firefox_profile=ffp, timeout=5)) # открываем браузер
page.get_screenshot_as_file('full_path.png') # делаем скриншот

Метод switch_to_alert() - переключение на окно сообщения

Примеры использования:
alert = page.switch_to_alert() # Переключаемся на окно алерта. switch_to_alert возвращает класс Alert:
alert.text # Возвращает текст алерта.
alert.dismiss() # Выполняет действие "отказаться" от алерта.
alert.accept() # Выполняет действие "принять" алерт.
alert.send_keys() # Выполняет действие "напечатать" в окне алерта.

<class 'selenium.webdriver.remote.webelement.WebElement'>

Список методов и свойств:
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_execute', '_upload', 'clear', 'click', 'find_element', 'find_element_by_class_name', 'find_element_by_css_selector', 'find_element_by_id', 'find_element_by_link_text', 'find_element_by_name', 'find_element_by_partial_link_text', 'find_element_by_tag_name', 'find_element_by_xpath', 'find_elements', 'find_elements_by_class_name', 'find_elements_by_css_selector', 'find_elements_by_id', 'find_elements_by_link_text', 'find_elements_by_name', 'find_elements_by_partial_link_text', 'find_elements_by_tag_name', 'find_elements_by_xpath', 'get_attribute', 'id', 'is_displayed', 'is_enabled', 'is_selected', 'location', 'parent', 'send_keys', 'size', 'submit', 'tag_name', 'text', 'value_of_css_property']

Свойство text  - возвращает текстовое значение элемента web-страницы

Примеры использования:
# Получение текстового значения некоторой ссылки, искомой по xpath:
link = page.find_element_by_xpath("//tr[@class='odd-row']/td/a")
a = link.text
# Или можно сразу получить это значение:
b = page.find_element_by_xpath("//tr[@class='odd-row']/td/a").text

Свойство tag_name - имя тега элемента web-страницы

Примеры использования:
# Получение имени тега, для некоторого элемента, найденного по xpath:
element = page.find_element_by_xpath("//div[@id='main']/..//input[@id='Title']")
a = element.tag_name # получим имя тега, в данном случае a = 'input'
# Или можно сразу:
b = page.find_element_by_xpath("//div[@id='main']/..//input[@id='Title']").tag_name

Метод clear() - очистка текстового содержимого элемента

Примеры использования:
# Удаляем текст, введенный в input:
page.find_element_by_xpath("//input[@id='Login']").clear()

Метод get_attribute() - получить имя некоторого атрибута для тега элемента web-страницы

Примеры использования:
# 1. Получение значения атрибута, для некоторого тега найденного по xpath:
tag = page.find_element_by_xpath("//div[@id='main']/..//input[@id='Title']")
a = tag.get_attribute('value') # Получаем значение атрибута 'value' для тега input
# Или можно сразу:
b = page.find_element_by_xpath("//div[@id='main']/..//input[@id='Title']").get_attribute('value')
# 2. Переход по ссылке для пункта меню "Настройка синхронизации":
page.get(page.find_element_by_xpath("//a[contains(text(),'Настройка синхронизации')]").get_attribute('href'))

Метод send_keys() - печать в поля ввода

Примеры использования:
# Ввод текста в поле формы, найденного по xPath:
login = page.find_element_by_xpath("//input[@id='UserName']")
login.send_keys('my_login')
# Или можно сразу:
page.find_element_by_xpath("//input[@id='UserName']").send_keys('my_login')

Метод click() - щелчок левой кнопки на элементе

Примеры использования:
# Щелчок левой кнопки мыши на иконку выпадающего списка, найденную по xpath:
element = page.find_element_by_xpath("//img[@id='osSelect']")
element.click()
# Или можно сразу:
page.find_element_by_xpath("//img[@id='osSelect']").click()

Метод is_displayed() - проверка видимости элемента

Примеры использования:
# 1. Определение того, является ли элемент, найденный по xpath, видимым на форме:
element = page.find_element_by_xpath("//div[@id='treeWrapper']") # В данном случае определяется, виден ли выпадающий список
flag = element.is_displayed() # flag = True - если элемент видим, flag = False - если нет
# Или можно сразу:
flag = page.find_element_by_xpath("//div[@id='treeWrapper']").is_displayed()
# 2. Использование в блоке ожидания появления элемента на форме:
WebDriverWait(page, 5).until(
    lambda element: element.find_element_by_xpath("//div[@id='treeWrapper']").is_displayed(),
    'Timeout while waiting popup-tree list.') # Ждём 5 сек. пока не появится выпадающий список, иначе - пишем сообщение.

<class 'selenium.webdriver.support.wait.WebDriverWait'>

Список методов и свойств:
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'until', 'until_not']

Метод until() - проверка выполнения логического условия

Примеры использования:
opTimeout = 5 # задаём таймаут 5 сек.
# Ждем появления некоторых элементов на форме, найденных по xpath, с указанным таймаутом. Until() принимает в качестве параметра логическое условие.
# В данном случае - ожидается появление надписи 'Основные параметры' и кнопки Сохранить внизу страницы. Если они не появятся, в лог запишется сообщение:
WebDriverWait(page, opTimeout).until(lambda element: 
    (element.find_element_by_xpath("//div[@id='main']/..//div[contains(text(), 'Основные параметры')]")) and
    (element.find_element_by_xpath("//div[@id='main']/..//input[@id='save']")), 'Таймаут! Элементы на форме не появились!')

<class 'selenium.webdriver.support.select.Select'>

Список методов и свойств:
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_escapeString', '_get_longest_token', '_setSelected', '_unsetSelected', 'all_selected_options', 'deselect_all', 'deselect_by_index', 'deselect_by_value', 'deselect_by_visible_text', 'first_selected_option', 'options', 'select_by_index', 'select_by_value', 'select_by_visible_text']

Метод select_by_index() - выбор строк в селекторе по индексу

Примеры использования:
# Обращение к существующей строке селектора по индексу, если селектор найден по xPath:
Select(page.find_element_by_xpath("//select[@id='SelectedAttackType']")).select_by_index(1) # Выбирает 2-ю строку в селекторе (отсчет с нуля).

Метод select_by_value() - выбор строк в селекторе по значению

Примеры использования:
# Обращение к существующей строке селектора по значению атрибута value, если селектор найден по xPath:
Select(page.find_element_by_xpath("//select[@id='SelectedStatusId']")).select_by_value(2) # Выбирает строку в селекторе с value=2.

<class 'selenium.webdriver.common.action_chains.ActionChains'>

Список методов и свойств:
['__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_actions', '_driver', 'click', 'click_and_hold', 'context_click', 'double_click', 'drag_and_drop', 'drag_and_drop_by_offset', 'key_down', 'key_up', 'move_by_offset', 'move_to_element', 'move_to_element_with_offset', 'perform', 'release', 'send_keys', 'send_keys_to_element']

Метод move_to_element() - перемещение курсора мыши на элемент

Примеры использования:
# Переместить мышь на элемент, найденный по xPath:
administrationTab = page.find_element_by_xpath("//ul[@class='dropdown']/li[11]/div") # Ищем выпадающее меню.
hover = ActionChains(page).move_to_element(administrationTab) # Действие по перемещению мыши сохраняется в объекте ActionChains. Затем нужно использовать метод perform()

Метод perform() - выполнение сохраненных действий

Примеры использования:
# Переместить мышь на пункт меню и подождать выпадающее меню:
administrationTab = page.find_element_by_xpath("//ul[@class='dropdown']/li[11]/div") # Ищем выпадающее меню.
hover = ActionChains(page).move_to_element(administrationTab) # Сохраняем действие в объекте ActionChains.
hover.perform() # применяем действие
# Ждем, пока выпадающее меню не откроется, то есть не станет видимой одна из его ссылок:
WebDriverWait(page, opTimeout).until(
    lambda el: el.find_element_by_xpath("//a[@href='/polidon2/ScheduledEntity']").is_displayed(),
    'Timeout while we are wait pop-up menu.')