14 февраля 2013 г.

Selenium тестирование PHP-проекта из Jenkins (ч2)

Статья является продолжением статьи о настройке системы непрерывного интегрирования Jenkins.
Здесь рассматривается решение вопроса автоматического конвертирования html-тестов в php с последующим запуском их через Ant с помощью системы непрерывной интеграции Jenkins на Windows.

Оглавление:
1. Запуск готовых Selenium-тестов подготовленных для PHPUnit
2. Selenium2php - автоматическое конвертирование HTML тестов Selenium в phpunit-тесты
3. Еще больше автоматизации
4. Результат

Возможно, вам так же будет интересна статья Установка и настройка Jenkins + Vagrant + Selenium с нуля на Linux (Debian).


1. Запуск готовых Selenium-тестов подготовленных для PHPUnit

Если вы установили Jenkins на отдельный компьютер/виртуальную машину, то производить Selenium-тестирование можно на этом же отдельном. Если же на этом компьютере нельзя запустить браузер или этот компьютер используется для разработки, то запуск браузеров лучше производить на удаленном компьютере. Для этого нужно указать адрес и порт, где установлен Selenium-сервер. Кроме того, нужно подготовить тестовый проект. Один из вариантов как всё сделать это описан мной ранее. Перед запуском тестов нужно обновить тестовый проект. Для этого можно добавить новую цель для ant
<target name="update-test" description="Update test host">
  <exec executable="cmd" dir="${test_project_dir}" failonerror="true">
    <arg value="/c"/>
    <arg value="hg"/>
    <arg value="pull"/>
    <arg value="-u"/>
    <arg value="-f"/>
    <arg value="${mercurial_repo_url}"/>
  </exec>
</target>
Здесь мной использованы переменный ant, которые можно указать в Jenkins в настройках проекта, раздел Сборка, расширенные настройки, поле "Свойства"
mercurial_repo_url=http://webpro:8000/portal/
test_project_dir=D:/www/projects/test_portal

Рассмотрим три варианта запуска Selenium-тестов с помощью Jenkins. Все три варианта запускают файлы тестов, которые наследуют PHPUnit_Extensions_SeleniumTestCase. Для успешного запуска мне пришлось использовать phpunit.phar вместо PEAR-пакета phpunit. Для этого я оставил phpunit.bat для запуска PEAR пакета, а для Selenium я создал рядом с php.exe новый файл phpunit_phar.bat:
%~dp0/php.exe %~dp0/phpunit.phar %*

Вариант 1
Используем NetBeansSuite.php, который принимает аргумент run= с путём, в котором нужно искать файлы тестов.
<exec executable="phpunit_phar.bat" failonerror="true">
    <arg value="--no-configuration"/>
    <arg value="--log-junit"/>
    <arg value="${basedir}/build/selenium/junit.xml"/>
    <arg value="NetBeansSuite"/>
    <arg value="cli/NetBeansSuite.php"/>
    <arg value="run=${basedir}/selenium-tests"/>
  </exec>
Здесь указаны параметры:
  • --no-configuration - не искать файлы конфигурации (не делать анализ покрытия кода),
  • --log-junit - сохранить лог в ${basedir}/build/selenium/junit.xml (для этого в целях clean и prepare нужно добавить путь для создания этой пустой директории),
  • NetBeansSuite - используем этот класс для запуска тестов, подключая его в cli/NetBeansSuite.php,
  • run=${basedir}/selenium-tests - искать файлы тестов *Test.php в этой директории и вложенных.
Вариант 2
Создаем отдельный файл настроек phpunit, например, phpunit_selenium.xml:
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         strict="true"
         verbose="true">

 <testsuites>
    <testsuite name="Portal Selenium">
      <directory suffix="Test.php">selenium-tests/</directory>
    </testsuite>
  </testsuites>

  <logging>
    <log type="junit" target="build/selenium/junit.xml" logIncompleteSkipped="false"/>
  </logging>

</phpunit>
И пропишем в цель использование этого файла:
<exec executable="phpunit_phar.bat" failonerror="true">
    <arg value="--configuration"/>
    <arg value="phpunit_selenium.xml"/>
</exec>

Вариант 3
Используем передачу аргументов в запуск вместо использования конфигурационного файла:
<exec executable="phpunit_phar.bat" dir="${basedir}/selenium-tests" failonerror="true">
      <arg value="--no-configuration"/>
      <arg value="--log-junit"/>
      <arg value="${basedir}/build/selenium/junit.xml"/>
      <arg value="./"/>
  </exec>
Здесь мы указываем директорию, в которой искать тесты, отключаем конфигурацию по умолчанию и настраиваем всё тот же вывод логов.

2. Selenium2php - автоматическое конвертирование html тестов Selenium в phpunit-тесты

Selenium IDE - отличный способ создания и редактирование тестов для вашего веб-проекта. Но для автоматизации тестирования и сбора отчетов нам приходилось вручную запускать дополнение PHP Formatters, конвертировать, сохранять и править. Я искал готовые инстурменты для автотизации этого процесса, но не нашел, поэтому сделал свой - selenium2php. Запускать его следует из командной строки. Например, чтобы конвертировать все *.html файлы из директории d:\www\portal\selenium-html-tests в формат PHPUnit_Extensions_SeleniumTestCase:
php.exe <путь/до/selenium2php.php> d:\www\portal\selenium-html
Я добавил возможность указать некоторые параметры для удобства, полный список есть на гитхабе и в справке. На данный момент не все функции конвертируются корректно, но те, что я использовал в Selenium IDE конвертируются корректно.

3. Еще больше автоматизации

Так как редактирование тестов я провожу в Selenium IDE, а selenium2php позволяет создать php-аналоги, то я решил отказаться от хранение php-версий в репозитории проекта, а создавать их с помощью Ant через Jenkins.
На машине с Jenkins я скопировал selenium2php в директорию рядом с php.exe и создал файл selenium2php.bat с содержимым:
%~dp0/php.exe %~dp0/selenium2php/selenium2php.php %*
Это позволит запускать selenium2php из любой директории.

В build.xml я добавил цель:
 <target name="selenium2php" description="Build php code from html files">
  <exec executable="selenium2php.bat" failonerror="true">
    <arg value="-r"/>
    <arg value="--class-prefix=S2p_"/>
    <arg value="--browser-url=${selenium_url}"/>
    <arg value="--remote-host=${selenium_remote_host}"/>
    <arg value="--dest=${basedir}/build/selenium-tests"/>
    <arg path="${basedir}/tests_selenium/html"/>
  </exec>
 </target>
Описание параметров:
  • -r - производить поиск html-файлов во вложенных каталогах;
  •  --class-prefix=S2p_ - добавить префикс ко всем классам, чтобы в случае ошибки, быть уверенным, что она произошла в автоконвертированном классе;
  • --browser-url=${selenium_url} - указание URL-адреса, который будет проставлен во все тесты; не забыть в Jenkins передать этот параметр (расширенные настройки вызова Ant);
  • --remote-host=${selenium_remote_host} - то же, что и выше, но для адреса Selenium-сервера;
  • --dest=${basedir}/build/selenium-tests - путь для выходящих php-файлов; перед каждой сборкой она очищается;
  • path="${basedir}/tests_selenium/html" - путь, где искать html-файлы тестов.

Созданную цель я добавил в цель с именем "build" перед запуском Selenium-тестов:
 <target name="build" depends="prepare,lint,phploc,pdepend,phpmd-ci,phpcpd,phpunit,selenium2php,selenium,phpcb"/>
Далее нужно обновить путь для поиска phpunit-тестов в цели selenium:
<target name="selenium" description="Update test host and run Selenium tests with PHPUnit">
  <exec executable="cmd" dir="${test_project_dir}" failonerror="true">
    <arg value="/c"/>
    <arg value="hg"/>
    <arg value="pull"/>
    <arg value="-u"/>
    <arg value="-f"/>
    <arg value="${mercurial_repo_url}"/>
  </exec>
  
  <exec executable="phpunit_phar.bat" dir="${basedir}/build/selenium-tests" failonerror="true">
      <arg value="--no-configuration"/>
      <arg value="--log-junit"/>
      <arg value="${basedir}/build/selenium/junit.xml"/>
      <arg value="./"/>
  </exec>
</target>
Теперь можно фиксировать, выталкивать и запускать обновленную сборку.

Результат

Теперь при сборке проекта Selenium-тестирование будет происходить по автоконвертированным тестам, а по журналу ошибок из имени класса можно определить какой html-файл дал ошибку и, при необходимости, можно воспроизвести html-тест с помощью Selenium IDE уже вручную.

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

2 комментария:

  1. Добрый день.
    Провожу анализ инструментов тестирования фронтенда в частности Selenium2.
    От внедрения меня настораживает тот факт что для selenium IDE в оф магазине приложений firefox есть php formatter только для 1й версии, а для второй версии я нашёл githab 2 инструмента ваш и ещё 1, но оба не поддерживались более 2 лет. Да и в принципе как-то всё что я встречал по нему отдаёт древностью.

    Это подводит меня к вопросу, в эпоху быстро развивающегося фронтенда, не устарел ли selenium? Может посоветуете посмотреть на его альтернативы, я гуглю вроде есть какие-то casperjs, mocha и т.д.?

    ОтветитьУдалить
    Ответы
    1. Здравствуйте.
      Сам по себе Selenium не устарел, но вот использование именно Selenium IDE - довольно редко. Люди пишут сценарии тестирования вручную в коде своего любимого языка программирования.

      Удалить