Статьи

Тестирование JavaScript с PhantomJS

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


Что такое PhantomJS? Ну, вот реклама с сайта PhantomJS :

PhantomJS — это безголовый WebKit с JavaScript API.

Как вы знаете, Webkit — это механизм компоновки, который используют Chrome, Safari и несколько других нишевых браузеров. Итак, PhantomJS — это браузер, но безголовый браузер. Это означает, что отображаемые веб-страницы фактически никогда не отображаются. Это может звучать странно для вас; так что вы можете думать об этом как о программируемом браузере для терминала. Через минуту мы рассмотрим простой пример, но сначала нам нужно установить PhantomJS.


Установка PhantomJS на самом деле довольно проста: это просто один двоичный файл, который вы загружаете и вставляете в путь своего терминала. На странице загрузки PhantomJS выберите свою операционную систему и загрузите правильный пакет. Затем переместите двоичный файл из загруженного пакета в каталог в вашем терминальном пути (мне нравится помещать подобные вещи в ~/bin ).

Если вы работаете в Mac OS X, есть более простой способ установить PhantomJS (и именно этот метод я использовал). Просто используйте Homebrew, вот так:

1
brew update && brew install phantomjs

Теперь у вас должен быть установлен PhantomJS. Вы можете дважды проверить вашу установку, запустив это:

1
phantomjs —version

Я вижу 1.7.0; ты?


Давайте начнем с небольшого примера.

Продолжайте и запустите этот код, введя следующую команду:

1
phantomjs simple.js

Вы должны увидеть выходные данные из двух строк console.log в окне терминала.

Конечно, это просто, но это хорошо: PhantomJS может выполнять JavaScript так же, как браузер. Однако в этом примере нет никакого специфичного для PhantomJS кода … ну, кроме последней строки. Это важная строка для каждого скрипта PhantomJS, потому что он выходит из скрипта. Это может не иметь смысла, но помните, что JavaScript не всегда выполняется линейно. Например, вы можете поместить вызов exit() в функцию обратного вызова.

Давайте посмотрим на более сложный пример.


Используя API PhantomJS, мы можем фактически загрузить любой URL и работать со страницей с двух точек зрения:

  • как JavaScript на странице.
  • как пользователь, смотрящий на страницу.

Давайте начнем с выбора загрузки страницы. Создайте новый файл сценария и добавьте следующий код:

Мы начнем с загрузки модуля webpagewebpage PhantomJS и создания объекта веб-страницы. Затем мы вызываем метод open , передавая ему URL и функцию обратного вызова; внутри этой функции обратного вызова мы можем взаимодействовать с реальной страницей. В приведенном выше примере мы просто записываем статус запроса, предоставленный параметром функции обратного вызова. Если вы запустите этот скрипт (с phantomjs script.js ), вы должны напечатать «success» в терминале.

Но давайте сделаем это более интересным, загрузив страницу и выполнив на ней немного JavaScript. Мы начнем с приведенного выше кода, но затем сделаем вызов page.evaluate :

PhantomJS — это браузер, но безголовый браузер.

Функция, которую мы передаем page.evaluate выполняется на загруженной веб-странице как JavaScript. В этом случае мы находим все элементы с классом post ; затем мы устанавливаем фон первого поста черным. Наконец, мы возвращаем document.title . Это хорошая функция, возвращающая значение из нашего обратного вызова evaluate и присваивающая его переменной (в нашем случае, title ).

Затем мы устанавливаем clipRect на странице; это размеры для скриншота, который мы берем методом render . Как видите, мы устанавливаем top и left значения, чтобы установить начальную точку, а также задаем width и height . Наконец, мы вызываем page.render , передавая ему имя для файла (переменная title ). Затем мы заканчиваем вызовом phantom.exit() .

Запустите этот скрипт, и у вас должно получиться изображение, похожее на это:

Вы можете увидеть обе стороны монеты PhantomJS здесь: мы можем выполнить JavaScript изнутри страницы, а также выполнить снаружи, на самом экземпляре страницы.

Это было весело, но не невероятно полезно. Давайте сосредоточимся на использовании PhantomJS при тестировании нашего DOM-связанного JavaScript.


Yeoman использует PhantomJS в своей процедуре тестирования, и это практически без проблем.

Для большого количества кода JavaScript вы можете тестировать без DOM, но бывают случаи, когда ваши тесты должны работать с элементами HTML. Если вы похожи на меня и предпочитаете запускать тесты в командной строке, то тут PhantomJS вступает в игру.

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

Во-первых, Жасмин и заявление об отказе от ответственности: в настоящее время нет хорошего бегуна PhantomJS для Жасмин. Если вы используете Windows и Visual Studio, вы должны проверить Chutzpah , а разработчики Rails должны попробовать guard-jasmine . Но кроме этого, поддержка Jasmine + PhantomJS редка.

По этой причине я рекомендую использовать Mocha для тестов, связанных с DOM.

ТЕМ НЕ МЕНИЕ.

Возможно, у вас уже есть проект с использованием Jasmine и вы хотите использовать его с PhantomJS. Один проект, Phantom-Jasmine , требует небольшой работы для настройки, но он должен сработать.

Начнем с набора тестов JasmineJS. Загрузите код для этого руководства (ссылка вверху) и проверьте папку jasmine-starter . Вы увидите, что у нас есть один файл tests.js который создает элемент DOM, задает несколько свойств и добавляет его в тело. Затем мы запускаем несколько тестов Jasmine, чтобы убедиться, что процесс действительно работает правильно. Вот содержимое этого файла:

Файл SpecRunner.html довольно стандартный; единственное отличие состоит в том, что я переместил теги сценария в тело, чтобы DOM полностью загружался до запуска наших тестов. Вы можете открыть файл в браузере и увидеть, что все тесты проходят нормально.

Давайте переведем этот проект на PhantomJS. Сначала клонируем проект « фантом-жасмин »:

Этот проект не так организован, как мог бы, но есть две важные части, которые вам нужны:

  • бегун PhantomJS (который заставляет Жасмин использовать DOM PhantomJS).
  • консольный репортер Jasmine (который выдает консольный вывод).

Оба этих файла находятся в папке lib ; скопируйте их в jasmine-starter/lib . Теперь нам нужно открыть наш файл SpecRunner.html и настроить элементы <script /> . Вот как они должны выглядеть:

01
02
03
04
05
06
07
08
09
10
11
<script src=»lib/jasmine-1.2.0/jasmine.js»></script>
<script src=»lib/jasmine-1.2.0/jasmine-html.js»></script>
<script src=»lib/console-runner.js»></script>
<script src=»tests.js»></script>
 
<script>
    var console_reporter = new jasmine.ConsoleReporter()
    jasmine.getEnv().addReporter(new jasmine.HtmlReporter());
    jasmine.getEnv().addReporter(console_reporter);
    jasmine.getEnv().execute();
</script>

Обратите внимание, что у нас есть два репортера для наших тестов: репортер HTML и консольный репортер. Это означает, что SpecRunner.html и его тесты могут работать как в браузере, так и в консоли. Это удобно К сожалению, нам нужна переменная console_reporter потому что она используется внутри файла CoffeeScript, который мы собираемся запустить.

Итак, как нам на самом деле запустить эти тесты на консоли? Предполагая, что вы находитесь в папке jasmine-starter на терминале, вот команда:

1
phantomjs lib/run\_jasmine\_test.coffee ./SpecRunner.html

Мы run\_jasmine\_test.coffee с PhantomJS и SpecRunner.html наш файл SpecRunner.html в качестве параметра. Вы должны увидеть что-то вроде этого:

Конечно, если тест не пройден, вы увидите что-то вроде следующего:

Если вы планируете использовать это часто, было бы неплохо переместить run\_jasmine\_test.coffee в другое место (например, ~/bin/run\_jasmine\_test.coffee ) и создать псевдоним терминала для всей команды. Вот как это можно сделать в оболочке Bash:

1
alias phantom-jasmine=’phantomjs /path/to/run\_jasmine\_test.coffee’

Просто добавьте это в ваш файл .bashrc или .bash_profile . Теперь вы можете просто запустить:

1
phantom-jasmine SpecRunner.html

Теперь ваши тесты Жасмин отлично работают на терминале через PhantomJS. Вы можете увидеть окончательный код в папке jasmine-total в загрузке.


К счастью, гораздо проще интегрировать Mocha и PhantomJS с mocha-phantomjs . Это очень легко установить, если у вас установлен NPM (что вам и нужно):

1
npm install -g mocha-phantomjs

Эта команда устанавливает mocha-phantomjs файл mocha-phantomjs который мы будем использовать для запуска наших тестов.

В предыдущем уроке я показал вам, как использовать Mocha в терминале, но вы будете действовать иначе, когда будете использовать его для тестирования кода DOM. Как и в случае с Jasmine, мы начнем с тестового репортера HTML, который может работать в браузере. Прелесть этого в том, что мы сможем запустить этот же файл на терминале для результатов тестирования консоли с PhantomJS; так же, как мы могли бы с Жасмин.

Итак, давайте создадим простой проект. Создайте каталог проекта и перейдите в него. Начнем с файла package.json :

Mocha — это тестовая среда, и мы будем использовать Chai в качестве нашей библиотеки утверждений. Мы устанавливаем их, запустив NPM.

Мы назовем наш тестовый файл test/tests.js , и вот его тесты:

Они очень похожи на тесты Jasmine, но синтаксис утверждения Chai немного отличается (поэтому не просто копируйте ваши тесты Jasmine).

Последним фрагментом головоломки является файл TestRunner.html :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<html>
    <head>
        <title> Tests </title>
        <link rel=»stylesheet» href=»./node_modules/mocha/mocha.css» />
    </head>
    <body>
        <div id=»mocha»></div>
        <script src=»./node_modules/mocha/mocha.js»></script>
        <script src=»./node_modules/chai/chai.js»></script>
        <script>
            mocha.ui(‘bdd’);
            mocha.reporter(‘html’);
            var expect = chai.expect;
        </script>
        <script src=»test/test.js»></script>
        <script>
            if (window.mochaPhantomJS) { mochaPhantomJS.run();
            else { mocha.run();
        </script>
    </body>
</html>

Здесь есть несколько важных факторов. Во-первых, обратите внимание, что этого достаточно для запуска в браузере; у нас есть CSS и JavaScript из узловых модулей, которые мы установили. Затем обратите внимание на встроенный тег сценария. Это определяет, загружен ли PhantomJS, и если да, запускает функциональность PhantomJS. Иначе, он придерживается сырой функциональности Мокко. Вы можете попробовать это в браузере и посмотреть, как это работает.

Чтобы запустить его в консоли, просто запустите это:

1
mocha-phantomjs TestRunner.html

Вуаля! Теперь вы выполняете тесты в консоли, и все это благодаря PhantomJS.


Могу поспорить, что вы не знали, что популярный Yeoman использует PhantomJS в своей процедуре тестирования, и это абсолютно безразлично. Давайте посмотрим на быстрый пример. Я предполагаю, что у вас все настроено.

Создайте новый каталог проекта, запустите в нем yeoman init и ответьте «Нет» на все опции. Откройте файл test/index.html , и вы увидите тег сценария внизу с комментарием, в котором вам предложат заменить его на свои собственные спецификации. Полностью игнорируйте этот хороший совет и поместите it блок it :

Теперь запустите yeoman test , и вы увидите, что тест работает нормально. Теперь откройте файл test/index.html в браузере. Оно работает! Отлично!

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


Используйте библиотеки, расширяющие PhantomJS, чтобы упростить тестирование.

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

Я надеюсь, что этот урок побудил вас взглянуть на PhantomJS. Я рекомендую начать с примеров файлов и документации, которые предлагает PhantomJS; они действительно откроют вам глаза на то, что вы можете сделать с PhantomJS — все, от автоматизации страниц до прослушивания сети.

Итак, можете ли вы вспомнить проект, который PhantomJS улучшит? Давайте послушаем об этом в комментариях!