- PVSM.RU - https://www.pvsm.ru -

Запуск тестов Siesta из консоли с помощью PhantomJS

Здесь будет рассказано как запустить тесты Siesta из консоли не используя платную (стандартную) версию продукта (которая стоит 499$).

Проблема

Дело в том, что бесплатная (лайт) версия инструмента Siesta [1] позволяет запускать тесты только из браузера. А если вам понадобиться запускать тесты для CI из консоли, то придется обратить свой взор на стандартную версию, которая имеет много вкусностей, в том числе и запуск из консоли. Сам инструмент использует широко известный бесплатный движок PhantomJS для запуска своих тестов.

Решение

Изучив документацию Phantom JS, Siesta и готовые примеры для запуска тестов Jasmine и QUnit, мною было написано немного кода, позволяющего сэкономить наши с вами деньги.

Краткий обзор инструментария

Инструмент Siesta [1] написан на фреймворке ExtJS [2]. Это мощное средство предназначено для тестирования javascript-приложений написанных с помощью различных популярных фреймворков таких как: ExtJS, jQuery, Dojo и т.д. Тестирование может проводиться как модульное так и функциональное, вплоть до полной имитации действий пользователя в браузере.

Инструмент PhantomJS [3] используется для запуска веб-страниц из консоли и основан на движке WebKit. Он достаточно широко освещен в русскоязычном сегменте интернета, в том числе на Хабре. В отличие от инструмента Siesta, по которому информации «кот наплакал».

Собственно, поэтому и пишу данный пост.

Необходимые условия

  1. Вы уже умеете запускать тесты Siesta из браузера (если нет, то вам сюда [4]). Для примера, будем запускать наши тесты по адресу http://localhost/tests/index.html
  2. У вас установлен PhantomJS (если нет, то сюда [5])
Необходимый код

Мною был написан скрипт-ранер run-siesta.js [6] для PhantomJS, чтобы запускать тесты Siesta.

Код run-siesta.js

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 [4] приведен на официальном сайте Siesta.

Чтобы тесты запускались автоматически необходимо добавить в конфигурацию опцию:

autoRun: true

Таким образом, при обращении PhantomJS к странице, тесты будут запускаться автоматически. Если вам необходимо автозапускать тесты и через браузер, то это делается через меню настроек страницы, выбрав опцию “Auto launch”.

Для того, чтобы PhantomJS получал информацию о каждом пройденном тесте, необходимо использовать событие Siesta — testfinalize [7], которое выбрасывается каждый раз при завершении очередного теста. Обработчик этого события добавляется в конфигурацию и выводит информацию о пройденном тесте в консоль страницы (которую в свою очередь подхватывает PhantomJS с помощью page.onConsoleMessage).

Завершение всех тестов отслеживается с помощью события testsuiteend [8]. Обработчик этого события выводит в консоль специальный код, который знает 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 [6] будет выглядеть так

Код 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.

Пример того, как все это выглядит в действии

скриншот

Запуск тестов Siesta из консоли с помощью PhantomJS
TODO

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

Итог

Понадобилось всего два небольших файлика с несложным кодом, чтобы сэкономить 499$.

Профит?

Автор: dew1983

Источник [9]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/40320

Ссылки в тексте:

[1] Siesta: http://www.bryntum.com/products/siesta/

[2] ExtJS: http://www.sencha.com/products/extjs/

[3] PhantomJS: http://phantomjs.org/

[4] сюда: http://www.bryntum.com/docs/siesta/#!/guide/siesta_getting_started-section-4

[5] сюда: http://phantomjs.org/download.html

[6] run-siesta.js: https://github.com/suvorov/run-siesta

[7] testfinalize: http://www.bryntum.com/docs/siesta/#%21/api/Siesta.Test-event-testfinalize

[8] testsuiteend: http://www.bryntum.com/docs/siesta/#!/api/Siesta.Harness-event-testsuiteend

[9] Источник: http://habrahabr.ru/post/189144/