Главная / Блог / Selenium WebDriver

Selenium WebDriver
для начинающих

Selenium WebDriver
для начинающих

Smartiqa Article selenium webdriver
Дата: 21 июня 2022
Автор: Евгений Поваров

1. UI тестирование

UI тестирование - имитация действий пользователя — клики, переходы по ссылкам, и другие действия подобного плана. Вопрос о целесообразности большого количества автоматизированных тестов, работающих через пользовательский интерфейс, является весьма спорным, потому что:
  1. Автоматизированные UI тесты очень хрупкие. Как правило, даже косметические изменения в коде тестируемого приложения(например, смена имени checkbox) приводят к необходимости внесения соответствующих изменений к код тестов. В итоге, поддержка обширных UI тестов является задачей достаточно трудоемкой, а для приложений с активно развивающимся графическим интерфейсом - даже бессмысленной.
  2. UI автотесты долгие. UI тесты практически всегда проигрывают в скорости тестам, работающим через API. Прогрузить страницу, обработать событие web-элемента - все требует времени, тогда как работа с API-функциями за счет своей низкоуровневости дает возможность проверить тот же самый функционал в разы быстрее.

Однако даже с учетом перечисленных недостатков, никто не будет отрицать тот факт, что клацать по одним и тем же кнопкам web-страницы каждый цикл регрессии, да еще и в разных браузерах и на разных ОС - дело нудное и так и просится, чтобы его передали в руки автоматизации. Поэтому вывод такой: UI автотестам - быть!

2. Продукты Selenium

Selenium – это проект, в рамках которого разрабатывается серия программных продуктов с открытым исходным кодом, предназначенных для автоматизации действий веб-браузера.

На что обратить внимание?
  1. Selenium - это не один продукт, а их совокупность.
  2. Selenium относится к open source продуктам.
  3. Selenium предназначен для работы с веб-браузером. В большинстве случаев используется для тестирования Web-приложений, но этим не ограничивается.

В состав проекта входят следующие продукты:
  1. Selenium WebDriver. Программная библиотека для управления браузерами. Эта библиотека используется для отправки HTTP запросов драйверу, в которых указано действие, которое должен совершить браузер в рамках текущей сессии. Примерами таких команд могут быть команды нахождения элементов по локатору, переход по ссылкам, парсинг текста страницы/элемента, нажатие кнопок или переход по ссылкам на странице веб-сайта. Основной продукт, разрабатываемый в рамках проекта Selenium. Подробнее будет рассмотрен ниже.
  2. Selenium RC. Предыдущая версия библиотеки для управления браузерами. Сейчас она находится в законсервированном состоянии, не развивается и даже известные баги не исправляются. А всем, кто сталкивается с ограничениями Selenium RC, предлагается переходить на использование WebDriver. Иногда Selenium RC называется также Selenium 1.0, тогда как WebDriver называется Selenium 3.0. С технической точки зрения WebDriver не является результатом эволюционного развития Selenium RC, они построены на совершенно разных принципах и у них практически нет общего кода. Объединяет их лишь тот факт, что обе реализации были сделаны в рамках проекта Selenium.
  3. Selenium Server. Сервер, который позволяет управлять браузером с удалённой машины, по сети. Сначала на той машине, где должен работать браузер, устанавливается и запускается сервер. Затем на другой машине запускается программа, которая, используя специальный драйвер RemoteWebDriver, соединяется с сервером и отправляет ему команды. Он в свою очередь запускает браузер и выполняет в нём эти команды, используя драйвер, соответствующий этому браузеру.
  4. Selenium Grid. Кластер, состоящий из нескольких Selenium-серверов. Он предназначен для организации распределённой сети, позволяющей параллельно запускать много браузеров на большом количестве машин. Selenium Grid имеет топологию «звезда», то есть в его составе имеется выделенный сервер, который носит название хаб или коммутатор, а остальные сервера называются ноды или узлы. Сейчас физически продукт один – Selenium Server, но у него есть несколько режимов запуска: он может работать как самостоятельный сервер, как коммутатор кластера, либо как узел кластера, что определяется параметрами запуска.
  5. Selenium IDE. Плагин к браузерам Firefox и Google Chrome, который может записывать действия пользователя, воспроизводить их, а также генерировать код для WebDriver или Selenium RC, в котором выполняются те же самые действия. Другими словами, это Selenium-рекордер.

Называть просто словом Selenium любой из этих пяти продуктов, вообще говоря, неправильно, хотя так часто делают, если
1) из контекста понятно, о каком именно из продуктов идёт речь, или если
2) речь идёт о нескольких продуктах одновременно, или обо всех сразу.

3. Selenium WebDriver

Selenium WebDriver - это семейство драйверов для различных браузеров, а также набор клиентских библиотек на разных языках, позволяющих работать с этими драйверами.
Проект Selenium
Проект Selenium
В рамках проекта Selenium разрабатываются драйверы для браузеров Firefox, Internet Explorer и Safari, а также драйверы для мобильных браузеров Android и iOS. Драйвер для браузера Google Chrome разрабатывается в рамках проекта Chromium, а драйвер для браузера Opera (включая мобильные версии) разрабатывается компанией Opera Software. Поэтому они формально не являются частью проекта Selenium, распространяются и поддерживаются независимо. Но логически, конечно, можно считать их частью семейства продуктов Selenium. Аналогичная ситуация и с клиентскими библиотеками – в рамках проекта Selenium разрабатываются библиотеки для языков Java, .Net (C#), Python, Ruby, JavaScript. Все остальные реализации не имеют отношения к проекту Selenium, хотя, возможно, в будущем, какие-то из них могут влиться в этот проект.

Исходя их этого, становится очевидным, что Selenium WebDriver по сути не является готовым инструментом для автоматизации тестирования. По своей сущности Selenium WebDriver представляет собой:
  1. спецификацию программного интерфейса для управления браузером,
  2. референсные реализации этого интерфейса для нескольких браузеров,
  3. набор клиентских библиотек для этого интерфейса на нескольких языках программирования.

WebDriver – это драйвер браузера, то есть не имеющая пользовательского интерфейса программная библиотека, которая позволяет различным другим программам взаимодействовать с браузером, управлять его поведением, получать от браузера какие-то данные и заставлять браузер выполнять какие-то команды. Исходя из этого определения, ясно, что WebDriver не имеет прямого отношения к тестированию. Он всего лишь предоставляет автотестам доступ к браузеру. На этом его функции заканчиваются.

Кто занимается остальным?
  1. Структурирование, группировку и запуск тестов, а также генерацию отчётов о тестировании, обеспечивает фреймворк тестирования, такой как JUnit или TestNG для Java, NUnit или Gallio для .Net, RSpec или Cucumber для Ruby и так далее.
  2. Разработка тестов ведётся в среде Eclipse, Intellij IDEA, Visual Studio, RubyMine и так далее.
  3. Сборка осуществляется посредством Maven, Gradle, Ant, NAnt,Rake и так далее.
  4. Запуск тестов по расписанию и публикацию отчётов выполняет сервер непрерывной интеграции – Jenkins, CruiseControl, Bamboo, TeamCity и так далее.

И всё это – самостоятельные инструменты, не имеющие отношения к проекту Selenium. Разумеется, WebDriver может использоваться не только при тестировании. Ему вообще безразлично, кто и зачем хочет управлять браузером. Вы можете автоматизировать какие-то рутинные задачи. Можете сделать ботов, которые будут флудить в форумах. Можете сделать скрипт, который автоматически снимает скриншоты для документации. Всё что угодно. Драйверу всё равно. Он всего лишь предоставляет доступ к браузеру.

При этом интерфейс самого WebDriver довольно скуден. Почему? Потому, что WebDriver – это:
  1. драйвер браузера, то есть библиотека достаточно низкого уровня абстракции,
  2. стандарт на интерфейс управления браузером, то есть минимальный набор команд, который должен быть реализован в каждом браузере.

При разработке Selenium WebDriver изначально была поставлена цель – не включать в него ничего лишнего. Стандартный интерфейс управления браузером должен быть простым и стабильным. Набор команд последовательно сокращался, были выброшены такие «повышающие удобство использования» команды как check, uncheck (для чекбоксов), select (для выпадающих списков). Все они сводятся к более простой команде click, и поэтому они лишние.

Но зато благодаря этой примитивности интерфейса сейчас для интерфейса WebDriver имеются реализации клиентских библиотек на Java, C#, Ruby, Python, JavaScript, PHP, Perl. И благодаря той же самой простоте WebDriver прекрасно интегрируется с любыми другими инструментами, встраивается в любой стек. В этом секрет его популярности и быстрого распространения – он не пытается «победить» другие инструменты, вместо этого он интегрируется с ними.

Задачу же удобства использования должны решать расширения, построенные на базе Selenium WebDriver. Именно они должны предоставлять расширенный набор команд, реализуя эти команды через примитивный интерфейс WebDriver. В дистрибутиве Selenium имеется класс Select, предназначенный для работы с выпадающими списками, который является наглядной демонстрацией того, как должны строиться расширения.

Постепенно появляются библиотеки, которые строятся на базе Selenium WebDriver и предоставляют более высокий уровень абстракции: Selenide, fluent-selenium, watir-webdriver, Thucidides. Популярные фреймворки для проектирования тестов позволяют наряду с другими драйверами использовать WebDriver. Среди таких фреймворков можно упомянуть Robot Framework, Capybara и тот же Thucidides. Число таких расширений и инструментов будет расти, сложность тоже. Так что вскоре может так случиться, что вы, используя какой-то инструмент, будете выполнять тесты, даже не подозревая о том, что взаимодействие с браузером осуществляется через драйвер Selenium WebDriver.
Подведем итог
Итак, что нужно для работы с Selenium WebDriver?
  1. Браузер, работу которого пользователь хочет автоматизировать. Это реальный браузер определенной версии, установленный на определенной ОС и имеющий свои настройки (по умолчанию или кастомные).
  2. Для управления браузером совершенно необходим driver браузера. Driver на самом деле является веб-сервером, который запускает браузер и отправляет ему команды, а также закрывает его. У каждого браузера свой driver. Связано это с тем, что у каждого браузера свои отличные команды управления и реализованы они по-своему.
  3. Скрипт/тест, который содержит набор команд на определенном языке программирования для драйвера браузера. Такие скрипты используют Selenium Webdriver bindings (готовые библиотеки), которые доступны пользователям на различных языках.

4. Selenium WebDriver API

Selenium WebDriver (он же Selenium 3.0) содержит множество замечательных возможностей и улучшений по сравнению с Selenium RC (он же Selenium 1.0). Самое главное изменение новой версии - это интеграция WebDriver API, альтернативного, упрощенного программного интерфейса, который избавлен от недостатков, характерных для Selenium RC. Цель создания WebDriver API - разработать объектно-ориентированный API, поддерживающий большее количество браузеров и лучше решающий проблемы тестирования современных веб-приложений. WebDriver API в свою очередь не привязан ни к каким тестовым фреймворкам, что позволяет использовать любые фреймворки модульного тестирования.

Основными понятиями в Selenium Webdriver являются:
  1. Webdriver - самая важная сущность, ответственная за управление браузером. Основной ход скрипта/теста строится именно вокруг экземпляра этой сущности.
  2. Webelement - вторая важная сущность, представляющая собой абстракцию над веб элементом (кнопки, ссылки, поля ввода и др.). Webelement инкапсулирует методы для взаимодействия пользователя с элементами и получения их текущего статуса.

Какие действия с браузером можно производить посредством Webdriver API?
Что можно делать с WebElement?
Следующий пример выполняет следующую последовательность действий:
  1. Создает драйвер для браузера Mozilla Firefox.
  2. Переходит на сайт Google.
  3. Ищет поле для ввода поискового запроса.
  4. Вводит тестовую фразу.
  5. Отправляет запрос.
  6. Закрывает браузер.
Пример, Ruby
driver = Selenium::WebDriver.for :firefox
driver.navigate.to "http://google.com"
element = driver.find_element(name: 'q')
element.send_keys "Hello Google!"
element.submit
driver.quit

Читайте также

5. Локаторы

Большая часть работы с Selenium WebDriver - это работа с веб-элементами (WebElements). WebElements - ни что иное, как DOM объекты, находящиеся на веб странице. А для того, чтобы осуществлять какие-то действия над DOM объектами, необходимо их точным образом определить(найти). Для поиска необходимых элементов страницы в Selenium WebDriver используются локаторы.

Локатор - это строка, уникально идентифицирующая UI-элемент. Когда вы делаете клик мышкой, ввод текста и прочие действия, вы эти действия выполняете над вполне конкретным объектом. Selenium поступает так же. Но поскольку он не умеет читать ваши мысли, то ему надо четко указать объект, для которого надо применить то или иное действие.
Пример поиска по локатору
driver.find_element(<тип_локатора>: <значение_локатора>)
Таким образом в Webdriver определяется нужный элемент. Рассмотрим основные типы локаторов:

1. Id.Соответствует элементу, у которого атрибут id равен заданному значению. Данный вид локаторов является одним из самых быстрых в нахождении и одним из самых уникальных. Это связано с тем, что в DOM-структуре ссылки на элементы, у которых задан ID, хранятся в отдельной таблице, и через JScript (собственно именно через него осуществляется доступ к элементам на конечном уровне) обращение к элементам по ID идет достаточно короткой инструкцией.

2. Name. Соответствует элементу, у которого атрибут name равен заданному значению. Эффективно применяется при работе с полями ввода формы: 1) кнопки, 2) текстовые поля, 3) выпадающие списки. Как правило, значения элементов формы используются в запросах, которые идут на сервер и как раз атрибут name в этих запросах ставит в соответствие поле и его значение. Данный тип локаторов тоже является достаточно быстрым в нахождении, но менее уникальным, так как на странице может быть несколько форм, у которых могут быть элементы с одинаковым именем.

3. Class. Соответствует элементу, у которого атрибут class равен заданному значению. Как правило, является еще менее уникальным, чем предыдущие локаторы.

4. Link. Специально для ссылок используется отдельно зарезервированный тип локаторов, который находит нужную ссылку по ее тексту. Это сделано отчасти потому, что ссылки как правило не имеют таких атрибутов как ID или name. У ссылки есть фиксированная часть и есть часть, которая может варьироваться. В этом случае можно использовать wildcards, в частности '*'.

5. XPath. Наиболее универсальный тип локаторов. Как XPath формируется? HTML, как и его более обобщенная форма - XML, представляет собой различное сочетание тегов, которые могут содержать вложенные теги, а те в свою очередь тоже могут содержать теги и т.д. То есть, выстраивается определенная иерархия, наподобие структуры каталогов в файловой системе. И задача XPath - отразить подобный путь к нужному элементу, с учетом иерархии. Например, XPath вида A/B/C/D указывает на некоторый элемент с тегом D, который находится внутри тега C, а тот в свою очередь - внутри тега B, который находится внутри тега A, который находится на самом верхнем уровне иерархии.

Если брать использование XPath в Selenium WebDriver, то там зачастую полный путь указывать не нужно, более того, вредно, особенно, если вложенность тега нужного элемента достаточно высока. Как правило, удобно указывать путь, начиная с некоторого промежуточного элемента, пропуская теги более высокого порядка.

У XPath есть много удобств, но есть и основной недостаток - низкая скорость нахождения объекта. В частности, с подобной проблемой можно столкнуться при работе с IE, так как при работе с XPath под IE используются JScript-библиотеки, которые не отличаются высокой скоростью выполнения. В таких случаях рекомендуется воспользоваться CSS-локаторами, но в некоторых случаях от XPath уйти не получится.

6. CSS. Данный тип локаторов основан на описаниях таблиц стилей (CSS), соответственно и синтаксис такой же. В отличие от локаторов по ID, по имени или по тексту ссылки, данный тип локаторов может учитывать иерархию объектов, а также значения атрибутов, что делает его ближайшим аналогом XPath. А в силу того, что объект находится по данному локатору быстрее, чем XPath, рекомендуется прибегать к помощи CSS вместо XPath. В CSS локаторе дочерний элемент отделяется символом '>':
Примеры локаторов
XPath: //div/a
CSS: div > a
Так же в CSS локаторах используется символ '#' для случаев, когда идет поиск по уникальному для страницы ID:
Примеры локаторов
XPath: //div[@id='example']
CSS: #example
И знак . для поиска уникального имени класса:
Примеры локаторов
XPath: //div[@class='example']
CSS: .example
Рассмотрим варианты локаторов для поиска следующего элемента:
Пример web-элемента для поиска
Пример web-элемента для поиска
Локаторы
# 1. Id локатор
driver.find_element(id: 'editPageLink')
	
# 2. Name локатор
driver.find_element(name: 'Edit')

# 3. Class локатор
driver.find_element(class: 'aui-icon aui-iconfont-edit')
	
# 4. Link локатор
driver.find_element(link: 'Edit134')
driver.find_element(link: 'Edit*')
	
# 5. XPath локатор
# Обратите внимание на начало данной записи. Строка '//' означает, что поиск элемента начинается с некоторого произвольного места.
driver.find_element(xpath: '//*[@id="editPageLink"'])
	
# 6. CSS локатор
# Обратите внимание на символ #, который, как уже упоминалось ранее, указывает на поиск по уникальному Id элемента.
driver.find_element(css: 'a[id='editPageLink']')
# или
driver.find_element(css: '#editPageLink')
Получается, что, с одной стороны, разных механизмов поиска достаточно много, с другой стороны, сложные языки запросов (CSS и XPath) дают большую свободу в построении локаторов. Поэтому для каждого элемента можно построить локатор, который его находит, многими разными способами.

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

Исходя из этого требования, сформулируем необходимые свойства хорошего локатора:

  1. Хороший локатор должен быть устойчив к изменениям. Это, пожалуй, самое главное. Если после небольшого изменения тестируемого приложения все тесты приходится переделывать – это просто катастрофа. Есть изменения, которые изначально заложены в приложение и могут определяться его настройками – локализация, расположение блоков на странице (например, включить/отключить рекламные блоки), "шкурки" (skins) и прочее. Локаторы нужно сразу проектировать так, чтобы они работали с разными вариантами настроек. Есть изменения, которые случатся в будущем. Тут заранее подготовиться на 100% нельзя, но можно хотя бы постараться предугадать, с чем эти изменения будут связаны. Например, если сейчас пока приложение одноязычное, но есть планы выхода на новые рынки – вероятно, добавятся разные локализации, поэтому поиск элементов по тексту перестанет работать. Если дизайнер скажет, что кнопки нужно сделать не прямоугольными, а закруглёнными – поменяются стили и вёрстка кнопок, поэтому полагаться при поиске на конкретный стиль рискованно, лучше выбрать какие-то более стабильные признаки. Конечно, при массированном изменении тестируемого приложения противостоять изменениям в тестах не удастся, но это вполне ожидаемо. Но незначительные изменения не должны приводить к разрушению тестов.
  2. Хороший локатор должен быть понятным. Вы разрабатываете тесты, Вы помните структуру страницы и можете легко представить, что найдётся по тому или иному локатору. Но через несколько месяцев память будет уже не так свежа, и, глядя на запутанный локатор, будет уже не так легко догадаться, что он ищет, или хотя бы что он должен искать. Конечно, можно добавить комментарии и пояснения. Но лучше всё таки стремиться к выразительности и понятности самих локаторов. Они должны быть простыми и осмысленными. Тогда читать и понимать старые тесты будет легко и приятно.

Читайте также

6. Ожидания

Ожидания - непременный атрибут любых UI тестов для динамических приложений. Нужны они для синхронизации работы приложения и тестового скрипта. Скрипт выполняется намного быстрее реакции приложения на команды, поэтому часто в скриптах необходимо дожидаться определенного состояния приложения для дальнейшего с ним взаимодействия. Самый простой пример - переход по ссылке и нажатие кнопки:
Нажатие на кнопку, Ruby
driver.navigate.to "http://google.com"
element = driver.find_element(name: 'q')
element.send_keys "Hello WebDriver!"
element.submit
В данном случае необходимо дождаться, когда появится поле ввода с name = 'q', и только потом совершать действия(вводить поисковый запрос). Для этого и существуют ожидания. Какими бывают ожидания:
  1. Неявные ожидания,
  2. Явные ожидания.

Рассмотрим оба типа ожиданий подробнее:
1) Неявные ожидания(от англ. Implicit Waits). Конфигурируют экземпляр WebDriver делать многократные попытки найти элемент (элементы) на странице в течении заданного периода времени, если элемент не найден сразу. Tолько по истечении этого времени WebDriver выдаст ошибку.
Неявное ожидание, Ruby
driver = Selenium::WebDriver.for :firefox
driver.manage.timeouts.implicit_wait = 3 # seconds
Неявные ожидания обычно настраиваются сразу после создания экземпляра WebDriver и действуют в течении всей жизни этого экземпляра, хотя переопределить их можно в любой момент.
2) Явные ожидания(от англ. Explicit Waits). Код, который ждет наступления какого-то события, прежде чем продолжит выполнение команд скрипта. Такое ожидание срабатывает один раз в указанном месте.
Явное ожидание, Ruby
wait = Selenium::WebDriver::Wait.new(timeout: 3)
wait.until { driver.find_element(id: "cheese").displayed? }
21 ИЮНЯ / 2022
Как вам материал?

Читайте также