Непрерывная интеграция ZF проекта при помощи Hudson & Phing

Дальнейшим этапом развития моих отношений с CI стала настройка выполнения юнит тестов в Zend Framework проекте при деплойменте через Phing, а также последующее отображение результатов в Hudson.

Zend Framework

В качестве примера я возьму базовый ZF проект созданный при помощи Zend Tool (также можно использовать NetBeans).

/var/www/test/ $ zf create project hudson
Creating project at /var/www/test/hudson
Note: This command created a web project, for more information setting up your VHOST, please see docs/README

Чтобы вам было удобней следить за ходом событий я положил все в репозиторий на GitHub и по ходу написания статьи буду выкладывать туда все материалы.

PHPUnit

Все знают/слышали о юнит тестировании и TDD. Все знают что это true way при разработке ПО. И в то же время мало кто эти практики применяет. Парадокс :).

«Жизнь дается человеку один раз и прожить ее надо так, чтобы не было мучительно больно за бесцельно прожитые годы».

Пишите тесты. Изначально они потребуют больше времени на разработку, но в последствии экономят множество времени/средств/нервов при внедрении новых фич в готовый проект.

На тему юнит тестов в ZF есть хороший скринкаст от Jon Lebensold и статья “Юнит тестирование приложений на Zend Framework’е” от Антона Шевчука.
Установке описана в офф. мануале по PHPUnit.

Для того, чтобы заработали тесты в созданном проекте нужно отредактировать конфиги phpunit.xml, добавить начальную инициализацию среды в application/bootstrap.php, а также создать сами тесты для IndexController и ErrorController.
Непосредственно код, который я добавил к проекту, можно посмотреть нужно посмотреть в diff на GitHub.

В первую очередь нужно убедиться, что тесты выполняются:

/var/www/test/hudson/tests $ phpunit 
PHPUnit 3.4.13 by Sebastian Bergmann.
 
..
 
Time: 3 seconds, Memory: 15.50Mb
 
OK (2 tests, 7 assertions)

Тесты работают. Приятно :)

Phing

Для дальнейшего деплоймента при помощи Phing нужно создать файл build.xml примерно такого содержания:

<?xml version="1.0" encoding="UTF-8"?>
<project name="zf-sample" basedir="." default="build">
    <property name="builddir" value="./build" />
    <property name="sourcedir" value="application" />
    <property name="logsdir" value="${builddir}/logs" />
 
    <target name="init">
        <mkdir dir="${builddir}" />
        <mkdir dir="${logsdir}" />
        <!--<mkdir dir="${logsdir}/coverage" />-->
    </target>
 
    <target name="clean">
        <echo msg="Clean..." />
        <delete dir="${builddir}" />
    </target>
 
    <target name="build" depends="clean,init,phpcpd,phpunit" />
 
    <!-- PHP copy/paste analysis -->
    <target name="phpcpd">
        <phpcpd>
            <fileset dir="${sourcedir}" id="filestocpd">
                <include name="**/*.php"/>
            </fileset>
            <formatter type="pmd" outfile="${logsdir}/pmd.xml"/>
        </phpcpd>
    </target>
 
    <!-- PHPUnit tests -->
    <target name="phpunit">
        <coverage-setup database="${logsdir}/coverage.db">
            <fileset dir="${sourcedir}">
                <include name="**/*.php"/>
            </fileset>
        </coverage-setup>
 
        <phpunit codecoverage="true">
            <formatter todir="${logsdir}" type="xml" outfile="phpunit.xml" />
            <batchtest>
                <fileset dir="tests">
                    <include name="**/*Test*.php"/>
                    <exclude name="**/Abstract*.php"/>
                </fileset>
            </batchtest>
        </phpunit>
    </target>
</project>

Все настройки для phpunit тасков можно увидеть в офф. документации по Phing.

Запускаем:

/var/www/test/hudson $ phing 
Buildfile: /var/www/test/hudson/build.xml
 
calculator > clean:
 
     [echo] Clean...
   [delete] Deleting directory /var/www/test/hudson/build
 
calculator > init:
 
    [mkdir] Created dir: /var/www/test/hudson/build
    [mkdir] Created dir: /var/www/test/hudson/build/logs
 
calculator > phpcpd:
 
Overriding previous definition of reference to filestocpd
   [phpcpd] Processing files...
   [phpcpd] Finished copy/paste detection
 
calculator > phpunit:
 
[coverage-setup] Setting up coverage database for 3 files
 
calculator > build:
 
 
BUILD FINISHED
 
Total time: 0.7262 seconds

Опять приятно :)

Hudson

Прежде всего у вас должны быть установлены активны плагины Hudson xUnit plugin и Hudson GIT plugin.

Создаем новый проект:
* New Job “zf-sample” => “Build a free-style software project”.
Вбиваем настройки для GIT:
* “Source Code Management” => GIT => git://github.com/stfalcon/zf-sample.git
И делаем пробный билд.

У меня шарик зеленый. Если у вас красный, тогда нужно внимательно почитать лог в Console Output.

Добавляю обработку отчетов по выполнению тестов и по поиску копипаста.
В настройках проекта добавляю Phing targets:
* “Build” => “Add build step” => “Invoke Phing targets”
и действия которые будут выполнятся после билда:
* “Publish testing tools result report” => “build/logs/phpunit.xml”
* “Publish duplicate code analysis results” => “build/logs/pmd.xml”

Делаю новый билд:

На этом этапе проект выглядит следующим образом — https://github.com/stfalcon/zf-sample/tree/4e406948940e6ffa6d830c7b2bf18d99d8ac3b00.

А если будет крах?

Пробую поломать тесты/проект и накопипастить —
https://github.com/stfalcon/zf-sample/commit/8e30d64e1c5bd9309c8f12bfa3183d2d28a1a1b7

Перебор — билд сразу фейлится из-за фатальной ошибки:

Fatal error: Cannot redeclare ErrorController::getLog() in /var/lib/hudson/jobs/zf-sample/workspace/application/controllers/ErrorController.php on line 54

Правлю код — https://github.com/stfalcon/zf-sample/commit/bc85da93637e29aefc9a2062c93911a0298fdf6a
В следующем билде получаем желтый шарик и сразу видим какие проблемы есть на проекте:

А такие графики видно на главной странице проекта в Hudson:

To be continued…

На этом закругляюсь. В следующей заметке я затрону тему Code coverage.

PS. На написание таких заметок уходит уйма времени. Но я надеюсь, что сэкономлю время тем, кто будет разбираться в CI после меня :).

PS2. Этот текст набирал в VIM. Потратил несколько часов на его тюнинг и очень доволен результатом :). Спасибо @farazdagi ;).

3 thoughts on “Непрерывная интеграция ZF проекта при помощи Hudson & Phing

  1. Дякую за статті, Степан.
    Вони дійсно економлять багато часу (особливо коли його немає).
    Пиши і далі!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>