Comment surveiller la
qualité de vos projets PHP
au quotidien ?
« L'intégration continue est un ensemble de
pratiques qui consistent à véri er à chaque
changement du code source que le résultat
des modi cations ne produit pas de
régression de l'application en cours de
développement »    Wikipedia
Quels avantages ?
Quelles pratiques au
    quotidien ?
q    Maintenir un dépôt unique de code versionné
q    Tous les développeurs committent quotidiennement
q    Automatiser les compilations (builds)
q    Tout commit doit compiler le tronc du code versionné
q    Maintenir une compilation courte en permanence
q    Rendre disponible le résultat du build à tout le monde
q    Automatiser le déploiement
Alice

                                Build
                                Successful
           SCM Server
  Bob




  Carlos
                        CI Server
Alice

                                          Build Failed

                 SCM Server
  Bob




  Carlos   Alerter l’équipe   CI Server
Alice

                                Build
                                Successful
           SCM Server
  Bob




  Carlos
                        CI Server
Quelles PIC sur le
   marché ?
Mettre en œuvre
une PIC pour PHP
q    Exécution de la suite de tests unitaires (PHPUnit)
q    Génération du rapport de couverture de code (PHPUnit)
q    Génération de la documentation d’API (PHPDocumentor)
q    Génération du rapport des dépendances (PDepend)
q    Analyse statique du code source (PMD)
q    Détection des violations de codage (PHP_CodeSniffer)
q    Détection du code dupliqué (PHPCPD)
q    Génération du navigateur de code (PHP Code Browser)
q    Hudson rebaptisé Jenkins en février 2011
q    Ecrit en Java
q    Exécute des tâches Ant, Maven, Shell et Windows
q    +300 plugins
q    Analyse des rapports de compilation
q    Génération de statistiques et de graphiques (métriques)
http://jenkins-ci.org
$ java –jar jenkins.war
http://localhost:8080
q    XDebug              q    PHPUnit 3.6.x

q    PDepend             q    PHPCPD

q    PHP Mess Detector   q    PHP Documentor

q    PHP CodeSniffer      q    PHP CodeBrowser
$ pecl install xdebug

$   pear   channel-discover   pear.pdepend.org
$   pear   channel-discover   pear.phpmd.org
$   pear   channel-discover   pear.phpunit.de
$   pear   channel-discover   components.ez.no
$   pear   channel-discover   pear.symfony-project.com
$   pear   channel-discover   pear.phing.info

$   pear   install   phing/phing
$   pear   install   pdepend/PHP_Depend-beta
$   pear   install   phpmd/PHP_PMD-alpha
$   pear   install   phpunit/phpcpd
$   pear   install   PHPDocumentor
$   pear   install   PHP_CodeSniffer
$   pear   install   --alldeps phpunit/PHP_CodeBrowser-alpha
$   pear   install   --alldeps phpunit/PHPUnit
Plugins Jenkins
q    Subversion       q    JDepend
q    Git              q    PMD
q    Checkstyle       q    Violations
q    Dry              q    xUnit
q    HTML Publisher   q    Clover
q    Green Balls
Démarrer un projet
Projet free-style
Con guration du projet
Con guration du dépôt Subversion
Dé nition des droits d’accès au SVN
Con guration du dépôt Git
Con guration des builds
Exécution et contrôle du build
Exécution et contrôle du build
Phing
q    Phing est un portage de Ant en PHP
q    Outil d’automatisation de tâches
q    Phing exécute des tâches à la suite
q    Les tâches sont décrites dans un chier build.xml
q    Supporte les dépendances entre les tâches
q    Tâches prédé nies pour PHPUnit, Code Sniffer, PMD…
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">
    <property name="builddir" value="${ws}/build" />
    <property name="srcdir"   value="${project.basedir}" override="true" />
    <property name="package" value="Syndication" override="true" />

    <target name="clean" description="Clean the build environment">
        <delete dir="${builddir}" />
        <delete dir="generatedJUnitFiles" />
    </target>

    <target name="prepare" depends="clean" description="Clean the build
environment">
        <mkdir dir="${builddir}" />
        <mkdir dir="${builddir}/logs" />
        <mkdir dir="${builddir}/logs/coverage" />
        <mkdir dir="${builddir}/docs" />
        <mkdir dir="${builddir}/browser" />
    </target>

    <target name="build" depends="prepare" description="Build the project">
        <!-- build target commands here -->
    </target>
</project>
phing –f $WORKSPACE/build.xml build –Dws=$WORKSPACE
PHPUnit
http://phpunit.de/
q    Exécuter les tests unitaires

q    Générer un rapport JUnit

q    Générer un rapport Clover XML

q    Générer un rapport de couverture HTML
<?xml version="1.0" encoding="UTF-8"?>

<phpunit backupGlobals="false" backupStaticAttributes="false"
         colors="true" convertErrorsToExceptions="true"
         convertNoticesToExceptions="true" convertWarningsToExceptions="true"
         processIsolation="true" stopOnFailure="false"
         syntaxCheck="false" bootstrap="src/autoload.php">

  <testsuites>
      <testsuite name="Syndication Component Test Suite">
          <directory>./tests/Syndication/</directory>
      </testsuite>
  </testsuites>

  <filter>
      <whitelist>
           <directory>./src/Syndication/</directory>
      </whitelist>
  </filter>
</phpunit>
<?xml version="1.0" encoding="UTF-8"?>

<project name="Syndication Component" basedir="." default="main">

   <!-- ... -->

   <target name="build" depends="prepare"
       description="Building the project">
       <phingcall target="phpunit" />
   </target>

   <target name="phpunit"
       description="Running unit tests and coverage analysis">
       <exec command="phpunit
           --log-junit ${builddir}/logs/phpunit.xml
           --coverage-clover ${builddir}/logs/coverage/clover.xml
           --coverage-html ${builddir}/logs/coverage/ ${ws}/tests"
       />
   </target>

</project>
Con gurer la suite de tests unitaires
Con gurer la couverture de code
Analyse de la couverture de code
Analyse des rapports de tests unitaires
Analyse des rapports de tests unitaires
Publication de la couverture de code
Publication de la couverture de code
PHPDocumentor
 http://www.phpdoc.org/
Générer la documentation d’API
<project name="Syndication Component" basedir="." default="main">

   <target name="build" depends="prepare">
       <phingcall target="phpunit" />
       <phingcall target="phpdoc" />
   </target>

    <!-- Generating API Documentation -->
    <target name="phpdoc" description="Generating api doc">
        <phpdoc title="Syndication API Documentation"
            destdir="${builddir}/docs" sourcecode="true"
            parseprivate="true" output="HTML:Smarty:PHP">
            <fileset dir="./src">
                <include name="**/*.php" />
            </fileset>
        </phpdoc>
    </target>
</project>
Publication de la documentation d’API
Publication de la documentation d’API
PHPCPD
     Copy Paste Detector
https://github.com/sebastianbergmann/phpcpd
Rechercher les duplications de code
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">

    <!-- ... -->
    <target name="build" depends="prepare">
        <phingcall target="phpunit" />
        <phingcall target="phpdoc" />
        <phingcall target="phpcpd" />
    </target>

    <!-- Detecting duplicated code -->
    <target name="phpcpd" description="Detecting duplicated code">
        <exec command="phpcpd
            --min-lines 5
            --min-tokens 5
            --log-pmd ${builddir}/logs/pmd-cpd.xml src/" />
     </target>
</project>
Ce graphique montre que le
code dupliqué a bien été
retiré dans le nouveau
commit qui a donné lieu au
dernier build.



Le graphique ci-contre
montre l’évolution du nombre
de tests unitaires réussis au
dernier build.
PHP Depend
http://pdepend.org/
Analyse statique du code
q    Complexité cyclomatique
q    Qualité globale du code
q    Nombre de classes / méthodes / fonctions / interfaces
q    Nombre d’appels d’une méthode
q    Nombre de propriétés / méthodes publiques vs privées
q    Nombre de lignes de code en commentaires….
Analyse statique du code




   build/logs/jdepend.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">

    <!-- ... -->
    <target name="build" depends="prepare">
        <phingcall target="phpunit" />
        <phingcall target="phpdoc" />
        <phingcall target="phpcpd" />
        <phingcall target="pdepend" />
    </target>

    <target name="pdepend" description="Generating JDepend
report">
         <exec command="pdepend
             --jdepend-xml=${builddir}/logs/jdepend.xml src/" />
    </target>
</project>
PHP Mess Detector
  http://phpmd.org/
Analyse statique du code
q     PHP Mess Detector est un portage en PHP de PMD (Java)
q     Recherche de bugs potentiels
q     Recherche de code mort (ie: méthodes non appelées)
q     Code non optimisé
q     Expressions trop complexes…
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">

   <!-- ... -->
   <target name="build" depends="prepare">
       <phingcall target="phpunit" />
       <phingcall target="phpdoc" />
       <phingcall target="phpcpd" />
       <phingcall target="pdepend" />
       <phingcall target="pmd" />
   </target>

    <target name="phpmd" description="Generating PHPMD report">
        <exec command="phpmd src/ xml codesize,unusedcode --
reportfile ${builddir}/logs/pmd.xml" />
    </target>

</project>
PHP Code Sniffer
http://pear.php.net/manual/en/package.php.php-codesniffer.php
q    Analyse des violations de codage

q    Nombreuses règles par défaut

q    Standards prédé nis : PEAR, Zend, Squiz, PHPCS…

q    Possibilité d’ajouter des règles supplémentaires
Installation du standard Symfony2
$ # Looking for the PEAR PHP directory
$ pear config-show | grep php_dir

$ # Move to the CodeSniffer standards folder
$ cd /path/to/pear/PHP/CodeSniffer/Standards

$ # Checkout the Symfony2 CodeSniffer standard from Github
$ git clone git://github.com/opensky/Symfony2-coding-standard.git Symfony2

$ # Eventually, set Symfony2 as your default CodeSniffer standard
$ phpcs --config-set default_standard Symfony2
Installation du standard Symfony2




   build/logs/checkstyle.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">

   <target name="build" depends="prepare">
       <phingcall target="phpunit" />
       <phingcall target="phpdoc" />
       <phingcall target="phpcpd" />
       <phingcall target="pdepend" />
       <phingcall target="phpmd" />
       <phingcall target="checkstyle" />
   </target>

   <target name="checkstyle" description="Looking for violations">
       <exec command="phpcs --standard=Symfony2 --report=checkstyle
           ${project.basedir}/src > ${builddir}/logs/checkstyle.xml"
           escape="false" />
   </target>

</project>
PHP Code Browser
https://github.com/mayflower/PHP_CodeBrowser
build/browser
<?xml version="1.0" encoding="UTF-8"?>
<project name="Syndication Component" basedir="." default="main">
    <!-- ... -->
    <target name="build" depends="prepare">
        <phingcall target="phpunit" />
        <phingcall target="phpdoc" />
        <phingcall target="phpcpd" />
        <phingcall target="pdepend" />
        <phingcall target="phpmd" />
        <phingcall target="checkstyle" />
        <phingcall target="phpcb" />
    </target>

    <target name="phpcb" description="Generating code browser...">
        <exec command="phpcb
              --log ${builddir}/logs
              --source ${project.basedir}/src
              --output ${builddir}/browser" />
    </target>
</project>
Prévenir plutôt que
      guérir!
q    Emails    q    RSS

q    Twitter   q    SMS

q    Jabber    q    …
Comment industrialiser la PIC
d’un projet PHP dans Jenkins ?
http://jenkins-php.org/
Aller plus loin avec Jenkins
q    Générer des archives PHAR, PEAR, TAR ou ZIP

q    Automatiser le déploiement des builds stables

q    Faciliter les audits de code

q    Intégration avec un bug tracker (Trac, Redmine, Jira)

q    Exécution de tests Sélénium / Fitness

q    …
Merci !
Ques%ons?	
  




 92-98, boulevard Victor Hugo
 92 115 Clichy Cedex
 trainings@sensio.com (+33 (0)1 40 99 82 11)

 sensiolabs.com - symfony.com – trainings.sensiolabs.com

Intégration Continue PHP avec Jenkins CI

  • 2.
    Comment surveiller la qualitéde vos projets PHP au quotidien ?
  • 3.
    « L'intégration continue estun ensemble de pratiques qui consistent à véri er à chaque changement du code source que le résultat des modi cations ne produit pas de régression de l'application en cours de développement » Wikipedia
  • 4.
  • 5.
  • 6.
    q  Maintenir un dépôt unique de code versionné q  Tous les développeurs committent quotidiennement q  Automatiser les compilations (builds) q  Tout commit doit compiler le tronc du code versionné q  Maintenir une compilation courte en permanence q  Rendre disponible le résultat du build à tout le monde q  Automatiser le déploiement
  • 7.
    Alice Build Successful SCM Server Bob Carlos CI Server
  • 8.
    Alice Build Failed SCM Server Bob Carlos Alerter l’équipe CI Server
  • 9.
    Alice Build Successful SCM Server Bob Carlos CI Server
  • 10.
    Quelles PIC surle marché ?
  • 12.
  • 13.
    q  Exécution de la suite de tests unitaires (PHPUnit) q  Génération du rapport de couverture de code (PHPUnit) q  Génération de la documentation d’API (PHPDocumentor) q  Génération du rapport des dépendances (PDepend) q  Analyse statique du code source (PMD) q  Détection des violations de codage (PHP_CodeSniffer) q  Détection du code dupliqué (PHPCPD) q  Génération du navigateur de code (PHP Code Browser)
  • 15.
    q  Hudson rebaptisé Jenkins en février 2011 q  Ecrit en Java q  Exécute des tâches Ant, Maven, Shell et Windows q  +300 plugins q  Analyse des rapports de compilation q  Génération de statistiques et de graphiques (métriques)
  • 17.
  • 18.
    $ java –jarjenkins.war
  • 19.
  • 20.
    q  XDebug q  PHPUnit 3.6.x q  PDepend q  PHPCPD q  PHP Mess Detector q  PHP Documentor q  PHP CodeSniffer q  PHP CodeBrowser
  • 21.
    $ pecl installxdebug $ pear channel-discover pear.pdepend.org $ pear channel-discover pear.phpmd.org $ pear channel-discover pear.phpunit.de $ pear channel-discover components.ez.no $ pear channel-discover pear.symfony-project.com $ pear channel-discover pear.phing.info $ pear install phing/phing $ pear install pdepend/PHP_Depend-beta $ pear install phpmd/PHP_PMD-alpha $ pear install phpunit/phpcpd $ pear install PHPDocumentor $ pear install PHP_CodeSniffer $ pear install --alldeps phpunit/PHP_CodeBrowser-alpha $ pear install --alldeps phpunit/PHPUnit
  • 22.
  • 23.
    q  Subversion q  JDepend q  Git q  PMD q  Checkstyle q  Violations q  Dry q  xUnit q  HTML Publisher q  Clover q  Green Balls
  • 24.
  • 25.
  • 26.
  • 27.
    Con guration dudépôt Subversion
  • 28.
    Dé nition desdroits d’accès au SVN
  • 29.
    Con guration dudépôt Git
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
    q  Phing est un portage de Ant en PHP q  Outil d’automatisation de tâches q  Phing exécute des tâches à la suite q  Les tâches sont décrites dans un chier build.xml q  Supporte les dépendances entre les tâches q  Tâches prédé nies pour PHPUnit, Code Sniffer, PMD…
  • 35.
    <?xml version="1.0" encoding="UTF-8"?> <projectname="Syndication Component" basedir="." default="main"> <property name="builddir" value="${ws}/build" /> <property name="srcdir" value="${project.basedir}" override="true" /> <property name="package" value="Syndication" override="true" /> <target name="clean" description="Clean the build environment"> <delete dir="${builddir}" /> <delete dir="generatedJUnitFiles" /> </target> <target name="prepare" depends="clean" description="Clean the build environment"> <mkdir dir="${builddir}" /> <mkdir dir="${builddir}/logs" /> <mkdir dir="${builddir}/logs/coverage" /> <mkdir dir="${builddir}/docs" /> <mkdir dir="${builddir}/browser" /> </target> <target name="build" depends="prepare" description="Build the project"> <!-- build target commands here --> </target> </project>
  • 36.
    phing –f $WORKSPACE/build.xmlbuild –Dws=$WORKSPACE
  • 37.
  • 38.
    q  Exécuter les tests unitaires q  Générer un rapport JUnit q  Générer un rapport Clover XML q  Générer un rapport de couverture HTML
  • 39.
    <?xml version="1.0" encoding="UTF-8"?> <phpunitbackupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="true" stopOnFailure="false" syntaxCheck="false" bootstrap="src/autoload.php"> <testsuites> <testsuite name="Syndication Component Test Suite"> <directory>./tests/Syndication/</directory> </testsuite> </testsuites> <filter> <whitelist> <directory>./src/Syndication/</directory> </whitelist> </filter> </phpunit>
  • 40.
    <?xml version="1.0" encoding="UTF-8"?> <projectname="Syndication Component" basedir="." default="main"> <!-- ... --> <target name="build" depends="prepare" description="Building the project"> <phingcall target="phpunit" /> </target> <target name="phpunit" description="Running unit tests and coverage analysis"> <exec command="phpunit --log-junit ${builddir}/logs/phpunit.xml --coverage-clover ${builddir}/logs/coverage/clover.xml --coverage-html ${builddir}/logs/coverage/ ${ws}/tests" /> </target> </project>
  • 41.
    Con gurer lasuite de tests unitaires
  • 42.
    Con gurer lacouverture de code
  • 43.
    Analyse de lacouverture de code
  • 44.
    Analyse des rapportsde tests unitaires
  • 45.
    Analyse des rapportsde tests unitaires
  • 46.
    Publication de lacouverture de code
  • 47.
    Publication de lacouverture de code
  • 48.
  • 49.
  • 50.
    <project name="Syndication Component"basedir="." default="main"> <target name="build" depends="prepare"> <phingcall target="phpunit" /> <phingcall target="phpdoc" /> </target> <!-- Generating API Documentation --> <target name="phpdoc" description="Generating api doc"> <phpdoc title="Syndication API Documentation" destdir="${builddir}/docs" sourcecode="true" parseprivate="true" output="HTML:Smarty:PHP"> <fileset dir="./src"> <include name="**/*.php" /> </fileset> </phpdoc> </target> </project>
  • 51.
    Publication de ladocumentation d’API
  • 52.
    Publication de ladocumentation d’API
  • 53.
    PHPCPD Copy Paste Detector https://github.com/sebastianbergmann/phpcpd
  • 54.
  • 55.
    <?xml version="1.0" encoding="UTF-8"?> <projectname="Syndication Component" basedir="." default="main"> <!-- ... --> <target name="build" depends="prepare"> <phingcall target="phpunit" /> <phingcall target="phpdoc" /> <phingcall target="phpcpd" /> </target> <!-- Detecting duplicated code --> <target name="phpcpd" description="Detecting duplicated code"> <exec command="phpcpd --min-lines 5 --min-tokens 5 --log-pmd ${builddir}/logs/pmd-cpd.xml src/" /> </target> </project>
  • 58.
    Ce graphique montreque le code dupliqué a bien été retiré dans le nouveau commit qui a donné lieu au dernier build. Le graphique ci-contre montre l’évolution du nombre de tests unitaires réussis au dernier build.
  • 59.
  • 60.
    Analyse statique ducode q  Complexité cyclomatique q  Qualité globale du code q  Nombre de classes / méthodes / fonctions / interfaces q  Nombre d’appels d’une méthode q  Nombre de propriétés / méthodes publiques vs privées q  Nombre de lignes de code en commentaires….
  • 61.
    Analyse statique ducode build/logs/jdepend.xml
  • 62.
    <?xml version="1.0" encoding="UTF-8"?> <projectname="Syndication Component" basedir="." default="main"> <!-- ... --> <target name="build" depends="prepare"> <phingcall target="phpunit" /> <phingcall target="phpdoc" /> <phingcall target="phpcpd" /> <phingcall target="pdepend" /> </target> <target name="pdepend" description="Generating JDepend report"> <exec command="pdepend --jdepend-xml=${builddir}/logs/jdepend.xml src/" /> </target> </project>
  • 64.
    PHP Mess Detector http://phpmd.org/
  • 65.
    Analyse statique ducode q  PHP Mess Detector est un portage en PHP de PMD (Java) q  Recherche de bugs potentiels q  Recherche de code mort (ie: méthodes non appelées) q  Code non optimisé q  Expressions trop complexes…
  • 67.
    <?xml version="1.0" encoding="UTF-8"?> <projectname="Syndication Component" basedir="." default="main"> <!-- ... --> <target name="build" depends="prepare"> <phingcall target="phpunit" /> <phingcall target="phpdoc" /> <phingcall target="phpcpd" /> <phingcall target="pdepend" /> <phingcall target="pmd" /> </target> <target name="phpmd" description="Generating PHPMD report"> <exec command="phpmd src/ xml codesize,unusedcode -- reportfile ${builddir}/logs/pmd.xml" /> </target> </project>
  • 69.
  • 70.
    q  Analyse des violations de codage q  Nombreuses règles par défaut q  Standards prédé nis : PEAR, Zend, Squiz, PHPCS… q  Possibilité d’ajouter des règles supplémentaires
  • 71.
    Installation du standardSymfony2 $ # Looking for the PEAR PHP directory $ pear config-show | grep php_dir $ # Move to the CodeSniffer standards folder $ cd /path/to/pear/PHP/CodeSniffer/Standards $ # Checkout the Symfony2 CodeSniffer standard from Github $ git clone git://github.com/opensky/Symfony2-coding-standard.git Symfony2 $ # Eventually, set Symfony2 as your default CodeSniffer standard $ phpcs --config-set default_standard Symfony2
  • 72.
    Installation du standardSymfony2 build/logs/checkstyle.xml
  • 73.
    <?xml version="1.0" encoding="UTF-8"?> <projectname="Syndication Component" basedir="." default="main"> <target name="build" depends="prepare"> <phingcall target="phpunit" /> <phingcall target="phpdoc" /> <phingcall target="phpcpd" /> <phingcall target="pdepend" /> <phingcall target="phpmd" /> <phingcall target="checkstyle" /> </target> <target name="checkstyle" description="Looking for violations"> <exec command="phpcs --standard=Symfony2 --report=checkstyle ${project.basedir}/src > ${builddir}/logs/checkstyle.xml" escape="false" /> </target> </project>
  • 76.
  • 77.
  • 78.
    <?xml version="1.0" encoding="UTF-8"?> <projectname="Syndication Component" basedir="." default="main"> <!-- ... --> <target name="build" depends="prepare"> <phingcall target="phpunit" /> <phingcall target="phpdoc" /> <phingcall target="phpcpd" /> <phingcall target="pdepend" /> <phingcall target="phpmd" /> <phingcall target="checkstyle" /> <phingcall target="phpcb" /> </target> <target name="phpcb" description="Generating code browser..."> <exec command="phpcb --log ${builddir}/logs --source ${project.basedir}/src --output ${builddir}/browser" /> </target> </project>
  • 80.
  • 81.
    q  Emails q  RSS q  Twitter q  SMS q  Jabber q  …
  • 82.
    Comment industrialiser laPIC d’un projet PHP dans Jenkins ?
  • 83.
  • 84.
    Aller plus loinavec Jenkins
  • 85.
    q  Générer des archives PHAR, PEAR, TAR ou ZIP q  Automatiser le déploiement des builds stables q  Faciliter les audits de code q  Intégration avec un bug tracker (Trac, Redmine, Jira) q  Exécution de tests Sélénium / Fitness q  …
  • 86.
  • 87.
    Ques%ons?   92-98,boulevard Victor Hugo 92 115 Clichy Cedex trainings@sensio.com (+33 (0)1 40 99 82 11) sensiolabs.com - symfony.com – trainings.sensiolabs.com