Fitnesse, Maven, Sonar : comment faire monter la mayonnaise
Publié le 20/09/2011, par Etienne Charignon dans Agile, Java, Valtech | 8 Commentaires
Comme je le disais récemment dans un tweet, j’ai finalement réussi à configurer le build Maven pour que la couverture du code par les tests, affichée dans le dashboard Sonar, tienne compte des tests Fitnesse.
En voila un sujet pointu ! Pourtant, à la suite de ce tweet, plusieurs personnes m’ont demandé une version longue. Je vais donc essayer dans ce message de décrire en détail la configuration complète que nous avons mise en place. J’espère que vous saurez comprendre le fonctionnement de cette solution, pour ensuite l’adapter à votre situation personnelle. Pour ceux qui ne comprennent pas les 3 premiers mot du titre, vous pouvez si vous le désirez vous plonger dans une bonne demi-heure de perplexité et lire la suite de ce message.
Intégration de Fitnesse dans le build Maven
Nous utilisons Fitnesse comme base de documentation pour notre projet. Le wiki contient toute sorte de documentation, technique ou non, concernant le projet ainsi que, bien entendu, tous les spécifications fonctionnelles automatisées.
Remarque : dans la suite de cet article, je parle indifféremment de spécifications fonctionnelles automatisées, de spécifications exécutables ou de tests Fitnesse. Toutes ces appellations désigne la même chose.
Fitnesse n’utilise pas de base de données, mais une hiérarchie de répertoires et de fichiers textes qui représentent les pages du wiki. L’intégralité du projet Fitnesse est contenu dans un répertoire qui est installé dans la gestion de configuration (sur notre projet, nous avons utilisé Git). Cette solution a l’avantage de permettre à tous les développeurs de l’équipe d’avoir une version complète du site en local sur leur poste. Ils peuvent ainsi exécuter les spécifications localement sur leur poste, avant de soumettre le code et les pages Fitnesse correspondantes à l’intégration continue.
Au niveau du build Maven, nous avons dédié un module à Fitnesse. Voici un extrait du répertoire racine de notre projet :

Vous voyez que dans notre répertoire lcwp-fitnesse (lcwp est le nom du projet) se trouve un fichier pom.xml. Le répertoire src ne contient pas de code. Toutes les pages du wiki sont dans le répertoire FitNesseRoot. Vous voyez aussi le fichier fitnesse.jar qui est l’exécutable proprement dit. Bien qu’il ne soit pas recommandé de mettre des binaires en gestion de configuration, nous faisons une exception pour celui-ci car c’est vraiment plus pratique comme ça.
Le plug-in Maven pour auto-générer le classpath utilisé par Fitnesse
Il s’agit du plugin maven-fitnesse-cpgen-plugin qui se trouve être un plugin développé par Valtech. Pour la documentation, suivez le lien suivant : http://source.valtech.com/maven-sites/maven-fitnesse-cpgen-plugin/usage.html
Installation du plugin
Pour utiliser ce plugin il suffit de référencer le dépôt Maven de Valtech (voir le lien ci-dessus) dans votre fichier setting.xml et d’ajouter la section XML suivante dans le fichier lcwp-fitnesse/pom.xml
<plugin> <groupId>com.valtech.source.maven</groupId> <artifactId>maven-fitnesse-cpgen-plugin</artifactId> <version>1.0</version> <configuration> <fitnesseRoot>${basedir}/FitNesseRoot</fitnesseRoot> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>gencp</goal> </goals> </execution> </executions> </plugin> |
Contenu de la page “root”
Vous devez ensuite modifier le fichier lcwp-fitnesse/FitNesseRoot/content.txt pour qu’il contienne exactement le texte suivant. Ce fichier correspond à la page “root” du site (http://localhost:9090/root) :
!define TEST_SYSTEM {slim}
!include ProjectPath
# begin of maven classpath
# end of maven classpath |
La première ligne ne concerne pas notre sujet. Elle indique que tous nos pages Fitnesse seront exécutés avec le moteur SLIM.
Le plug-in ajoutera tout le classpath maven, dont les dépendances sont décrites dans le pom.xml du module lcwp-fitnesse, entre les deux dernières lignes du fichier.
La page ProjectPath contient des chemins spécifiques qui ne seront pas ajoutés par le plugin et que nous devons donc ajouter nous même. J’en reparlerai plus tard. Elle contient une partie de l’astuce ultime de notre solution.
Problème : ce fichier lcwp-fitnesse/FitNesseRoot/content.txt sera modifié à chaque build et le classpath inséré par Maven sera potentiellement différent pour chaque poste de développeur. Ce fichier ne peut donc pas être géré dans Git (il faut l’ajouter au fichier .gitIgnore).
Astuce : Pour que chaque développeur ne soit pas obligé de créer ce fichier sur son poste, nous avons ajouté la configuration suivante dans notre pom.xml :
<plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.6</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>Fitnesse root</echo> <copy file="src/test/resources/fitnesseRootContent.txt" tofile="${project.basedir}/FitNesseRoot/content.txt" overwrite="true" /> </tasks> </configuration> </execution> </executions> </plugin> |
Le contenu standard du fichier lcwp-fitnesse/FitNesseRoot/content.txt est enregistré dans le fichier src/test/resources/fitnesseRootContent.txt qui lui est géré dans Git. Ce fichier est recopié au moment du build, juste avant l’éxécution du plugin maven-fitnesse-cpgen-plugin.
Propriétés de la page “root”
Enfin, vous devez changer une propriété de la page root pour quelle soit de type “Suite”. C’est nécessaire pour que le plugin maven trouve la page. Vous pouvez le faire par le wiki en vous rendant à l’URL http://localhost:9090/root, en cliquant sur le bouton “Properties” et en sélectionnant “Suite” pour la propriété “Page type”. Alternativement, vous pouvez aussi directement modifier le fichier lcwp-fitnesse/FitNesseRoot/properties.xml pour qu’il contienne la balise <Suite/>. Voici par exemple le contenu de notre fichier :
<?xml version="1.0"?> <properties> <Edit/> <Files/> <Help></Help> <Properties/> <RecentChanges/> <Refactor/> <Search/> <Suite/> <Suites></Suites> <Versions/> <WhereUsed/> </properties> |
Le contenu de la page ProjectPath
Le plugin décrit précédemment nous a permis de gérer simplement le gigantesque classpath des dépendances vers les composants externes de notre projet. C’est la page ProjectPath qui contient les chemins vers le code proprement dit de notre projet. Voici son contenu dans notre cas :
!path ../lcwp-web/target/generated-classes/cobertura !path ../lcwp-web/target/classes !path ../lcwp-core/target/classes !path ../lcwp-integration/target/classes !path ../lcwp-web/target/test-classes !path ../lcwp-test-support/target/classes |
Le chemin est indiqué relativement au répertoire lcwp-fitnesse, c’est pourquoi tout les chemins sont précédés de “../“.
Et voilà la solution du problème : Pour que la couverture des tests affichée dans le dashboard Sonar tienne compte des tests Fitnesse, il faut que ces derniers soit exécutés sur le code instrumenté par cobertura. Le code instrumenté est généré dans le répertoire target/generated-classes/cobertura. Avec la première ligne de notre fichier nous obtiendrons donc la couverture du code du module lcwp-web.
En développement, le répertoire generated-classes/cobertura est vide et c’est la ligne suivante qui permettra de trouver le code du module lcwp-web.
Pour information, nous avons mis le code des fixtures Fitnesse dans l’arborescence de tests du module lcw-web. C’est donc la ligne ../lcwp-web/target/test-classes qui permet de le trouver.
L’exécution des spécifications par Maven
Tout ce que je viens d’expliquer nous permet d’exécuter les spécifications depuis le wiki.
En local sur le poste d’un développeur, vous devez démarrez Fitnesse avec les commandes suivantes :
cd lcwp-fitnesse java -jar fitnesse.jar -p 9090 -e 0 |
Ensuite, vous pouvez vous rendre sur le site à l’URL : http://localhost:9090/FrontPage, naviguer jusqu’à la page de spécification qui vous intéresse et cliquer sur le bouton [Test] (dans la colonne de gauche) pour l’exécuter.
Mais ce que nous voulons, c’est que toutes les spécifications Fitnesse soit exécutées lors du build maven, c’est à dire à l’exécution de la commande mvn clean package
Fitnesse vous propose une ligne de commande pour exécuter tous ses tests :
java -jar fitnesse.jar -c DetailedSpecifications?suite&format=text |
DetailedSpecifications est la page du wiki, racine de toutes nos spécifications. Elle est de type “Suite”.
Nous avons tout d’abord ajouté au build un appel à cette commande en utilisant le plugin ant de maven, mais il nous a paru finalement plus simple de faire un appel système dans un tests unitaire jUnit. En effet, la seule façon de savoir si les tests se sont exécutés correctement est d’analyser la sortie standard, le code de retour de cette commande (code de retour de la JVM en fait) étant zéro dans tous les cas. Il est nettement plus facile d’analyser cette sortie en java qu’avec la configuration XML du plug-in ant de maven.
Ce test unitaire doit faire parti des tests du module lcwp-web (c’est la couverture sur ce module qui nous intéresse). Il doit donc se trouver dans l’arborescence lcwp-web/src/test/java/...
J’ai posté le code sur GitHub à l’URL suivante :
https://github.com/etienneCharignon/FitnesseTools/blob/master/fitnesse/tools/FitnesseTest.java
Conclusion
Une belle image vaut mieux qu’un long discours. Nous sommes passés d’un peu plus de 25% à 65,20 % :


La Marmite est un rendez vous mensuel organisé par