Статьи

Функциональное тестирование без головы с помощью Selenium и PhantomJS

Давайте создадим систему для выполнения функциональных тестов в веб-приложениях, используя Selenium и PhantomJS. Получившаяся система позволит нам писать простые тестовые сценарии на JavaScript и тестировать эти сценарии как в реальных браузерах, так и в симуляторе без головы.


Очевидным недостатком Selenium является то, что для всех тестов требуется полный графический рабочий стол.

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

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

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

Selenium теперь может управлять PhantomJS так же, как и любой другой браузер.

PhantomJS, будучи полным WebKit, покрывает 90% ваших потребностей в функциональном тестировании. В конце концов, если ваше приложение работает в WebKit правильно, вполне вероятно, что оно будет работать правильно в других браузерах. Очевидно, что это исключает Internet Explorer 6–8 .

Однако, по мере того как ваш проект становится все более популярным, оставшиеся 10% становятся серьезной проблемой. Если ваш комплект функционального тестирования настроен непосредственно на PhantomJS, было бы непросто переписать тесты для Selenium.

К счастью, недавно, ближе к концу 2012 года , мы получили подарок в виде привязки PhantomJS к Selenium. Другими словами, Selenium теперь может управлять PhantomJS так же, как и любой другой браузер.

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

Таким образом, наш выбор для движка браузера — Selenium с PhantomJS .

Selenium предлагает привязки на самых популярных языках программирования, поэтому мы можем выбрать язык в соответствии с нашими потребностями. Это, пожалуй, самая противоречивая часть этой статьи: я считаю, что JavaScript — лучший выбор для описания функциональных тестов для веб-сайтов и веб-приложений.

  • Независимо от того, какую серверную технологию вы используете, ваш интерфейс всегда будет использовать JavaScript ( это применимо, даже если вы используете язык, который компилируется до обычного JavaScript, например CoffeeScript или TypeScript. ). Таким образом, JavaScript всегда будет понятным хотя бы для одного человека из вашей команды.

  • Затем рассмотрите возможность написания ваших функциональных тестов непрограммистами. Популярность JavaScript во внешнем интерфейсе в сочетании с выразительностью в способности создавать понятные доменно-ориентированные языки явно позволяют большему количеству людей писать функциональные тесты.

  • Наконец, вполне естественно управлять тестовым браузером с помощью JavaScript, учитывая, что он очень асинхронный, и это то, чем мы ежедневно управляем браузером.

Привязки Selenium для JavaScript называются webdriverjs . Хотя проект является менее зрелым, чем официально поддерживаемые драйверы для Java, C #, Ruby и Python, тем не менее он уже содержит большую часть необходимой нам функциональности.

Для целей данной статьи были выбраны мокко с чаем .

Наконец, нам нужен тестовый прогон или приложение для запуска тестов по имени, и просто распечатать вывод, отметив, сколько тестов прошло успешно или не удалось. Этот организатор теста должен также предложить библиотеку утверждений, которая позволяет кодировщику выразить, если тест пройден успешно или не выполнен.

Выбор здесь абсолютно свободен. Существует множество тестов JavaScript, но для этой статьи был выбран Mocha с Chai . Mocha обеспечивает значительную гибкость, широкий выбор форматов вывода и популярный жасминоподобный синтаксис. Чай позволяет писать описательные BDD-подобные утверждения.


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

  1. Мокко — тестовый бегун
  2. Чай — библиотека утверждений
  3. webdriverjs — привязки управления браузером
  4. Selenium — браузерная абстракция и запущенная фабрика
  5. PhantomJS — быстрый безголовый браузер

Поскольку большая часть нашего стека основана на JavaScript, нам нужны node.js и npm . Оба из них являются общими инструментами в сообществе, и я предполагаю, что вы уже настроили их. Если вы этого не сделаете, используйте установщик на сайте node.js. Не волнуйся; если что-то пойдет не так, в Интернете есть множество руководств по установке Node.

Все три из них могут быть установлены, используя npm :

1
sudo npm install -g mocha chai webdriverjs

Кроме того, вы можете установить их локально в каталоге, где находятся ваши тесты:

1
npm install mocha chai webdriverjs

Скачать Selenium Server . Он распространяется в виде одного файла jar , который вы запускаете просто:

1
java -jar selenium-server-standalone-2.28.0.jar

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

Используйте npm для глобальной установки PhantomJS:

1
sudo npm install -g phantomjs

Нам нужна свежая версия PhantomJS — как минимум 1.8. Это означает, что пакеты, предоставляемые вашим менеджером пакетов ( apt-get , MacPorts, …), скорее всего, будут устаревшими.

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

1
PATH=»/path/to/node_modules/phantomjs/bin:$PATH» java -jar selenium-server-standalone-2.28.0.jar

Теперь, когда у нас есть все части, мы должны собрать все воедино.

Помните: перед запуском любых тестов вы должны запустить Selenium Server:

1
java -jar selenium-server-standalone-2.28.0.jar

Selenium будет управлять PhantomJS изнутри; вам не нужно беспокоиться об этом.

Теперь нам нужно подключиться к Selenium из нашего JavaScript. Вот пример фрагмента, который будет инициировать соединение с Selenium и иметь готовый объект для управления нашим экземпляром Selenium:

Теперь мы можем описать наши тесты и использовать переменную client для управления браузером. Полная ссылка на API webdriverjs доступна в документации , но вот короткий пример:

Давайте использовать синтаксис Mocha и Chai для описания теста; мы протестируем некоторые свойства веб-страницы example.com :

Возможно, вы захотите использовать одну client инициализацию для нескольких тестовых файлов. Создайте небольшой модуль Node для инициализации и импортируйте его в каждый тестовый файл:

client.js :

test.js :

1
2
3
4
var client = require(‘./client’).client;
var expect = require(‘chai’).expect;
 
// Perform tests

Тестовые наборы Mocha выполняются с помощью бинарного mocha mocha. Если вы следовали этому руководству и установили Mocha локально, то вы должны сами описать полный путь к бинарному node_modules/mocha/bin/mocha : node_modules/mocha/bin/mocha .

По умолчанию Mocha считает любой тест, который занимает больше двух секунд, неудачным. Учитывая, что мы фактически инициализируем веб-браузер и делаем HTTP-запрос, нам нужно увеличить это время ожидания до 5 или 10 секунд:

1
node_modules/mocha/bin/mocha test.js -t 10000

Если все шло по плану, вы должны увидеть результат примерно так:

1
2
3
.
 
 ✔ 1 <span class=»nb»>test complete

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

Два очевидных направления — непрерывная интеграция и распределенное тестирование Selenium.

Ваша цель должна заключаться в том, чтобы минимизировать время, затрачиваемое на выполнение тестов.

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

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

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

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

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

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

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

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


Получившийся стек, хотя и не тривиальный, на самом деле довольно прост. Добавление PhantomJS в конец Selenium позволяет нам начать использовать Selenium без особых начальных вложений, таких как настройка графических тестовых серверов.

Использование JavaScript в качестве механизма тестирования гарантирует, что наши тесты будут оставаться актуальными в контексте веб-разработки в обозримом будущем.