Проблема
Дело в том, что бесплатная (лайт) версия инструмента Siesta позволяет запускать тесты только из браузера. А если вам понадобиться запускать тесты для CI из консоли, то придется обратить свой взор на стандартную версию, которая имеет много вкусностей, в том числе и запуск из консоли. Сам инструмент использует широко известный бесплатный движок PhantomJS для запуска своих тестов.
Решение
Изучив документацию Phantom JS, Siesta и готовые примеры для запуска тестов Jasmine и QUnit, мною было написано немного кода, позволяющего сэкономить наши с вами деньги.
Краткий обзор инструментария
Инструмент Siesta написан на фреймворке ExtJS. Это мощное средство предназначено для тестирования javascript-приложений написанных с помощью различных популярных фреймворков таких как: ExtJS, jQuery, Dojo и т.д. Тестирование может проводиться как модульное так и функциональное, вплоть до полной имитации действий пользователя в браузере.
Инструмент PhantomJS используется для запуска веб-страниц из консоли и основан на движке WebKit. Он достаточно широко освещен в русскоязычном сегменте интернета, в том числе на Хабре. В отличие от инструмента Siesta, по которому информации «кот наплакал».
Собственно, поэтому и пишу данный пост.
Необходимые условия
- Вы уже умеете запускать тесты Siesta из браузера (если нет, то вам сюда). Для примера, будем запускать наши тесты по адресу
http://localhost/tests/index.html
- У вас установлен PhantomJS (если нет, то сюда)
Необходимый код
Мною был написан скрипт-ранер run-siesta.js для PhantomJS, чтобы запускать тесты Siesta.
var start = new Date().getTime(), system = require('system'), page = require('webpage').create(); console.log('\nStart tests...\n'); /** * Лог. */ var globalLog = (function() { var store = []; return { /** * Добавляет сообщение в лог. * * @param msg */ add: function(msg) { store.push(msg); }, /** * Выводит логи в консоль. */ console: function() { var log = ''; for (var i= 0; i < store.length; i++) { log += store[i] + '\n'; } console.log(log); } }; }()); if (system.args.length !== 2) { globalLog.add('Usage: phantomjs run-siesta.js URL'); myExit(1); } /** * Завершает работу программы и возвращает в консоль числовой код. * * @param exitCode код завершения (0 - ОК) */ function myExit(exitCode) { globalLog.add('Total time: ' + (new Date().getTime() - start) + ' ms'); globalLog.add('Exit code: ' + exitCode); globalLog.console(); phantom.exit(exitCode); } /** * Отслеживает сообщения консоли на странице. * @param msg */ page.onConsoleMessage = function(msg) { if (msg.match(/END_TESTS/)) { var exitCode = page.evaluate( function() { var totalPass = document.getElementsByClassName('total-pass')[0].innerText; var totalFail = document.getElementsByClassName('total-fail')[0].innerText; if (totalFail !== '0') { console.log('\nFailed!'); } else { console.log('\nCompleted!'); } console.log('\nTotal pass: ' + totalPass); console.log('Total fail: ' + totalFail); return totalFail === '0' ? 0 : 1; } ); myExit(exitCode); } else if (!msg.match(/\[object Object\]/)) { console.log(msg); } }; /** * Открывает страницу. * @param {String} URL страницы */ page.open(system.args[1], function(status) { if (status !== "success") { globalLog.add("Unable to access network"); myExit(1); } } );
Данный код использует API PhantomJS для запуска страницы c тестами и выводит в консоль логи, которые формируются на странице index.html.
Как вы уже знаете, index.html включает в себя скрипт index.js, который описывает конфигурацию запуска тестов. Простой пример index.js приведен на официальном сайте Siesta.
Чтобы тесты запускались автоматически необходимо добавить в конфигурацию опцию:
autoRun: true
Таким образом, при обращении PhantomJS к странице, тесты будут запускаться автоматически. Если вам необходимо автозапускать тесты и через браузер, то это делается через меню настроек страницы, выбрав опцию “Auto launch”.
Для того, чтобы PhantomJS получал информацию о каждом пройденном тесте, необходимо использовать событие Siesta — testfinalize, которое выбрасывается каждый раз при завершении очередного теста. Обработчик этого события добавляется в конфигурацию и выводит информацию о пройденном тесте в консоль страницы (которую в свою очередь подхватывает PhantomJS с помощью page.onConsoleMessage).
Завершение всех тестов отслеживается с помощью события testsuiteend. Обработчик этого события выводит в консоль специальный код, который знает PhantomJS. Благодаря чему он может завершить свою работу и вывести итоговую информацию в консоль.
listeners: { testfinalize: function(event, test) { var fail = test.$failCount, pass = test.$passCount; var log = (fail ? '~~~~~~~~\n FAILED ' : '[PASSED] ') + test.url + ' [pass: ' + pass + ', fail: ' + fail + ']' + (fail ? '\n~~~~~~~~' : ''); console.log(log); }, testsuiteend: function(event, harness) { console.log('END_TESTS'); } }
Если собрать все вместе, используя простой пример с оф. сайта Siesta, то index.js будет выглядеть так
var Harness = Siesta.Harness.Browser.ExtJS; Harness.configure({ title : 'Awesome Test Suite', // автозапуск тестов autoRun : true, preload : [ // version of ExtJS used by your application '../ext-4.1.1/resources/css/ext-all.css', '../resources/yourproject-css-all.css', // version of ExtJS used by your application '../ext-4.1.1/ext-all-debug.js', '../yourproject-all.js' ], listeners: { // добавляем обработчик события о заврешении очередного теста testfinalize: function(event, test) { var fail = test.$failCount, pass = test.$passCount; var log = (fail ? '~~~~~~~~\n FAILED ' : '[PASSED] ') + test.url + ' [pass: ' + pass + ', fail: ' + fail + ']' + (fail ? '\n~~~~~~~~' : ''); console.log(log); }, // добавляем обработчик события о заврешении всего пакета тестов testsuiteend: function(event, harness) { console.log('END_TESTS'); } } }); Harness.start( '010_sanity.t.js', '020_basic.t.js' );
При завершении тестов run-siesta.js парсит тестовую страницу на общее количество пройденных тестов, выводит общее затраченное время и возвращает соответствующий числовой идентификатор в консоль (0 – успех, 1 — ошибка), что важно для CI.
Пример того, как все это выглядит в действии
TODO
Необходимо предусмотреть возможность завершения работы PhantomJS по таймауту, на тот случай, если он никогда не получит код завершения END_TESTS.
Итог
Понадобилось всего два небольших файлика с несложным кодом, чтобы сэкономить 499$.
Профит?
ссылка на оригинал статьи http://habrahabr.ru/post/189144/
Добавить комментарий