Запуск тестов в selenium на сервере без монитора
Перед каждым разработчиком рано или поздно встает вопрос тестирования его кода. При чем unit-тестирование покрывает не всегда и не все нужды. Для более полного обеспечения качества создаваемого проекта приходится прибегать и к приемочному тестированию.
На сегодняшний день дела обстоят более менее не плохо. Есть набивший многим оскомину селениум. Есть Mink Константина Кудряшова, который позволяет писать функциональные/приемочные тесты в достаточно дружелюбном стиле. И при чем в качестве драйвера использовать не только селениум, среди перечня доступных есть вполне достойный безголовый zombie. Но, после моих тестов наиболее точным тестирование оказалось только через селениум. Зомби по каким-то причинам выкидывал ошибки при парсинге jquery.
Но, минус селениума в том, что ему для работы нужен браузер (по традиции firefox). А firefox требует для запуска дисплей. А на моем сервере, который используется для Continuous Integration монитора нет (это же сервер). Решение было найдено в лице утилиты Xvfb, представляющей из себя виртуальный дисплей.
sudo apt-get install xvfb
На просторах сети даже описываются способы создания скриншотов сайтов с её помощью.
Запуск дисплея
Запуск программ, которые будут отображать свой гуй на виртуальном мониторе осуществляется командой:
xvfb-run [OPTION ...] COMMAND
Run COMMAND (usually an X client) in a virtual X server environment.
Options:
-a --auto-servernum try to get a free server number, starting at
--server-num
-e FILE --error-file=FILE file used to store xauth errors and Xvfb
output (default: /dev/null)
-f FILE --auth-file=FILE file used to store auth cookie
(default: ./.Xauthority)
-h --help display this usage message and exit
-n NUM --server-num=NUM server number to use (default: 99)
-l --listen-tcp enable TCP port listening in the X server
-p PROTO --xauth-protocol=PROTO X authority protocol name to use
(default: xauth command's default)
-s ARGS --server-args=ARGS arguments (other than server number and
"-nolisten tcp") to pass to the Xvfb server
(default: "-screen 0 640x480x8")
В нашем случае требуется запустить в окружении этой утилиты именно селениум:
DISPLAY=:99 xvfb-run -a -n 1 -l -s "-screen 0, 1024x768x8" java -jar /usr/local/bin/selenium-server
Но, это еще не все. Мало запустить selenium, нужно ещё и тесты. Тогда команда запуска тестов будет представлять примерно следующий вид:
DISPLAY=:99 xvfb-run -a -n 1 -l -s "-screen 0, 1024x768x8" java -jar /usr/local/bin/selenium-server.jar & php bin/phpunit -c test/phpunit.xml
Здесь сначала активируем виртуальный дисплей
DISPLAY=:99 xvfb-run -a -n 1 -l -s "-screen 0, 1024x768x8"
потом запускаем selenium, который будет выводить на этом дисплее окно firefox
java -jar /usr/local/bin/selenium-server.jar
и наконец запускаем сами тесты
& php bin/phpunit -c test/phpunit.xml
Запуск PHP
Но, тут есть один нюанс. А именно, selenium должен обращаться к какому-то веб-серверу. Если CI работает не под root (что скорее всего), то он вряд ли сможет перед началом тестирования сборки запускать nginx или apache с виртуальным хостом в нужной директории. Тогда вспоминаем, что в php 5.4 нам подарили built-in server, для запуска которого достаточно выполнить команду
php -S localhost:8888
чтобы запустить сервер на соответствующем хосте и порту.
Чтобы реализовать у себя запуск сервера перед тестами и его остановку после, воспользуемся примером из статьи Using PHP’s built-in web server in your test suites. Для этого внесем в начало bootstrap-файла несколько строк кода:
$host = 'localhost';
$port = '8888';
// Command that starts the built-in web server
$command = sprintf('php -S %s:%d -t %s >/dev/null 2>&1 & echo $!', $host, $port, '.');
// Execute the command and store the process ID
$output = array();
exec($command, $output);
sleep(1);
$pid = (int) $output[0];
echo sprintf('%s - Web server started on %s:%d with PID %d', date('r'), $host, $port, $pid) . PHP_EOL;
// Kill the web server when the process ends
register_shutdown_function(function() use ($pid) {
echo sprintf('%s - Killing process with ID %d', date('r'), $pid) . PHP_EOL;
exec('kill ' . $pid);
});
$startUrl = sprintf('http://%s:%s', $host, $port);
Далее значение $startUrl
можно использовать в тестах, для определения адреса сервера, на котором запущен проект.
Продуктивного тестирования!
Автор: keltanas
comments powered by Disqus