Voilà, c’est fait ! Vous êtes venus à Devoxx France, vous avez assisté à ma présentation (ou alors vous avez juste lu mon post sur le sujet), et donc vous voulez désormais chouchouter votre code JavaScript.

Pour démarrer sur le sujet, vous avez suivi les étapes écrites sur mon post, comme je l’ai fait lors de ma présentation. C’est bien joli tout ça, mais dans la vraie vie réelle, vous n’avez pas un module Maven dédié au code JavaScript. Votre code JavaScript est (bêtement) dans votre application web ! Du coup, vous vous posez des questions sur la façon de procéder, en particulier concernant les analyses Sonar…

Allez zou, suivez le guide !

Zou, créons un projet

Lors de ma présentation, j’ai utilisé l’archetype Maven de.akquinet.javascript.archetypes:javascript-quickstart, qui crée un squelette d’application contenant juste du JavaScript.
Cette fois-ci, on va partir d’un projet web classique dans lequel on incluera notre code JavaScript. Donc quelque chose de plus proche que ce que vous avez sur votre projet !

Je pars donc avec l’archetype org.codehaus.mojo.archetypes:webapp-javaee6 pour avoir un squelette d’application web. Il s’agit là de votre propre projet web… De mon côté, j’y ajoute une petite classe Java, ainsi qu’une class de test JUnit pour le fun.

Désormais, on peut lancer une première analyse Sonar, avec la commande mvn clean install sonar:sonar.

Jusqu'ici, tout va bien !

Maintenant, je rajoute mon code JavaScript (les fichiers underscore.js et undescore-test.js). Je les positionne respectivement dans les répertoires src/main/javascript et src/test/javascript. Il est possible d’adapter ces répertoires, bien entendu !
On ajoute le fichier de configuration de jsTestDriver.conf qui va nous permettre de lancer nos tests JavaScript de Jasmine. On ajoute aussi dans un coin (le répertoire lib/ disons) :

  • le fichier jasmine.js ;
  • le fichier jasmineAdapter.js (pour lancer les tests JavaScript écrits en Jasmine avec js-test-driver) ;
  • la librairie coverage-1.3.4.b.jar, qui est le plugin de calcul de couverture du code JavaScript pour js-test-driver.

Au final, la structure de mon projet a la tête suivante :

chouchoutage (oui, c'est le nom pourri de mon projet)
  + pom.xml
  ` src
      + lib
      |   ` coverage-1.3.4.b.jar
      |   ` jasmine.js
      |   ` jasmineAdapter.js
      + main
      |   + java
      |   |   ` ze-code-java
      |   ` javascript
      |       ` underscore.js
      + test
      |   + java
      |   |   ` test-unitaires
      |   ` javascript
      |       ` underscore-test.js
      ` webapp
          ` toute-la-partie-web

Si vous souhaitez plus d’informations sur cette étape (comme le contenu du fichier jsTestDriver.conf par exemple), allez jeter un oeil sur mon post décrivant ma session Devoxx.

Voilà, on arrive à quelque chose qui ressemble en gros à votre projet. Maintenant, on va voir comment on va pouvoir exécuter nos codes JavaScript, et en faire l’analyse Sonar.

Ne tombons pas dans les poms !

Attaquons nous au problème principal : la modification du pom. Nous allons d’abord l’adapter pour exécuter nos tests JavaScript. Nous verrons ensuite pour l’analyse Sonar…

Ajoutons d’abord la dépendance suivante :

    <dependency>
        <groupId>com.googlecode.jstd-maven-plugin</groupId>
        <artifactId>jstd-maven-plugin</artifactId>
        <version>1.3.2.5</version>
        <scope>test</scope>
    </dependency>

On ajoute ensuite le plugin de jstd-maven-plugin :

    <plugin>
        <groupId>com.googlecode.jstd-maven-plugin</groupId>
        <artifactId>jstd-maven-plugin</artifactId>
        <version>1.3.2.5</version>
        <configuration>
            <port>9876</port>
            <!-- A adapter ! -->
            <browser>/Applications/Firefox.app/Contents/MacOS/firefox-bin</browser>
            <tests>all</tests>
            <config>jsTestDriver.conf</config>
            <testOutput>target/jstestdriver</testOutput>
        </configuration>
        <executions>
            <execution>
                <id>run-tests</id>
                <goals>
                    <goal>test</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

Dernier point, nous ajoutons le repository contenant les plugins sus-cités :

    <repositories>
          <repository>
              <id>jstd-maven-plugin google code repo</id>
              <url>http://jstd-maven-plugin.googlecode.com/svn/maven2</url>
          </repository>
    </repositories>
    <pluginRepositories>
          <pluginRepository>
              <id>jstd-maven-plugin google code repo</id>
              <url>http://jstd-maven-plugin.googlecode.com/svn/maven2</url>
          </pluginRepository>
    </pluginRepositories>

Voilà, nous pouvons vérifier si cela fonctionne. La commande mvn clean install va nous le dire :

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running fr.linsolas.WorldTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.053 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- jstd-maven-plugin:1.3.2.5:test (run-tests) @ chouchoutage ---

-------------------------------------------
 J S  T E S T  D R I V E R
-------------------------------------------

Firefox: Runner reset.
................
Total 16 tests (Passed: 16; Fails: 0; Errors: 0) (10,00 ms)
  Firefox 9.0.1 Mac OS: Run 16 tests (Passed: 16; Fails: 0; Errors 0) (10,00 ms)

C’est plutôt une bonne nouvelle ça ! Surefire a lancé mon test JUnit (fr.linsolas.WorldTest), puis, dans un second temps, a exécuté les tests de js-test-driver.

Plongeons dans l’analyse Sonar

Et bien voilà, il ne nous reste plus qu’à exécuter une analyse Sonar et le tour est joué… Mais ce n’est pas si simple en fait !
Sonar permet bien d’analyser un projet Java, il permet d’analyser également un projet JavaScript, mais hélas pas en même temps !
Nous allons devoir donc lancer deux analyses Sonar pour arriver à nos fins.

Etant donné que nous ne voulons pouvoir lancer avec le même pom.xml l’analyse Sonar pour le code Java et l’analyse Sonar pour le code JavaScript, nous allons créer un profil Maven qui sera dédié à l’analyse JavaScript :

    <profiles>
        <profile>
            <id>js</id>
            <properties>
                <sonar.language>js</sonar.language>
                <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
            </properties>
        </profile>
    </profiles>

Voyons voir si cela fonctionne. Lançons une première analyse avec mvn clean install sonar:sonar. En exécutant cette commande, l’analyse Sonar ne montre aucune différence avec celle réalisée plus tôt. Normal, me direz-vous, on reste sur l’analyse Java.
Lançant maintenant la même commande, mais en activant le profile js : mvn -Pjs clean install sonar:sonar. Le résultat n’est pas celui attendu :

Ooooups

Houlà, mais on a tout cassé ! On n’obtient plus aucun chiffre, ni rien :( Le problème vient simplement du fait que le plugin JavaScript pour Sonar va chercher les sources dans le répertoire src/main/java au lieu de src/main/javascript.
Il faut donc lui spécifier ce nouveau répertoire. On va donc spécifier un sourceDirectory dans notre profile js. Du moins on aimerait bien, car hélas Maven n’autorise pas que l’on redéfinisse ce répertoire dans un profil ! C’est étrange, mais c’est comme ça. Enfin pas tant que ça, car Maven – par défaut – n’accepte qu’un seul chemin de sources. Comme plusieurs profiles peuvent être actifs en même temps, on pourrait bidouiller les profiles pour avoir ainsi plusieurs répertoires de sources. On s’égare un peu là…
Nous pourrions passer par le plugin build-helper qui permet de spécifier plusieurs répertoires de sources. Je n’en ferais rien, je vais « simplement » fourvoyer Maven en jouant avec les propriétés :

    <properties>
        <source.dir>src/main/java</source.dir>
        <test.source.dir>src/test/java</test.source.dir>
    </properties>

    <build>
        <sourceDirectory>${source.dir}</sourceDirectory>
        <testSourceDirectory>${test.source.dir}</testSourceDirectory>
        ...
    </build>

    <profiles>
        <profile>
            <id>js</id>
            <properties>
                <source.dir>src/main/javascript</source.dir>
                <test.source.dir>src/test/javascript</test.source.dir>
                ...

Voilà, Maven n’y voit que du feu, et moi j’ai réussi à me débrouiller (à bidouiller disons plutôt).

Alors, que donne l’analyse Sonar maintenant ?

Voilà qui est mieux !

OUI ! Enfin, nous réussissons à obtenir notre belle analyse du code JavaScript par Sonar !

Et voilà, c’est fini.
Vraiment ? Non !
Un dernier souci se pose : si je lance l’analyse Java, j’ai un beau rapport Sonar. Mais dès que je lance l’analyse JavaScript, mon rapport JavaScript efface celui de Java !
Il faut donc trouver un moyen de faire cohabiter les deux. Je propose simplement de profiter de l’option sonar.branch pour différencier les deux projets. On ajoute donc dans le profil js :

    <profiles>
        <profile>
            <id>js</id>
            <properties>
                <sonar.branch>javascript</sonar.branch>
                ...

Cette fois-ci, on relance les deux analyses : mvn clean install sonar:sonar puis mvn -Pjs clean install sonar:sonar.
Une fois les deux commandes terminées, nous nous retrouvons avec non plus un mais deux projets Sonar :

Les deux font la paire

Chacun de ces projets est adapté à son langage, le premier pour Java, le second pour JavaScript.

Et voilà, c’est fini.
Vraiment ? Cette fois, oui :)

N’hésitez pas à faire part, dans les commentaires, de vos propres expériences, ou propositions d’améliorations !

Start Slide Show with PicLens Lite PicLens