Tag Archives: phpUnderControl

Sonar for PHP coming

sonarI have received a lot of positive feedback after my The Journey towards Continuous Integration talk at PHP NW 2010 conference. It seems that a lot of people have found it both interesting and inspiring. I am really glad. After the talk many people asked me about Sonar which I briefly mentioned and were eager to know more about it. With this blog post I will try to fill the gap in my talk.

Solving the mistery

I have heard about Sonar for the first time about a year ago I think. It looked cool! All the fancy graphs, statistics, numbers… But, first I couldn’t understand how would it actually fit into our development process and secondly it had no support for PHP. A lot of things has changed since then though.

With a continuous integration process nearly in place at work, we now need to properly track the progress not only of the build itself, but also how in overall our code quality changes. We want to know whether the code complies to the rules we have set up, whether over time it gets better and at the same time we want to communicate the progress to the business.  What a surprise for me it was, when I have found out that actually all of that we could achieve with Sonar! And imagine the grin on my face when I was told that there are people that have started working on PHP plugin for Sonar!

Installing Sonar

Installing Sonar is very easy. Sonar runs on any operating system that support Java and Maven. For version 2.1 which I am gonna install you will need Java Development Kit v1.5 or later and Maven 2.0.9+, 2.1.+ or 2.2.+.

If you’re using Ubuntu distribution, just can just follow the instructions below.

To install Sun JDK you need to enable partner repositories first. Just edit /etc/apt/sources.list , uncomment the following lines:

# deb http://archive.canonical.com/ubuntu maverick partner
# deb-src http://archive.canonical.com/ubuntu maverick partner

and install the JDK:

#> sudo apt-get update
#> sudo apt-get install sun-java6-jdk

To install maven you can use apt-get as well:

#> sudo apt-get install maven2

With all the things in place it’s time to download Sonar. You can get it from its download page. Remember that not all plugins are compatible with all Sonar versions, so before you make a decision which version to download check Sonar Compatibility matrix. Because I am gonna use 0.2 version of PHP plugin I will download Sonar 2.1.2.

#> wget http://dist.sonar.codehaus.org/sonar-2.1.2.zip

Installation is as easy as just unpacking the archive:

#> mkdir ~/apps
#> cd ~/apps && unzip /home/proofek/Downloads/sonar-2.1.2.zip

Configuring Sonar

By default Sonar runs with an embedded Apache Derby database. If you want just to play with Sonar or test it then you can just skip the next step, but if you plan to use it later on or you want to install it in a production environment then you better switch to more robust database server like MySQL, Oracle, Postgresql or MS SqlServer. Sonar suports them all. I will install it and configure it with MySQL server.

First, let’s install MySQL server. Again apt comes handy:

#> sudo apt-get install mysql-server

The server should automatically be started after that and should accept any incoming connections. Now we have to create empty database and a user that Sonar will use. Let’s name the database and user sonar and use S0n4rU53r as a password. Obviously it’s up to you how you will call them, just make sure you use the same names later on in Sonar configuration file. Also remember this is only a sample configuration and you might want to configure the access to database differently for security reasons.

#> mysql -uroot -p -e "CREATE DATABASE sonar"
#> mysql -uroot -p -e "CREATE USER 'sonar'@'%' IDENTIFIED BY 'S0n4rU53r'"
#> mysql -uroot -p -e "GRANT ALL ON sonar.* TO 'sonar'@'%'"

Next, edit conf/sonar.properties configuration file, uncomment template for MySQL support and comment out the default Derby configuration.

#sonar.jdbc.url: jdbc:derby://localhost:1527/sonar;create=true
#sonar.jdbc.driver: org.apache.derby.jdbc.ClientDriver
#sonar.jdbc.defaultTransactionIsolation: 1
#sonar.jdbc.validationQuery: values(1)
sonar.jdbc.url: jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8
sonar.jdbc.driver: com.mysql.jdbc.Driver
sonar.jdbc.validationQuery: select 1

At the bottom of that file, in Global database settings section, you can change default database username and password.

sonar.jdbc.username:                       sonar
sonar.jdbc.password:                       S0n4rU53r
sonar.jdbc.maxActive:                      10
sonar.jdbc.maxIdle:                        5
sonar.jdbc.minIdle:                        2
sonar.jdbc.maxWait:                        5000
sonar.jdbc.minEvictableIdleTimeMillis:     600000
sonar.jdbc.timeBetweenEvictionRunsMillis:  30000

If you want to run Sonar on different IP address or port you can configure that at the top of this configuration file:

# Listen host/port and context path (for example / or /sonar). Default values are 0.0.0.0:9000/
#sonar.web.host:                           0.0.0.0
#sonar.web.port:                           9000
#sonar.web.context:                        /

Now we’re ready to start Sonar for the first time. Start  and stop scripts are located in bin directory.

Execute the following script to start the server :

  • on linux/mac : bin/[YOUR PLATEFORM]/sonar.sh start
  • on windows : bin/windows-x86-32/StartSonar.bat

Note that you can also run as a NT service with bin/windows-x86-32/InstallNTService.bat, then bin/windows-x86-32/StartNTService.bat

For Linux start command will look like this:

#> ~/apps/sonar-2.1.2/bin/linux-x86-32/sonar.sh start

and you stop Sonar like this:

#> ~/apps/sonar-2.1.2/bin/linux-x86-32/sonar.sh stop

It gets a while to start it for the first time as the database schema is being set up. Have a look at the log file to see the progress and watch for any issues that might prevent Sonar from starting.

#> tail -f ~/apps/sonar-2.1.2/logs/sonar.log

Message like this indicates that application is ready to use:

2010.11.09 21:55:39 INFO  org.sonar.INFO  Sonar started: http://0.0.0.0:9000/

Just browse now to http://localhost:9000/. Sonar is ready to use.

Sonar dashboard

Sonar dashboard (after first run)

Installing PHP plugin

At the moment (mid Nov 2010), only version 0.2 of the plugin has been released, and you can download it from the official plugin site.

It’s split into 5 separate jar files:

  • core PHP plugin
  • PHPUnit plugin
  • PHP_Codesniffer plugin
  • PHP Depend plugin
  • PHP MD plugin
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-plugin/0.2/sonar-php-plugin-0.2.jar
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-unit-plugin/0.2/sonar-php-unit-plugin-0.2.jar
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-codesniffer-plugin/0.2/sonar-php-codesniffer-plugin-0.2.jar
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-depend-plugin/0.2/sonar-php-depend-plugin-0.2.jar
#> wget http://repository.codehaus.org/org/codehaus/sonar-plugins/sonar-php-pmd-plugin/0.2/sonar-php-pmd-plugin-0.2.jar

But that’s not all. The plugin actually requires the following tools to be installed on a machine that you are going to analyse your project on (and it actually doesn’t have to be the same machine you install Sonar on):

If you are already using them, you will know how to install/configure them. Only PHP_Codesniffer requires special treatment, so I strongly recommend you follow my installation guide for PHP_Codesniffer below. For those of you, who are not really familiar with these tools yet, here is a quick guide how to set them all up.

PHP + PEAR

Fairly simple installation, especially with apt:

#> sudo apt-get install php5-cli
#> php -v
PHP 5.3.3-1ubuntu9.1 with Suhosin-Patch (cli) (built: Oct 15 2010 14:17:04)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
#> sudo apt-get install php-pear
#> pear list
Installed packages, channel pear.php.net:
=========================================
Package          Version State
Archive_Tar      1.3.7   stable
Console_Getopt   1.2.3   stable
PEAR             1.9.1   stable
Structures_Graph 1.0.3   stable
XML_Util         1.2.1   stable

PHPUnit + Xdebug

Now lets use PEAR installer to install PHPUnit. This is a standard installation procedure for PHPUnit.

#> sudo pear channel-discover pear.phpunit.de
#> sudo pear channel-discover components.ez.no
#> sudo pear channel-discover pear.symfony-project.com
#> sudo pear install --alldeps phpunit/PHPUnit
#> phpunit --version
PHPUnit 3.5.3 by Sebastian Bergmann.

and pecl installer to install Xdebug. We will need php sources and some development tools as well, because pecl will actually compile Xdebug on the fly before installing it. For systems from Ubuntu/Debian family just use apt to install php5-dev package.

#> sudo apt-get install php5-dev

And after that install Xdebug and enable the extension by creating xdebug.ini file with the following content:

#> sudo pecl install xdebug
#> sudo vim /etc/php5/conf.d/xdebug.ini
zend_extension=/usr/lib/php5/20090626+lfs/xdebug.so
xdebug.auto_trace = "Off"
xdebug.collect_params = "On"
xdebug.collect_return = "Off"
xdebug.trace_format = "0"
xdebug.trace_options = "1"
xdebug.trace_output_dir = "/local/tmp/xdebug"
xdebug.trace_output_name = "timestamp"
xdebug.profiler_enable = "0"
xdebug.auto_profile = "1"
xdebug.auto_profile_mode = "6"
xdebug.output_dir = "/local/tmp/xdebug"
xdebug.profiler_output_dir = "/local/tmp/xdebug"
xdebug.profiler_output_name = "timestamp"

Refer to Xdebug documentation for specific configuration options. Let’s just verify now that PHP has Xdebug support.

#> php -v
  PHP 5.3.3-1ubuntu9.1 with Suhosin-Patch (cli) (built: Oct 15 2010 14:17:04)
  Copyright (c) 1997-2009 The PHP Group
  Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
      with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans

PHP_Codesniffer

With PHP_Codesniffer it’s a little bit different. The stable version 1.2.2 which is available now (mid Nov 2010) doesn’t support rulesets yet (but bear in mind version 1.3 will). So guys at SQLi have come up with a work around.

First of all if you already have PHP_Codesniffer installed with version bigger then 1.2.2 you have to uninstall it first. And that’s because we have to install a modified version 1.2.3 of PHP_CodeSniffer. BUT REMEMBER, this is not an official release. It has been created specifically to work with Sonar. So:

#> sudo pear uninstall PHP_CodeSniffer

and

#> wget https://www.assembla.com/spaces/sqlics/documents/dSJnowvZqr35SUeJe5cbLr/download/dSJnowvZqr35SUeJe5cbLr -O PHP_CodeSniffer_1.2.3.tgz
#>  sudo pear install ~/Downloads/PHP_CodeSniffer_1.2.3.tgz
#> phpcs --version
PHP_CodeSniffer version 1.2.3 (stable) by Squiz Pty Ltd. (http://www.squiz.net)

Then we have to download and install SQLi Codesniffer which will work like a bridge between Sonar and PHP_Codesniffer.

#> wget https://www.assembla.com/spaces/sqlics/documents/ak6024vZur34RweJe5cbLA/download/ak6024vZur34RweJe5cbLA -O SQLI_CodeSniffer_0.4.0dev1.tgz
#> sudo pear install /home/proofek/Downloads/SQLI_CodeSniffer_0.4.0dev1.tgz
#> sqlics --version
SQLI_CodeSniffer version 0.4.0dev1 (alpha) by SQLI (http://www.sqli.com)

If for any reasons these links or instructions doesn’t work anymore, check the original instructions at SQLi site.

PHP Depend

PHP Depend installation is also a standard one:

#> sudo pear channel-discover pear.pdepend.org
#> sudo pear install pdepend/PHP_Depend-beta
#> pdepend --version
PHP_Depend 0.9.19 by Manuel Pichler

PHPMD

Same with PHP Mess Detector:

#> sudo pear channel-discover pear.phpmd.org
#> sudo pear install --alldeps phpmd/PHP_PMD-alpha
#> phpmd --version
PHPMD 0.2.7 by Manuel Pichler

With all tools in place, just stop Sonar, copy the jar files to Sonar’s plugins directory (~/apps/sonar-2.1.2/extensions/plugins/) and start Sonar again:

#> ~/apps/sonar-2.1.2/bin/linux-x86-32/sonar.sh stop
#> cp sonar-php-plugin-0.2.jar sonar-php-codesniffer-plugin-0.2.jar sonar-php-depend-plugin-0.2.jar sonar-php-pmd-plugin-0.2.jar sonar-php-unit-plugin-0.2.jar /home/proofek/apps/sonar-2.1.2/extensions/plugins/
#> ~/apps/sonar-2.1.2/bin/linux-x86-32/sonar.sh start

If you carefully watch logs now you will see the plugins being loaded and set up!

#> tail -f ~/apps/sonar-2.1.2/logs/sonar.log
2010.11.09 22:51:18 INFO  org.sonar.INFO  Load metrics...
2010.11.09 22:51:19 INFO  org.sonar.INFO  cleaning alert thresholds...
2010.11.09 22:51:19 INFO  org.sonar.INFO  Load metrics done: 1118 ms
2010.11.09 22:51:19 INFO  org.sonar.INFO  Load rules...
2010.11.09 22:51:19 INFO  org.sonar.INFO  loading 365 findbugs rules...
2010.11.09 22:51:21 INFO  org.sonar.INFO  loading findbugs extensions...
2010.11.09 22:51:21 INFO  org.sonar.INFO  loading 97 PHP CODESNIFFER rules...
2010.11.09 22:51:22 INFO  org.sonar.INFO  loading PHP CODESNIFFER extensions...
2010.11.09 22:51:22 INFO  org.sonar.INFO  loading 12 PHP PMD rules...
2010.11.09 22:51:22 INFO  org.sonar.INFO  loading PHP PMD extensions...
2010.11.09 22:51:22 INFO  org.sonar.INFO  loading 123 checkstyle rules...
2010.11.09 22:51:23 INFO  org.sonar.INFO  loading checkstyle extensions...
2010.11.09 22:51:23 INFO  org.sonar.INFO  loading 216 pmd rules...
2010.11.09 22:51:25 INFO  org.sonar.INFO  loading pmd extensions...
2010.11.09 22:51:25 INFO  org.sonar.INFO  loading 3 squid rules...
2010.11.09 22:51:25 INFO  org.sonar.INFO  loading squid extensions...
2010.11.09 22:51:25 INFO  org.sonar.INFO  Load rules done: 6566 ms
2010.11.09 22:51:25 INFO  org.sonar.INFO  Load profiles...
2010.11.09 22:51:27 INFO  org.sonar.INFO  loading findbugs profiles...
2010.11.09 22:51:27 INFO  org.sonar.INFO  loading the profile Sonar way with Findbugs/java from findbugs
2010.11.09 22:51:34 INFO  org.sonar.INFO  loading PHP CODESNIFFER profiles...
2010.11.09 22:51:34 INFO  org.sonar.INFO  loading the profile Default Php Profile/php from PHP CODESNIFFER
2010.11.09 22:51:37 INFO  org.sonar.INFO  loading PHP PMD profiles...
2010.11.09 22:51:37 INFO  org.sonar.INFO  loading the profile Default Php Profile/php from PHP PMD
2010.11.09 22:51:38 INFO  org.sonar.INFO  loading checkstyle profiles...
2010.11.09 22:51:38 INFO  org.sonar.INFO  loading the profile Sonar way/java from checkstyle
2010.11.09 22:51:39 INFO  org.sonar.INFO  loading the profile Sonar way with Findbugs/java from checkstyle
2010.11.09 22:51:40 INFO  org.sonar.INFO  loading the profile Sun checks/java from checkstyle
2010.11.09 22:51:43 INFO  org.sonar.INFO  loading pmd profiles...
2010.11.09 22:51:43 INFO  org.sonar.INFO  loading the profile Sonar way/java from pmd
2010.11.09 22:51:47 INFO  org.sonar.INFO  loading the profile Sonar way with Findbugs/java from pmd
2010.11.09 22:51:51 INFO  org.sonar.INFO  loading the profile Sun checks/java from pmd
2010.11.09 22:51:51 INFO  org.sonar.INFO  loading squid profiles...
2010.11.09 22:51:51 INFO  org.sonar.INFO  activating php default profile...
2010.11.09 22:51:51 INFO  org.sonar.INFO  activating java default profile...
2010.11.09 22:51:51 INFO  org.sonar.INFO  Load profiles done: 25681 ms
2010.11.09 22:51:51 INFO  org.sonar.INFO  Start sonar done: 37528 ms
2010.11.09 22:52:12 INFO  org.sonar.INFO  Loading web services...
2010.11.09 22:52:13 INFO  org.sonar.INFO  Sonar started: http://0.0.0.0:9000/

Preparing for analysis

We’re just about to analyse our first project then. How exciting! There is only a few things left before we can start though.

Sonar uses maven to analyse projects and needs a pom file to perform it. A typical pom file for PHP project looks like this:

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsichemaLocation="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <groupId>group-name</groupId>
    <artifactId>artifact-id</artifactId>
    <name>project-name</name>
    <version>1.0</version>
    <packaging>pom</packaging>
    <build>
        <directory>build-directory</directory>
        <sourceDirectory>source-directory</sourceDirectory>
        <testSourceDirectory>tests-directory</testSourceDirectory>
    </build>
</project>

All you have to do, is to replace underscored values with relevant ones. I’ll show you a complete example of it in a minute.

We need to configure maven first, so it knows how to connect to sonar mysql database. There are two locations, where maven keeps its settings.xml file:

  • The Maven install: $M2_HOME/conf/settings.xml
  • A user’s install: ${user.home}/.m2/settings.xml

Refer to your operating system documentation to find out how maven is installed by default. In Ubuntu/Debian family system global configuration file is in /etc/maven2/settings.xml, while in MacOsX it is in /usr/share/maven/conf/settings.xml.

All we have to do now, is to create custom maven profile and activate it. First locate <profiles> section in the xml file. Although there are a few profile examples inside this section already, they are probably all commented out. We will simply add our profile section to it:

<profiles>
    <!-- profile
    Existing profiles definitions (...)
    -->
    <profile>
        <id>sonar-profile</id>
        <properties>
            <sonar.jdbc.url>jdbc:mysql://localhost:3306/sonar?useUnicode=true&amp;characterEncoding=utf8</sonar.jdbc.url>
            <sonar.jdbc.driver>com.mysql.jdbc.Driver</sonar.jdbc.driver>
            <sonar.jdbc.username>sonar</sonar.jdbc.username>
            <sonar.jdbc.password>S0n4rU53r</sonar.jdbc.password>
        </properties>
    </profile>
</profiles>

Next activate the new profile in activeProfiles section. Remove the comments around this section and just add bolded section to it:

<activeProfiles>
    <activeProfile>sonar-profile</activeProfile>
</activeProfiles>

If there are any profiles activated already there, just simply delete them. They don’t exists anyway and will only cause maven to complain during analysis.

If Sonar has been installed on a separate machine and you want to analyse your project on a different machine, then you will have to adjust sonar.jdbc.url option to point it to the sonar database and at the same time grant relevant permissions to the database itself. Also you have to tell maven how it can access Sonar server by specifying sonar.host.url option in profile section:

<sonar.host.url>http://sonar.server.org/</sonar.host.url>

The last thing we have to do is to switch on a few options and make some tweaks for the PHP plugin itself. Integration with the PHP tools is pretty basic at the moment, but is enough to perform some simple analysis. So I am gonna run Sonar in so called dynamic analysis mode, run the tools manually to create all xml reports, and then run Sonar maven task to parse them and add the results to Sonar dashboard. The only exception will be PHP_CodeSniffer – I will let Sonar run the SQLi version and produce compatible report. Bear in mind in future plugin releases I expect the integration to get much better and then, if  you would like to you will be able to use Sonar to run the tools.

Let’s add the following lines to the maven settings.xml file then:

<profile>
    <id>sonar-profile</id>
    <properties>
        <sonar.jdbc.url>jdbc:mysql://localhost:3306/sonar?useUnicode=true&amp;characterEncoding=utf8</sonar.jdbc.url>
        <sonar.jdbc.driver>com.mysql.jdbc.Driver</sonar.jdbc.driver>
        <sonar.jdbc.username>sonar</sonar.jdbc.username>
        <sonar.jdbc.password>S0n4rU53r</sonar.jdbc.password>
       <sonar.language>php</sonar.language>
       <sonar.dynamicAnalysis>true</sonar.dynamicAnalysis>
       <sonar.phpUnit.analyzeOnly>true</sonar.phpUnit.analyzeOnly>
       <sonar.phpDepend.analyzeOnly>true</sonar.phpDepend.analyzeOnly>
    </properties>
</profile>

Analysing projects with Sonar

I have picked up vfsStream project as an example for analysis. Unfortunately this is the only open source project I have found so far, that requires a minimal effort to get it up and running. I have tried PHPUnit, pdepend, PHP_CodeSniffer, Zend Framework and many many more, but they either fail analysis, they are not compatible with PHPUnit 5.3 yet or they have very custom test suite runners which would need some major changes before we could actually perform analysis.

From my experience so far, Sonar often can not analyse the project because it still has problems parsing coverage report. I expect this to improve in next plugin versions though. Most problems can be solved by stopping using AllTests.php files and properly defining phpunit.xml file with filter whitelist section. I have analysed dosens of projects at work using that approach without a problem.

So let’s get vfsStream sources first:

#> svn checkout http://bovigo.googlecode.com/svn/vfs/trunk/ vfsStream

Let’s make it PHPUnit 3.5 compatible first by removing the following line from src/test/AllTests.php file:

PHPUnit_Util_Filter::addDirectoryToWhitelist(SOURCE_DIR);

Next let’s create a directory we will use to store xml reports in:

mkdir -p build/logs

and run PHPUnit to generate both junit log file and coverage clover report file:

#> phpunit --coverage-clover build/logs/phpunit.coverage.xml --log-junit build/logs/phpunit.xml src/test/AllTests.php
PHPUnit 3.5.3 by Sebastian Bergmann.

............................................................  60 / 169
............................................................ 120 / 169
.................................................

Time: 3 seconds, Memory: 13.75Mb

OK (169 tests, 759 assertions)

Writing code coverage data to XML file, this may take a moment.

vfsStream doesn’t have phpunit.xml file, but fortunately  AllTests.php works just fine.

Now let’s run PHP Depend to create pdepend report.

#> pdepend --phpunit-xml=build/logs/pdepend.xml src/main
PHP_Depend 0.9.19 by Manuel Pichler

Parsing source files:
.........                                                        9

Executing CyclomaticComplexity-Analyzer:
.....                                                          119

Executing ClassLevel-Analyzer:
.....                                                          112

Executing CodeRank-Analyzer:
                                                                10

Executing Coupling-Analyzer:
.......                                                        148

Executing Hierarchy-Analyzer:
......                                                         139

Executing Inheritance-Analyzer:
..                                                              57

Executing NPathComplexity-Analyzer:
.....                                                          119

Executing NodeCount-Analyzer:
......                                                         122

Executing NodeLoc-Analyzer:
......                                                         131

Generating pdepend log files, this may take a moment.

Time: 00:01; Memory: 19.25Mb

With all the reports in place

#> ls -ltr build/logs/
total 184
-rw-r--r--  1 smarek  staff  15565 22 Nov 10:18 pdepend.xml
-rw-r--r--  1 smarek  staff  41787 22 Nov 10:18 phpunit.xml
-rw-r--r--  1 smarek  staff  32455 22 Nov 10:18 phpunit.coverage.xml

it’s time to create pom.xml file based on the template mentioned before. Our pom.xml file will look like this:

<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsichemaLocation="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.googlecode.bovigo</groupId>
<artifactId>vfsStream</artifactId>
<name>vfsStream</name>
<version>1.0</version>
<packaging>pom</packaging>
<build>
    <directory>build</directory>
    <sourceDirectory>src/main</sourceDirectory>
    <testSourceDirectory>src/test</testSourceDirectory>
</build>
</project>

Let’s save the file in top level project directory and run analysis command from there:

smarek@14:~/apps/vfsStream$ mvn sonar:sonar
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'sonar'.
[INFO] Ignoring available plugin update: 2.0-beta-1 as it requires Maven version 3.0
[INFO] ------------------------------------------------------------------------
[INFO] Building vfsStream
[INFO]    task-segment: [sonar:sonar] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] [sonar:sonar {execution: default-cli}]
[INFO] Sonar host: http://localhost:9000
[INFO] Sonar version: 2.1.2
[INFO] Execute: org.codehaus.sonar.runtime:sonar-core-maven-plugin:20101122103356:internal
[INFO] [sonar-core:internal {execution: default-internal}]
[INFO]  Database dialect class org.sonar.api.database.dialect.MySql
[INFO]  -------------  Analyzing vfsStream
[INFO]  Selected quality profile : Default Php Profile, language=php
[INFO]  Configure maven plugins...
[INFO]  Sensor PhpSourceImporter[getLanguage()=PHP,getClass()=class org.sonar.plugins.php.core.sensors.PhpSourceImporter]...
[INFO]  Importing files from project vfsStream
[INFO]  main
[INFO]  test
[INFO]  Sensor PhpSourceImporter[getLanguage()=PHP,getClass()=class org.sonar.plugins.php.core.sensors.PhpSourceImporter] done: 409 ms
[INFO]  Sensor AsynchronousMeasuresSensor...
[INFO]  Sensor AsynchronousMeasuresSensor done: 20 ms
[INFO]  Sensor PhpCodesnifferSensor...
[INFO]  ExecutePHPCodeSniffer with command 'sqlics --report-file=/Users/smarek/apps/vfsStream/build/logs/codesniffer.xml --report=checkstyle --level=warning --standard=GN --extensions=php,php3,php4,php5,phtml,inc /Users/smarek/apps/vfsStream/src/main'
[INFO]  PHPCodeSniffer ended with returned code '1'.
[INFO]  Analysing project with file:/Users/smarek/apps/vfsStream/build/logs/codesniffer.xml
[INFO]  Sensor PhpCodesnifferSensor done: 4233 ms
[INFO]  Sensor SurefireSensor...
[INFO]  parsing /Users/smarek/apps/vfsStream/build/surefire-reports
[INFO]  Sensor SurefireSensor done: 2 ms
[INFO]  Sensor CpdSensor...
[INFO]  Sensor CpdSensor done: 228 ms
[INFO]  Sensor PhpUnitSensor...
[INFO]  Parsing file :
[INFO]  Parsing file : {0}
[INFO]  Sensor PhpUnitSensor done: 637 ms
[INFO]  Sensor ProfileSensor...
[INFO]  Sensor ProfileSensor done: 13 ms
[INFO]  Sensor ProjectLinksSensor...
[INFO]  Sensor ProjectLinksSensor done: 6 ms
[INFO]  Sensor VersionEventsSensor...
[INFO]  Sensor VersionEventsSensor done: 9 ms
[INFO]  Sensor PHP Depend Sensor...
[INFO]  Collecting measures...
[INFO]  Saving measures...
[INFO]  Sensor PHP Depend Sensor done: 173 ms
[INFO]  Sensor Maven dependencies...
[INFO]  Sensor Maven dependencies done: 7 ms
[INFO]  Execute decorators...
[INFO]  ANALYSIS SUCCESSFUL, you can browse http://localhost:9000
[INFO]  Database optimization...
[INFO]  Database optimization done: 83 ms
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 19 seconds
[INFO] Finished at: Mon Nov 22 10:34:50 GMT 2010
[INFO] Final Memory: 25M/81M
[INFO] ------------------------------------------------------------------------

Let’s get back to the browser now and refresh the dashboard.

sonar-vfsStream

Sonar dashboard after running analysis

vfsStream-dashboard

vfsStream analysis details

Congratulations! You have just analysed your first PHP project with Sonar!

Understanding the measures

I will only briefly tell you about different sections of the dashboard this time. Feel free to explore it and remember – there is quite comprehensive documentation at http://www.sonarsource.org/ including wiki, tutorials and even some screencasts!

At the top of the dashboard you have all the results of static code analysis, including all sort of statistics about your code complexity and size.

code-complexity

Code complexity analysis

On the right side of the dashboard, Sonar reports all rules violations generated by PHP_CodeSniffer. Don’t be surprised with the results you see. Remember we didn’t configure the plugin to use any specific standard. 0.2 version of the plugin uses an included GN standard, just for illustration purposes. That will definitely improve in future plugin versions and complete integration with PHP_CodeSniffer 1.3.

rules-violations

Rules violations based on PHP_CodeSniffer report

And finally at the bottom you have got results of the test suite run:

unittest-results

Unit tests results

phpUnderControl integration

Integration with phpUnderControl is really trivial. All you have to do is to add another task to your ant build file and execute it at the end of the build!

<project default="build" basedir=".">

    <!--
    All the other targets here
    -->

    <target name="sonar">
        <exec dir="${basedir}/Source/" executable="mvn" failonerror="false" >
           <arg line="sonar:sonar" />
        </exec>
    </target>

    <target name="build" depends="clean,checkout-code,update-branches,generate-configs,php-documentor,php-codesniffer,php-depend,phpunit,sonar" />

</project>

What’s next?

Version 0.3 of the plugin is coming soon to your houses soon, and with it comes:
  • better integration with PHP_CodeSniffer 1.3 (SQLi CodeSniffer no longer required)
  • rulesets support – import/export feature
  • Copy/Paste detector support (phpcpd)
  • better code coverage analysis
  • one plugin – one jar – easier installation
It will only get better! Happy analysis!

phpUnderControl 0.6.0 released

I am pleased to announce that new version of phpUnderControl is out.

You can install it through its pear channel:

proofek@home:~$ sudo pear channel-discover pear.phpundercontrol.org
Adding Channel "pear.phpundercontrol.org" succeeded
Discovery of channel "pear.phpundercontrol.org" succeeded
proofek@home:~$ sudo pear install --alldeps phpuc/phpUnderControl-0.6.0
downloading phpUnderControl-0.6.0.tgz ...
Starting to download phpUnderControl-0.6.0.tgz (545,857 bytes)
.............................................................................................................done: 545,857 bytes
install ok: channel://pear.phpundercontrol.org/phpUnderControl-0.6.0

or if you already have a previous version simply upgrade:

proofek@home:~$ sudo pear upgrade --alldeps phpuc/phpUnderControl-0.6.0
downloading phpUnderControl-0.6.0.tgz ...
Starting to download phpUnderControl-0.6.0.tgz (545,857 bytes)
.............................................................................................................done: 545,857 bytes
upgrade ok: channel://pear.phpundercontrol.org/phpUnderControl-0.6.0

Release 0.6.0 brings a few new features as well as a few bug fixes.

New Copy/Paste Detector and Changeset tab

Big thanks to hpbuniat for this contribution.
Changeset tab contains details of modifications in the source code since the last successful build. Copy/Paste Detector tab contains report produced by Copy/Paste Detector (CPD) for PHP.

Copy/Paste Detector (CPD) for PHP

PHP-CPD tab

Changeset

Changeset tab

Integrating CPD with phpUnderControl is dead easy. Just install the tool and define another target in your build file. See an example below.

proofek@home:~$ sudo pear channel-discover pear.phpunit.de
proofek@home:~$ sudo pear channel-discover components.ez.no
proofek@home:~$ sudo pear install phpunit/phpcpd
proofek@home:~$ phpcd --version
phpcpd 1.3.1 by Sebastian Bergmann.
<target name="phpcpd" >
    <exec executable="phpcpd" failonerror="false">
        <arg line="--log-pmd ${basedir}/build/logs/pmd-cpd.xml ${basedir}/source/src" />
    </exec>
</target>

With these new features there are also two additional graphs on the metrics tab: Build at Revision Timeline and Duplicated Code

phpUnderControl metrics charts

Metrics tab

More details in PHP-MD and Codesniffer tabs

PHP Mess Detector and Codesniffer tabs got refreshed a little bit and now contain a bit more details.

PHPMD - PHP Mess Detector

PHPMD tab

PHP_Codesniffer

Codesniffer tab

Implemented #665: Display limit for build metrics.

As per Manuel post earlier on, now it is also possible to control maximum number of log entries displayed on the graphs. Simply modify your config file that generates graphs and add –max-number option to it.

<publishers>
    <artifactspublisher dir="projects/${project.name}/build/api" dest="artifacts/${project.name}" subdirectory="api"/>
    <artifactspublisher dir="projects/${project.name}/build/coverage" dest="artifacts/${project.name}" subdirectory="coverage"/>
    <execute command="phpcb --log projects/${project.name}/build/logs --source projects/${project.name}/source/src --output projects/${project.name}/build/php-code-browser"/>
    <artifactspublisher dir="projects/${project.name}/build/php-code-browser" dest="artifacts/${project.name}" subdirectory="php-code-browser"/>
    <execute command="/usr/bin/phpuc graph --max-number 10 logs/${project.name} artifacts/${project.name}"/>
</publishers>

Bug fixes

  • Fixed #771:  Invalid character in CodeSniffer output.
  • Fixed #732: Show revision of SVN/CVS on dashboard. Patch supplied by hpbuniat, through phpunit’s issue tracker.
  • Fixed #1003: Force build button in the /cruisecontrol app doesn’t work.
  • Fixed #1011: Custom ant script now set properly when requested
  • Fixed #1044: callServer should return false. Patch supplied by Mekras in phpunit’s issue tracker.

Joining phpUnderControl development team

I have been using phpUnderControl for over 2 years now. In fact I still remember the first time I set it up at work. Big times. Now we’ve got nearly hundred (if not over hundred) modules set up which build regularly on a daily basis. To improve the overall experience I’ve enhanced some things and submitted it back to the project, but only when project was migrated from SVN to git it really became easy to contribute.

I have been contributing to phpUnderControl quite regularly recently, and when I received a message from Manuel Pichler telling me that I now have write access to project repository and I am part of core development team I couldn’t hide my excitement. That will only mean I can contribute more and often. Hopefully only with benefits to the project.

For now, I can’t wait for the next stable release with its all new features. It’s nearly there! So stay tuned!

Integrate PHP_Depend with phpUnderControl

The newest version of phpUnderControl has now basic support for PHP_Depend. With PHPUnit deprecating support for metrics, it’s just about the time to switch. And it’s not as complicated as it might sound.

First of all you need to install PHP_Depend. Using pear it’s the easiest and quickest way to do it. If you haven’t registered PHP_Depend pear channel yet, it is time to do it now:

141:~ sebmarek$ sudo pear channel-discover pear.pdepend.org
Adding Channel "pear.pdepend.org" succeeded
Discovery of channel "pear.pdepend.org" succeeded

After that simply use pear to install the latest version of PHP_Depend:

141:~ sebmarek$ sudo pear install pdepend/PHP_Depend-beta
Did not download optional dependencies: pecl/imagick, use --alldeps to download automatically
pdepend/PHP_Depend can optionally use package "pecl/imagick" (version >= 2.2.0b2)
downloading PHP_Depend-0.9.11.tgz ...
Starting to download PHP_Depend-0.9.11.tgz (323,787 bytes)
..................................................................done: 323,787 bytes
install ok: channel://pear.pdepend.org/PHP_Depend-0.9.11

and confirm that PHP_Depend installed successfully:

141:~ sebmarek$ pdepend --version
PHP_Depend 0.9.11 by Manuel Pichler

The next step is to modify your project’s build file. If you don’t use phpunit configuration xml file the change is really simple. Just remove –log-metrics option from your phpunit ant task:

<target name="phpunit">
    <exec dir="/pth/to/your/module" executable="phpunit" failonerror="true">
        <arg line="--log-junit ${basedir}/build/logs/phpunit.xml
                   --log-metrics ${basedir}/build/logs/phpunit.metrics.xml
                   --coverage-xml ${basedir}/build/logs/phpunit.coverage.xml
                   --coverage-html ${basedir}/build/coverage" />
    </exec>
</target>

If you use phpunit xml file remove relevant entry from logging section:

<logging>
    <log type="coverage-html" target="/path/to/build/coverage/" charset="UTF-8" yui="true" highlight="false" lowUpperBound="35" highLowerBound="70"/>
    <log type="coverage-clover" target="/path/to/build/logs/phpunit.coverage.xml"/>
    <log type="junit" target="/path/to/build/logs/phpunit.test.xml" logIncompleteSkipped="true"/>
    <log type="metrics-xml" target="/path/to/build/logs/metrics.xml"/>
</logging>

Finally just add new ant task in the build file that will run pdepend and generate metrics xml file and additional graphs.

<target name="php-depend">
    <exec executable="pdepend" dir="${basedir}/Source" logerror="on">
        <arg line="--phpunit-xml=${basedir}/build/logs/pdepend.xml
                   --jdepend-chart=${basedir}/build/graph/08-dependencies.svg
                   --overview-pyramid=${basedir}/build/graph/09-software-metrics-pyramid.svg
                   . " />
    </exec>
</target>

<target name="phpunit">
    <exec dir="${basedir}/Source/Test/" executable="phpunit" failonerror="true" />
</target>

<target name="build" depends="clean,checkout-code,php-documentor,php-codesniffer,php-depend,phpunit" />

Now either wait until next build happens or simply trigger the next build manually and navigate to the metrics tab. All the charts should be still there. In addition two additional charts has been added – Package Dependencies and visual summary of the analyzed project source code.

PHP_Depend metrics

Additional charts generated with PHP_Depend

Package dependencies chart is also shown at the top of phpUnderControl Overview tab.

To learn more about software metric and PHP_Depend itself have a look at Documentation section at http://www.pdepend.org/

Fixing metrics in phpUnderControl 0.5.0

I recently upgraded our buildbox to phpUnderControl 0.5.0 being really curious about new CodeBrowser feature. And indeed CodeBrowser addon is really cool (see Manuel Pichler announcement on his site for details), but after the upgrade I found Metrics tab broken. Instead of nice shiny graphs it showed me Java exception like this:

Metrics exception

Metrics exception

It took me a while to figure out what caused this strange behaviour. I have found the answer when I have run graph generation manually:

#> phpuc graph logs/PHPUnit-3.5/ artifacts/PHPUnit-3.5/

It returned pretty instantly the following error:

The value '1' that you were trying to assign to setting 'labelCount' is invalid. Allowed values are: int > 1.

A little bit of googling and I actually found the answer, again on Manuel Pichler site, in the comments for the announcement.

Basically with phpUnderControl 0.5.0 a file has been released called ClassComplexityInput.php. It is not ready yet to generate a graphs (I suspect it’s gonna be a graph representing class complexity), but phpUnderControl goes through all available input processors to generate graphs for the metrics page.

Fix in that case is pretty trivial, just remove the file (it’s in phpUnderControl/Graph/Input/ directory) and voila – your graphs are back!

Metrics fixed

Metrics fixed