Selenium eclipse chrome настройка с нуля

Обновлено: 06.07.2024

В этой статье рассматривается создание достаточного простого автотеста. Статья будет полезна начинающим автоматизаторам.

Материал изложен максимально доступно, однако, будет значительно проще понять о чем здесь идет речь, если Вы будете иметь хотя бы минимальные представления о языке Java: классы, методы, etc.

  • установленная среда разработки Intellij IDEA (является самой популярной IDE, для большинства случаев достаточно бесплатной версии Community Edition);
  • установленные Java (jdk/openjdk) и Maven, прописанные в системные окружения ОС;
  • браузер Chrome и chromedriver — программа для передачи команд браузеру.

Создание проекта

Запустим Intellij IDEA, пройдем первые несколько пунктов, касающихся отправки статистики, импорта проектов, выбора цветовой схемы и т.д. — просто выберем параметры по умолчанию.

В появившемся в конце окне выберем пункт «Create New Project», а в нем тип проекта Maven. Окно будет иметь вид:

image

  • Maven — это инструмент сборки Java проектов;
  • Project SDK — версия Java, которая установлена на компьютере;
  • Create from archetype — это возможность создавать проект с определенным архетипом (на данном этапе данный чекбокс отмечать не нужно).

Нажмем «Next». Откроется следующее окно:

image

Groupid и Artifactid — идентификаторы проекта в Maven. Существуют определенные правила заполнения этих пунктов:

  • Groupid — название организации или подразделения занимающихся разработкой проекта. В этом пункте действует тоже правило как и в именовании пакетов Java: доменное имя организации записанное задом наперед. Если у Вас нет своего доменного имени, то можно использовать свой э-мейл, например com.email.email;
  • Artifactid — название проекта;
  • Version — версия проекта.

Нажмем «Finish»: IDE автоматически откроет файл pom.xml:

image

В нем уже появилась информация о проекте, внесенная на предыдущем шаге: Groupid, Artefiactid, Version. Pom.xml — это файл который описывает проект. Pom-файл хранит список всех библиотек (зависимостей), которые используются в проекте.

image

Выберем нужную версию (в примере будет использована версия 3.14.0). Откроется страница:

image

Копируем содержимое блока «Maven» и вставим в файл pom.xml в блок

Таким образом библиотека будет включена в проект и ее можно будет использовать. Аналогично сделаем с библиотекой Junit (будем использовать версию 4.12).

image

Создание пакета и класса

Раскроем структуру проекта. Директория src содержит в себе две директории: «main» и «test». Для тестов используется, соответственно, директория «test». Откроем директорию «test», кликом правой клавиши мыши по директории «java» выберем пункт «New», а затем пункт «Package». В открывшемся диалоговом окне необходимо ввести название пакета. Имя базового пакета должно носить тоже имя, что и Groupid — «org.example».

Следующий шаг — создание класса Java, в котором пишется код автотеста. Кликом правой клавиши мыши по названию пакета выберем пункт «New», а затем пункт «Java Class».

В открывшемся диалоговом окне необходимо ввести имя Java класса, например, LoginTest (название класса в Java всегда должно начинаться с большой буквы). В IDE откроется окно тестового класса:

image

Настройка IDE

Прежде чем начать, необходимо настроить IDE. Кликом правой клавиши мыши по названию проекта выберем пункт «Open Module Settings». В открывшемся окне во вкладке «Sources» поле «Language level» по умолчанию имеет значение 5. Необходимо изменить значение поля на 8 (для использования всех возможностей, присутствующих в этой версии Java) и сохранить изменения:

image

Далее необходимо изменить версию компилятора Java: нажмем меню «File», а затем выберем пункт Settings.

В открывшемся перейдем «Build, Execution, Deployment» -> «Compiler» -> «Java Compiler». По умолчанию установлена версия 1.5. Изменим версию на 8 и сохраним изменения:

image

Test Suite

  1. Пользователь открывает страницу аутентификации;
  2. Пользователь производит ввод валидных логина и пароля;
  3. Пользователь удостоверяется в успешной аутентификации — об этом свидетельствует имя пользователя в верхнем правом углу окна;
  4. Пользователь осуществляет выход из аккаунта путем нажатия на имя пользователя в верхнем правом углу окна с последующим нажатием на кнопку «Выйти…».

Тест считается успешно пройденным в случае, когда пользователю удалось выполнить все вышеперечисленные пункты.

Для примера будет использоваться аккаунт Яндекс (учетная запись заранее создана вручную).

Первый метод

В классе LoginTest будет описана логика теста. Создадим в этом классе метод «setup()», в котором будут описаны предварительные настройки. Итак, для запуска браузера необходимо создать объект драйвера:

Перед созданием объекта WebDriver следует установить зависимость, определяющую путь к chomedriver (в ОС семейства Windows дополнительно необходимо указывать расширение .exe):

Чтобы ход теста отображался в полностью открытом окне, необходимо сказать об этом драйверу:

Случается, что элементы на страницах доступны не сразу, и необходимо дождаться появления элемента. Для этого существуют ожидания. Они бывают двух видов: явные и неявные. В примере будет использовано неявное ожидание Implicitly Wait, которое задается вначале теста и будет работать при каждом вызове метода поиска элемента:

Таким образом, если элемент не найден, то драйвер будет ждать его появления в течении заданного времени (10 секунд) и шагом в 500 мс. Как только элемент будет найден, драйвер продолжит работу, однако, в противном случае тест упадем по истечению времени.

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

Выносим настройки

Для удобства вынесем название страницы в отдельный файл (а чуть позже и некоторые другие параметры).

Создадим в каталоге «test» еще один каталог с названием «resources», а в нем обычный файл «conf.properties», в который поместим переменную:

а также внесем сюда путь до драйвера

image

В пакете «org.example» создадим еще один класс «ConfProperties», который будет читать записанные в файл «conf.properties» значения:

image

Обзор первого метода

image

Метод «setup()» пометим аннотацией Junit «@BeforeClass», которая указывает на то, что метод будет выполняться один раз до выполнения всех тестов в классе. Тестовые методы в Junit помечаются аннотацией Test.

Page Object

При использовании Page Object элементы страниц, а также методы непосредственного взаимодействия с ними, выносятся в отдельный класс.

Создадим в пакете «org.example» класс LoginPage, который будет содержать локацию элементов страницы логина и методы для взаимодействия с этими элементами.

В результате мы увидим этот элемент среди множества других. Теперь мы можем скопировать его локацию. Для этого кликаем правой кнопкой мыши по выделенному в панели разработчика элементу, выбираем меню «Copy» -> «Copy XPath».

Для локации элементов в Page Object используется аннотация @FindBy.

Напишем следующий код:

Таким образом мы нашли элемент на страницу и назвали его loginField (элемент доступен только внутри класса LoginPage, т.к. является приватным).

Однако, такой длинный и страшный xpath использовать не рекомендуется (рекомендую к прочтению статью «Не так страшен xpath как его незнание». Если присмотреться, то можно увидеть, что поле ввода логина имеет уникальный id:

image

Воспользуемся этим и изменим поиск элемента по xpath:

Теперь вероятность того, что поле ввода пароля будет определено верно даже в случае изменения местоположения элемента на странице, возросла.

Аналогично изучим следующие элементы и получим их локаторы.

Поле ввода пароля:

А теперь напишем методы для взаимодействия с элементами.

Метод ввода логина:

Метод ввода пароля:

Метод нажатия кнопки входа:

Для того, чтобы аннотация @FindBy заработала, необходимо использовать класс PageFactory. Для этого создадим конструктор и передадим ему в качестве параметра объект Webdriver:

image

После авторизации мы попадаем на страницу пользователя. Т.к. это уже другая страница, в соответствии с идеологией Page Object нам понадобится отдельный класс для ее описания. Создадим класс ProfilePage, в котором определим локаторы для имени пользователя (как показателя успешного входа в учетную запись), а также кнопки выхода из аккаунта. Помимо этого, напишем методы, которые будут получать имя пользователя и нажимать на кнопку выхода.

Итого, страница будет иметь следующий вид:

image

Интересный момент: в метод getUserName() пришлось добавить еще одно ожидание, т.к. страница «тяжелая» и загружалась довольно медленно. В итоге тест падал, потому что метод не мог получить имя пользователя. Метод getUserName() с ожиданием:

Вернемся к классу LoginTest и добавим в него созданные ранее классы-страницы путем объявления статических переменных с соответствующими именами:

Сюда же вынесем переменную для драйвера

В аннотации @BeforeClass создаем экземпляры классов созданных ранее страниц и присвоим ссылки на них. Создание экземпляра происходит с помощью оператора new. В качестве параметра указываем созданный перед этим объект driver, который передается конструкторам класса, созданным ранее:

А создание экземпляра драйвера приведем к следующему виду (т.к. он объявлен в качестве переменной):

Теперь можно перейти непосредственно к написанию логики теста. Создадим метод loginTest() и пометим его соответствующей аннотацией:

Осталось лишь корректно все завершить. Создадим финальный метод и пометим его аннотацией @AfterClass (методы помеченные этой аннотацией выполняются один раз, после завершения всех тестовых методов класса).

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

Последняя строка нужна для закрытия окна браузера.

Обзор теста

Запуск автотеста

Для запуска автотестов в Intellij Idea имеется несколько способов:

  • Alt+Shift+F10;
  • Клик правой клавишей мышки по имени тестового класса, после чего в открывшемся меню выбрать Run;

В результате выполнения автотеста, в консоли Idea я вижу, что тестовый метод loginTest() пройден успешно:

В этой статье мы будем устанавливать тестовую среду на Windows машину. Установим Eclipse, Java, Maven, TestNg, Selenium Webdriver и Firebug для определения объектов в веб-интерфейсе.

1. Установка и настройка Java на вашем ПК.

1.2 Установите java с настройками по умолчанию

1.3.1 Если машина Windows перейдите в Computer->Properties->Advance system settings->Environment Variables->New:

Создайте переменную: JAVA_HOME

Значение переменной: <путь куда установлена java> например (C:\Program Files\Java\jdk1.7.0_04)

1.3.2 Также нужно добавить значение <путь куда установлена java>\bin в переменную PATH: Нажать Edit и добавить ;C:\Program Files\Java\jdk1.7.0_04\bin;

path

1.3.3 После установки переменной следует перезапустить cmd консоль. Проверим java в cmd: java –version

path-1

Если вы видите версию java в консоле, значит java установлена успешно.

2. Установка Eclipse или Idea

В качестве среды для содания тестов вы можете выбрать бесплатные Eclipse или Idea.

Покажем, как установить и настроить Eclipse. Вы можете загрузить стандартную версию Eclipse, которая включает базовые возможности для любого java девелопера. Оба продукта можно скачать с оффициальных ресурсов.

2.1 Загрузите Eclipse и разархивируйте в любое удобное для вас место, а так как Eclipse не нужно устанавливать, то это место и будет местом установки. Для запуска используется файл eclipse.exe. В некоторых ситуациях нужно будет найти виртуальную машину в файле eclipse.ini.

path-2

2.2 Добавьте строку, показанную на скриншоте:

path-3

path-4

2.4 Для настройки eclipse вы можете воспользоваться диалогом Preferences, но для того чтобы найти специальные функции, стоит обратиться к помощи в интернете.

path-5

3. Установка и настройка maven

path-6

Мы настроили Maven на загрузку библиотек (selenium-webdriver, firefoxdriver и др.).

3.2 Разархивируем в удобное место

3.3 Добавим переменую окружения для maven M2_HOME, M2 и добавим путь к exe файлу mvn.bat

Для системы windows: Computer->Properties->Advance system settings->Environment Variables->New:

Имя переменной: M2_HOME

Значение: путь куда где установлен maven (e.g C:\Program Files\maven\)

Имя переменной: M2

Значение: %M2_HOME%\bin

Добавить в PATH следующее: ;C:\Program Files\maven\bin;

path-7

Проверим корректность установки maven: mvn –version в cmd

path-8

4. Установка TestNG для запуска тестов

TestNG преднеазначен для покрытия всех категорий тестов: юнит, функционального, интеграционного и тд.

path-9

Нажмите Install или Update. После этого eclipse попросит вас перезагрузиться. Для проверки установки нажмите на стрелку рядом с Run кнопкой (больой зеленый круг) и выберите Run Configurations…

path-10

Должна быть видна секция TestNG:

path-11

5. Установка FireBug для нахождения объектов интерфейса

FireBug является одним из самых популярных и мощных интрументов в веб разработке: анализ использования и производительности сети, отладка JavaScript, возможность расшерения функциональности самого инструмента. Вы можете редактировать, отлаживать и контролировать CSS, HTML и JavaScript любой веб-страницы с его помощью. Firebug интегрируется только с браузером Firefox.

В автоматизации FireBug поможет в поиске объектов интерфейса веб-страницы и для нахождения некоторых свойств объектов.

path-12

Также можно использовать девелоперскую среду Chrome:

path-13

Подписывайтесь на рассылку, чтобы быть в курсе новых статей по автоматизации.

Чтобы сконфигурировать Eclipse с Selenium WebDriver, необходимо запустить Eclipse IDE, создать Workspace, создать Project, Package, Class и добавить External libraries к проекту.

1) Выбор WorkSpace при запуске Eclipse

1.1) Запустите Еclipse.

Start-Eclipse-1

Creating-Class-111

2) Создание проекта

2.1) Создайте новый Java проек: File > New > Project .

Setup-Project-1

2.2) Выберите Java Project и нажмите Next.

Setup-Project-2

Creating-project-1

2.4) Если увидите следующее окно, выберите Remember my decision и нажмите Yes.

Setup-Project-4

3) Создание нового Package

Creating-Package-1

Creating-Package-2

4) Cоздание нового класса

Creating-Class-22

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

Creating-Class-23

4.3) Теперь ваше окно проектов будет выглядеть следующим образом.

Creating-Class-3

5) Добавление внешних Jar-файлов в Java build path

Теперь Вам нужно добавить Selenium webdriver jar-файлов в Java build path.

Selenium-Jar-1

5.2) Добавьте Selenium Java jar-файл, также можете добавить source-файл.

Selenium-Jar-2

5.3) Также добавьте все jar-файлы с папки libs.

Selenium-Jar-3

5.4) Нажмите OK.

Selenium-Jar-4

Это все о настройках WebDriver и Eclipse. Теперь Вы можете писать первые скрипты в Еclipse и запускать их с помощью WebDriver.

Selenium сегодня является стандартом де-факто для автоматизации выполнения тестов в браузерах. Все популярные браузеры поддерживаются из коробки, а архитектура хорошо известна. Существуют даже компании, предоставляющие Selenium за деньги. Но удобен ли обычный Selenium сервер для локальной отладки тестов?





Проблема

Как веб-разработчик или инженер по автоматизации тестирования вы можете столкнуться со следующими неудобствами при работе со стандартным Selenium сервером:

  1. Нужно устаналивать несколько разных браузеров себе на компьютер. В обычной жизни вы, как правило, используете один браузер, например, Chrome, но вам приходится устанавливать себе Firefox и Opera, чтобы отлаживать в них Selenium-тесты.
  2. Трудно устанавливать и использовать несколько версий одного браузера. Если вы устанавливаете браузер из пакетов, то вообще можно иметь только одну установленную версию. Кроме того Selenium и его веб-драйверы обычно ищут исполняемый файл браузера по определенному пути. Поэтому, поверьте, использовать несколько версий может быть трудной задачей.
  3. Если вы запускаете браузер, установленный в вашей операционной системе — он забивает место на диске своими временными файлами и содержимым кеша.
  4. Нельзя гарантировать, что настройки браузера всегда останутся в том же состоянии, как после чистой установки. Например, вы можете случайно изменить адрес прокси-сервера или настройки безопасности. Это может привести к падению ранее работавших тестов.
  5. Трудно запускать несколько тестов в разных браузерах параллельно. Попытка сделать это как правило приводит к различным проблемам: окна начинают конкурировать за фокус, не срабатывающие события, не ожидаемые CSS стили и так далее.
  6. Нужно знать какая версия Selenium совместима с какой версией браузера. То же самое верно для исполняемых файлов веб-драйверов (например, Chromedriver).

Приведенный выше список недостатков далеко не полный. Но давайте остановимся на этом и попробуем гораздо более удобный способ отладки Selenium-тестов локально.

Selenoid

В моей предыдущей статье (часть I, часть II) я коротко описал новые открытые инструменты для работы с Selenium: Ggr и Selenoid. Ggr в основном нужен для больших Selenium кластеров и не нужен для отладки тестов на вашей машине. Сегодня я более подробно расскажу о Selenoid — альтернативной реализации Selenium хаба, которая запускает браузеры в Docker контейнерах.

Но почему же запуск браузеров в контейнерах так удобен? И в чем разница между запуском браузеров из контейнеров, поставляемых разработчиками Selenium и Selenoid? — Основная идея Selenoid состоит в том, чтобы запускать новый контейнер для каждой Selenium сессии (т.е. запроса нового браузера) и останавливать их сразу же после закрытия сессии. Такой подход сразу же решает все проблемы связанные с залипанием состояния в кешах и использования одних настроек браузера в разных сессиях. В каждом контейнере находится конкретная версия браузера, правильная версия веб-драйвера или Selenium сервера, поддерживающая этот браузер и все зависимости наподобие шрифтов, графических библиотек и так далее. Более того, контейнеры обеспечивают достаточный уровень изоляции процессов браузеров. Это позволяет запускать неограниченное количество разлиных версий браузеров параллельно и забыть о проблемах с фокусом. Безусловно, эти же проблемы решаются и обычными Selenium контейнерами. Но для того, чтобы получить поведение, аналогичное Selenoid, в дополнение к Docker как правило требуется использовать сложные админские инструменты наподобие Ansible или Salt.

Установка

Немного порекламировав Selenoid, настало время показать как просто с ним работать. Для того, чтобы получить работающий Selenium нужно выполнить 3 коротких шага:

Установить Docker. Обычно это делается при помощи стандартного менеджера пакетов вашей операционной системы такого как APT, Yum или Homebrew. Подробности можно найти в документации Docker.

Создать каталог для хранения конфигурации Selenoid и сгенерировать конфигурационный файл:

Последняя команда также скачает образы Docker-контейнеров двух последних версий Firefox, Chrome и Opera и сгенерирует правильный файл конфигурации для Selenoid.

Все — прошло 60 секунд и Selenoid готов к работе. Не нужно устанавливать Java и скачивать Selenium руками. Просто запустите свои тесты, используя тот же самый URL, что и у обычного Selenium server:

Мордочка и сбор статистики

Selenoid может использоваться совместно с Ggr для настройки большого Selenium кластера, поэтому у него нет графического интерфейса наподобие Grid Console в обычном Selenium. Посмотреть потребление браузеров можно двумя способами:

I. Запустить дополнительный легковесный контейнер с Selenoid UI. Это делается командой:




II. Отправлять статистику Selenoid во внешнюю систему: Graphite, InfluxDB, ElasticSearch и так далее. Статистика Selenoid может быть получена по следующему URL:

Данные отправляются в виде JSON следующего формата:

Готовые контейнеры с браузерами

Согласитесь, круто иметь инструмент, автоматически запускающий контейнеры с разными браузерами. Но еще круче иметь набор готовых контейнеров с разными версиями популярных браузеров. Мы проделали много работы и подготовили образы контейнеров с разными версиями Firefox, Chrome и Opera. Полный список можно посмотреть на selenoid@DockerHub.

Чтобы всегда иметь набор свежих версий браузеров нужно лишь время от времени выполнять команду:

Эта команда автоматически скачивает последние версии контейнеров и генерирует новую JSON-конфигурацию для Selenoid. Чтобы начать использовать новые браузеры отправьте Selenoid команду на перечитывание конфигурации (можно делать под нагрузкой):

Наши контейнеры также поддерживают возможность установки произвольно разрешения экрана (по-умолчанию 1920x1080x24 ). Чтобы выставить разрешение просто передайте capability screenResolution :

Заключение

В этой статье я рассказал как эффективно управлять различными браузерами при помощи Selenoid. Поверьте — работа с Selenium может быть комфортной. Если вам интересны вопросы построения эффективной инфраструктуры тестирования, вы можете взглянуть на другие открытые инструменты в нашей организации на Github или подпишитесь на наш Твиттер @aerokube.

В благодарность автору замечательной картинки, посмотрите как ее рисовали.




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

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

Что внутри рабочей ноды

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

  1. Как организовать хабы и ноды, чтобы эффективно потреблять аппаратные ресурсы и хорошо масштабироваться?
  2. Какую операционную систему использовать?
  3. Какие программы должны быть установлены?
  4. Можно ли работать без монитора?

Одним из способов может быть использование "железа" с одним Selenium хабом и множеством нод с различными браузерами. Выглядит разумно, но на самом деле неудобно:

  1. Как было сказано Selenium хаб с большим числом нагруженных нод работает очень медленно. Не уверен насчет настоящих причин, но практика показывает именно это. Мой совет — не читайте исходники Selenium на ночь, если не хотите, чтобы вам снились кошмары. Таким образом мы не можем использовать десятки Selenium нод с одним и тем же хабом. Остается использовать один хаб и лишь несколько нод. Чтобы эффективно использовать железо нужно уменьшить общее число ядер на хаб — хорошая причина переехать в облака. Например, наш работающий грид длительное время использовал маленькие виртуальные машины с 2 ядрами и 4 Гб памяти.
  2. Непонятно как установить разные версии одного браузера простым способом (например, из пакетов).
  3. Непонятно как легко учитывать общее количество доступных браузеров одной версии.
  4. Разные версии Selenium-ноды совместимы с разными версиями браузеров, т.е. более новая Selenium нода может не поддерживать более старый браузер.

Наиболее простой способ иметь одинаковое количество нод на один хаб — это запускать их внутри одной виртуальной машины. Если каждая версия браузера — это отдельная виртуальная машины, то подсчет общего числа доступных браузеров становится задачей из начальной школы. Можно легко добавлять и удалять виртуальные машины, содержащие совместимые версии ноды и браузера. Мы рекомендуем такой подход при установке кластера Selenium в облако с постоянно доступным количеством каждой версии браузера.




Что же еще кроме Selenium хаба и ноды находится внутри виртуальной машины, чтобы все работало?

  • Во-первых, мы рекомендуем использовать Linux в качестве основном операционной системы везде, где возможно. Используя Linux вы можете покрыть 80% потребности в браузерах. Легче перечислить то, что не покрыто:
    1. Internet Explorer и Microsoft Edge. Эти браузеры работают только под Windows и заслуживают отдельной статьи. Нет повести печальнее на свете.
    2. Desktop Safari. Кто-нибудь им вообще пользуется? Selenium довольно плохо поддерживает этот браузер.
    3. iOS и мобильные телефоны Apple. Для работы с этими устройствами нужно использовать железо от Apple, например, MacMini и Appium.
  • Для запуска Selenium нужно установить Java (JDK или JRE), а также скачать нужную версию Selenium в виде JAR-архива.

Виртуальные машины не имеют монитора, поэтому Selenium должен быть запущен в особой версии X-сервера, которая эмулирует дисплей. Эта реализация называется Xvfb. Запускается это так:

Обратите внимание, что Xvfb нужно только для процесса Selenium-ноды.

Худеем


Как вы уже могли заметить, Selenium — это Java-приложение. Для запуска Selenium нужно установить Java Virtual Machine (JVM). Самый маленький установочный пакет Java, называемый JRE, имеет размер около 50 мегабайт. Selenium JAR самой последней версии 3.0.1 добавляет еще 20 мегабайт. Теперь добавим размер операционной системы, нужные шрифты, размер самого браузера и вы легко достигаете нескольких сотен мегабайт. И хотя жесткие диски сейчас стоят дешево, мы можем сделать лучше. Selenium версий 2.0 и 3.0 также называют Selenium Webdriver. Это связано с тем, что поддержка разных браузеров реализована при помощи отдельных приложений, называемых веб-драйверами.

  1. Разработчики браузера могут писать свой продукт, как им хочется. Чтобы браузер поддерживался в Selenium им нужно предоставить приложение веб-сервер, предоставляющее то же API, что и сам Selenium Server и поддерживающий протокол JSONWire. Это приложение должно уметь запускать процесс браузера, выполнять команды Selenium согласно спецификации и останавливать браузер по запросу. Любые детали взаимодействия драйвера с браузером могут быть реализованы по-усмотрению разработчиков. Единственное требование — поддержка одинакового Selenium API. Например, Chrome имеет Chromedriver, Opera Blink предоставляет OperaDriver и так далее.
  2. При установке Selenium требуется указать только путь до приложения-драйвера.
  3. Когда вы запрашиваете браузер у Selenium, он, на самом деле, запускает процесс драйвера и проксирует все запросы в драйвер. Драйвер выполняет всю остальную работу. Такой же результат вы можете получить, если вручную запустите процесс драйвера на требуемом порту и нацелите свои тесты на него.

Теперь, когда мы выяснили это, встает вопрос: не слишком ли дорого тратить сотни мегабайт для простого проксирования? Год назад ответ был определенно нет, потому что не существовало приложения-драйвера для Firefox — наиболее часто используемый браузер в Selenium. Ответственностью Selenium было запустить Firefox, загрузить в него специальное расширение и проксировать запросы в порт, открытый этим расширением. За последний год ситуация изменилась. Начиная с Firefox 48.0 Selenium взаимодействует с браузером, используя отдельный бинарный драйвер — Geckodriver. Это означает, что теперь для большинства настольных браузеров мы можем совсем удалить Selenium Server и проксировать запросы напрямую в драйверы.

Переезжаем в контейнеры

В предыдущих разделах я описал как можно построить кластер Selenium, используя виртуальные машины в облаке. В этом подходе виртуальные машины всегда запущены и постоянно тратят ваши деньги. Кроме того общее число доступных браузеров для каждой версии ограничено и может приводить к полному исчерпанию доступных браузеров во время пиковых нагрузок. Я слышал о работающих и даже запатентованных сложных решениях, которые запускают и прогревают пул виртуальных машин в зависимости от текущей нагрузки, чтобы всегда иметь доступные браузеры. Это работает, но можно ли сделать лучше? Основная проблема гипервизорной виртуализации — это скорость. Запуск новой виртуальной машины может занимать неколько минут. Но давайте немного подумаем — нужна ли нам отдельная операционная система для каждого браузера? — Нет, нужна только простая изоляция по диску и сети. Вот почему контейнерная виртуализация становится актуальной. На данный момент контейнеры работают в основном только под Linux, но, как я уже говорил, Linux покрывает 80% наиболее популярных браузеров. Контейнеры с браузерами стартуют за секунды и останавливаются еще быстрее.




Что же должно быть внутри контейнера? — Практически то же самое, что и внутри виртуальной машины: сам браузер, шрифты, Xvfb. Для старых версий Firefox (< 48.0) по-прежнему нужно установить Java и Selenium Server, но для Chrome, Opera и свежих версий Firefox мы можем использовать приложение-драйвер в качестве основного процесса контейнера. Если использовать легковесный Linux дистрибутив (например, Alpine), можно получить очень маленькие и легковесные контейнеры.

Selenoid

На данный момент наиболее популярной и известной контейнерной платформой является Docker. Разработчики Selenium предоставляют набор готовых Docker контейнеров для запуска Selenium в режиме Standalone или Grid в Docker. Для того, чтобы запустить кластер из таких образов, нужно запускать и останавливать контейнеры вручную или при помощи инструментов наподобие Docker Compose. Такой подход уже намного лучше, чем установка Selenium из пакетов, но было бы еще лучше, если бы существовал сервер со следующим поведением:

  1. Администратор стартует демон сервера вместо обычного Selenium хаба.
  2. Демон "знает" (из конфигурации), что, например, для запуска Firefox 48.0 нужно скачать и запустить контейнер Х, а для Chrome 53 — контейнер Y.
  3. Пользователь запрашивает Selenium сессию обычным способом, но у этого нового демона.
  4. Демон анализирует капабилити (desired capabilities), стартует нужный контейнер и затем проксирует запросы в основной процесс контейнера (Selenium server или веб-драйвер).

Мы сделали такой демон… и даже больше.

За годы использования Selenium server в больших масштабах мы поняли, что очень неэффективно использовать JVM и "толстый" Selenium JAR для простого проксирования запросов. Поэтому мы искали более легковесную технологию. Наш выбор остановился на языке программирования Go также известном как Golang. Почему для наших целей Go подходит лучше?

Мы так и не придумали хорошего имени для описанного выше демона. Поэтому мы назвали его просто Selenoid. Чтобы попробовать Selenoid нужно выполнить 3 простых шага:

  • Создать JSON-файл, содержащий информацию о том какой контейнер нужно запустить для каждой версии браузера:

Как и в XML файле для Gridrouter указан список доступных версий браузеров. Поскольку Selenoid запускает контейнеры на той же машине или через Docker API, нет необходимости указывать имена хостов и регионы. Для каждой версии браузера нужно указать имя контейнера, его версию и порт, на котором слушает основной процесс контейнера.

По-умолчанию Selenoid стартует на порту 4444, как обычный Selenium хаб.

  • Запустить свои тесты на хост Selenoid, как будто это обычный Selenium хаб.

Наши эксперименты показывают, что даже контейнеры со стандартным Selenium сервером внутри стартуют за несколько секунд. Взамен вы получаете гарантированное состояние диска и памяти. Браузер всегда находится в состоянии как после установки на чистую операционную систему. Кроме того вы можете установить Selenoid на большой кластер из хостов имеющих одинаковый набор поддерживаемых браузеров, сохраненных в виде Docker образов. Это дает вам большой кластер Selenium, который автоматически масштабируется в зависимости от потребления браузеров. Например, если текущие запросы пользователей требуют больше Chrome — автоматически запускается больше контейнеров. Когда запросов на Chrome не поступает — контейнеры с Chrome останавливаются и освободившиеся хосты могут использоваться для других браузеров.

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




Но Selenoid позволяет запускать не только контейнеры. Он также умеет запускать по требованию процессы веб-драйвера. Основное применение этой функциональности — замена Selenium Server на Windows. В этом случае Selenoid стартует процесс IEDriverServer, что позволяет экономить память и избегать ошибок проксирования в самом Selenium.

Go Grid Router (также известный как ggr)

Возможно, вы помните, что оригинальный GridRouter — это Java приложение. Мы написали с нуля легковесную реализацию этого прокси на Go и назвали просто Go Grid Router (или ggr). В чем преимущества новой версии по сравнению со старой?

  1. Увеличенная производительность. Может обслуживать минимум на 25% больше запросов.
  2. Меньшее потребление памяти. При нагрузке в 150 rps потребляет всего 100-200 мегабайт памяти и это число не меняется.
  3. Отслеживается отсоединение клиента. Если клиент отсоединяется (например, из-за таймаута) Java-версия GridRouter продолжает перебирать хосты, пытаясь создать сессию. Это забивает сеть ненужными пакетами и уменьшает производительность GridRouter, когда много хабов становятся недоступны. Новая реализация на Go перестает пытаться получить браузер как только клиент отключается.
  4. Перезагрузка сервера без потери соединений (graceful restart). Если сервер используется вне Docker контейнера, то можно перезагрузить его без потери соединений, послав процессу сигнал SIGUSR2.
  5. Перезагрузка квот по запросу. Когда используется несколько инстансов GridRouter за балансером важно обновлять квоты одновременно. Когда в XML файлы квот добавляются новые хосты и квоты обновляются не одновременно на работающем кластере Selenium может произойти ситуация, когда одна "голова" GridRouter уже знает про новые хосты и перенаправляет туда запросы, а другая еще не знает об этих хостах и возвращает ошибку 404. Реализация на Go перезагружает квоты по сигналу SIGHUP, а не автоматически, как это происходит в Java версии. Эта функциональность работает как в Docker, так и без него.
  6. Зашифрованные пароли. Ggr использует текстовые файлы формата Apache htpasswd для хранения логинов и паролей. Логины хранятся в открытом виде, а пароли зашифрованы.
  7. Маленький размер исполняемого файла. Всего 6 мегабайт. Не требует установки Java. Если устанавливать в Docker, то контейнер на основе Alpine Linux занимает всего 11 мегабайт.

В связке с Selenoid, позволяет создавать масштабируемый, надежный кластер Selenium:




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

  1. Почему Selenium хорошо упаковывается и запускается в контейнерах
  2. Что должно быть внутри контейнера
  3. Какие open-source инструменты для работы Selenium в контейнерах существуют

В заключение в одном месте собраны ссылки на упомянутые в статье продукты:

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