Welcome to the second part of the tutorial on the use TeamCity projects php. In this part, I will deal with integration with phpunit.

Integration

Phpunit installation is simple: just issue the following command on the machine where you run the unit tests:
<br />
pear channel-discover pear.phpunit.de<br />
pear channel-discover components.ez.no<br />
pear channel-discover pear.symfony-project.com<br />
pear install phpunit/PHPUnit

This will install all necessary packages.

Now you just have to prepare a configuration file in xml format. I use the following configuration:

<?xml version="1.0" encoding="UTF-8" ?>
<phpunit backupGlobals="false"
        backupStaticAttributes="true"
        bootstrap="bootstrap.php"
        colors="false"
        convertErrorsToExceptions="true"
        convertNoticesToExceptions="true"
        convertWarningsToExceptions="true"
        processIsolation="false"
        stopOnFailure="true"
        syntaxCheck="false"
        verbose="true"
        strict="true">

        <testsuite name="Application">
                <directory>./</directory>
        </testsuite>

        <logging>
                <log type="coverage-clover" target="tests/artifacts/phpunit/coverage.xml" />
                <log type="junit" target="tests/artifacts/phpunit/phpunit.xml" logIncompleteSkipped="true" />
                <log type="testdox-html" target="./logs/testdox.html" />
        </logging>
</phpunit>

Some of you already using phpunit may be surprised at the lack of a html report generation but the reason is very simple: the generation takes too long, it takes too much memory and to generate it several times a day is totally unnecessary.Generating only XML report is faster. I create an additional configuration that adds a command line to generate the HTML report once a week. XML report is needed to track the code coverage testing in the form of a chart – but more on that in a moment, in bonus part – if you do not want to track this information, you can remove the coverage-clover from the process.

Now, we modify the build.xml file created previously:

<?xml version="1.0" encoding="UTF-8"?>
<project name="Application" default="checkout">

    <property name="artifactsDir" value="${basedir}/tests/artifacts" description="Base dir for all output of build commands" />

    <target name="prepare">
        <delete includeemptydirs="true" description="Clear artifacts dir">
            <fileset dir="${artifactsDir}" includes="**/*" />
        </delete>

        <mkdir dir="${artifactsDir}/" />
    </target>

    <target name="checkout" description="Base task - update directory with new version from server and overwrite all conflicts with files from server">
        <exec executable="svn" failonerror="true" output="${artifactsDir}/svn.log">
            <arg line="up" />
            <arg line="--force" />
            <arg line="--accept theirs-full" />
        </exec>
    </target>

    <target name="phpunit" depends="prepare">
        <mkdir dir="${artifactsDir}/phpunit/" description="Make sure that artifacts directory exists" />

        <exec dir="${basedir}" executable="phpunit" failonerror="true" output="${artifactsDir}/phpunit.log" >
            <arg line="--configuration ${basedir}/tests/phpunit.xml" />
        </exec>
    </target>

    <target name="phpunit-html-report" depends="prepare">
        <mkdir dir="${artifactsDir}/phpunit/" description="Make sure that artifacts directory exists" />

        <exec dir="${basedir}" executable="phpunit" failonerror="true" output="${artifactsDir}/phpunit.log">
            <arg line="--configuration ${basedir}/tests/phpunit.xml" />
            <arg line="--coverage-html ${artifactsDir}/phpunit/report" />
        </exec>

        <zip destfile="${artifactsDir}/coverage.zip" basedir="${artifactsDir}/phpunit/report" whenempty="skip" />
    </target>
</project>

Ok. So we have phpunit integration, report generation, special action for HTML report. Now we must import results to TeamCity.

Import data (service messages)

During the integration process script can provide additional information to the server. This can be done either by modifying team-city.xml or by printing messages from a script. The latter seems to be simpler and yet more flexible, so I’ll focus on it is.

Service messages have the following form

##teamcity[message 'value']
##teamcity[message name1='value1' name2='value2']

The first is the message of one argument and the second is a message with multiple arguments. In addition, all messages with multiple arguments support two common arguments: flowid and timestamp. The first takes the time value and the second is used when the integration process involves a number of scripts / tasks running simultaneously. Examples of messages that can be sent:

##teamcity[buildStatus status='' text='{build.status.text} and some aftertext']
##teamcity[message text='' errorDetails='' status='']
##teamcity[testSuiteStarted name='suite.name']
##teamcity[testSuiteFinished name='suite.name']
##teamcity[testStarted name='testname']
##teamcity[testFinished name='testname' duration='50']

And most useful in today’s tutorial:

##teamcity[publishArtifacts '']
##teamcity[importData type='junit' path='' whenNoDataPublished='error']

The aim of such a complex process of integration is the ability to easily change the machine on which the build is performed. To achieve this, the server must know which files contain reports. These messages can be transmitted either from within PHP scripts or through a directive <echo /> in ant scripts. Modified build.xml file looks like this:

<code><?xml version="1.0" encoding="UTF-8"?>
<project name="Application" default="checkout">

    <property name="artifactsDir" value="${basedir}/tests/artifacts" description="Base dir for all output of build commands" />

    <target name="prepare">
        <delete includeemptydirs="true" description="Clear artifacts dir">
            <fileset dir="${artifactsDir}" includes="**/*" />
        </delete>

        <mkdir dir="${artifactsDir}/" />
    </target>

    <target name="checkout" description="Base task - update directory with new version from server and overwrite all conflicts with files from server">
        <exec executable="svn" failonerror="true" output="${artifactsDir}/svn.log">
            <arg line="up" />
            <arg line="--force" />

            <arg line="--accept theirs-full" />
        </exec>

        <echo message="##teamcity[publishArtifacts '${artifactsDir}/svn.log']" description="Import detailed svn log to TeamCity"/>
    </target>

    <target name="phpunit" depends="prepare">
        <mkdir dir="${artifactsDir}/phpunit/" description="Make sure that artifacts directory exists" />

        <exec dir="${basedir}" executable="phpunit" failonerror="true" output="${artifactsDir}/phpunit.log" >
            <arg line="--configuration ${basedir}/tests/phpunit.xml" />
        </exec>

        <echo message="##teamcity[importData type='junit' path='${artifactsDir}/phpunit/phpunit.xml' whenNoDataPublished='error']" description="Import test status to TeamCity"/>
        <echo message="##teamcity[publishArtifacts '${artifactsDir}/phpunit.log']" description="Import phpunit log to TeamCity"/>
    </target>

    <target name="phpunit-html-report" depends="prepare">
        <mkdir dir="${artifactsDir}/phpunit/" description="Make sure that artifacts directory exists" />

        <exec dir="${basedir}" executable="phpunit" failonerror="true" output="${artifactsDir}/phpunit.log">
            <arg line="--configuration ${basedir}/tests/phpunit.xml" />
            <arg line="--coverage-html ${artifactsDir}/phpunit/report" />
        </exec>

        <echo message="##teamcity[importData type='junit' path='${artifactsDir}/phpunit/phpunit.xml' whenNoDataPublished='error']" description="Import test status to TeamCity" />
        <echo message="##teamcity[publishArtifacts '${artifactsDir}/phpunit.log']" description="Import phpunit log to TeamCity" />

        <zip destfile="${artifactsDir}/coverage.zip" basedir="${artifactsDir}/phpunit/report" whenempty="skip" />
        <echo message="##teamcity[publishArtifacts '${artifactsDir}/coverage.zip']" />
    </target>
</project>
</code>

When we inform TeamCity (specifically, the integrating agent installed on the machine where you perform the task), about the location of each file to import, it is possible to perform the integration on any machine. Report files are automatically uploaded from the agent on the server to a known location. File phpunit.xml imported at the end and it will be processed by the server. This will enable the display of number of tests and statistics tracking for a project. This is it for basic integration. The next step is the extra bonus, extending the view of the project with …

Additional statistics

Previously generated xml report can be automatically processed through a small PHP script that displays the most important statistics of the project and allows you to display in a graph.

A simple script that parses the report from first argument is attached to this post.

Now just modify phpunit action with one entry:

<exec dir="${basedir}" executable="php" failonerror="false">
    <arg line="-f ${basedir}/tests/clover_parser.php -- ${artifactsDir}/phpunit/coverage.xml" />
</exec>

Now, during the integration of a set of statistics will be displayed:

##teamcity[buildStatisticValue key='CodeCoverageAbsBCovered' value='245']
##teamcity[buildStatisticValue key='CodeCoverageAbsLCovered' value='209']
##teamcity[buildStatisticValue key='CodeCoverageAbsMCovered' value='36']
##teamcity[buildStatisticValue key='CodeCoverageAbsLTotal' value='979']
##teamcity[buildStatisticValue key='CodeCoverageAbsMTotal' value='85']
##teamcity[buildStatisticValue key='CodeCoverageAbsCTotal' value='8']

It’s enough to display basic statistics in form of graph. To create your own graphs based on your data just to edit a file &lt;TeamCity data dir&gt;/config/main-config.xml for graphs available for all projects or &lt;TeamCity data dir&gt;/config/&lt;Project Name&gt;/plugin-settings.xml for individual projects. &lt;TeamCity data dir&gt; is usually a directory .TeamCity in home directory of the user who runs the server. In these files, simply add:

<graph title="Custom data" seriesTitle="Metric name">
    <valueType key="key1" title="Metric 1" />
    <valueType key="key2" title="Metric 2" />
    <valueType key="BuildDuration" title="Duration" />
</graph>

Substituting, of course, the values ??that we want to present.More information about Service Messages and Custom Charts can be found in the TeamCity manual: service messages and custom charts.

Attachments

  1. clover_parser (1.4 KiB)

22 maja 2011 10:38 Grzegorz Drozd Brak komentarzy Komentuj Kategorie: Narz?dzia, PHP, Praca, TeamCity

Bądź uprzejma(y).

Możesz używać następujących tagów HTML tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Twój adres e-mail nie będzie wyświetlony.

Twój adres e-mail nie będzie przekazany nikomu.

Wszystkie komentarze są moderowane.