Developpez.com - Java
X

Choisissez d'abord la catégorieensuite la rubrique :


Développons en Java

Par Jean-Michel Doudoux (home)
 

Développons en Java : didactiel de JM-Doudoux, Version 0.8


50. Ant
50.1. Installation de Ant
50.1.1. Installation sous Windows
50.2. Exécuter ant
50.3. Le fichier build.xml
50.3.1. Le projet
50.3.2. Les commentaires
50.3.3. Les propriétés
50.3.4. Les ensembles de fichiers
50.3.5. Les ensembles de motifs
50.3.6. Les listes de fichiers Le tag <filelist> permet de définir une liste de fichiers finis. Chaque fichier est nommément ajouté dans laliste, séparé chacun par une virgule. La définition d'un tel élément est réalisée grace à des attributs du tag <filelist> :
50.3.7. Les éléments de chemins
50.3.8. Les cibles
50.4. Les tâches (task)
50.4.1. echo
50.4.2. mkdir
50.4.3. delete
50.4.4. copy
50.4.5. tstamp
50.4.6. java
50.4.7. javac
50.4.8. javadoc
50.4.9. jar
51. Maven
51.1. Installation
51.2. Les plug-ins
51.3. Le fichier project.xml
51.4. Exécution de Maven
51.5. Génération du site du projet
51.6. Compilation du projet
52. Les frameworks de tests
52.1. JUnit
52.1.1. Un exemple très simple
52.1.2. Exécution des tests avec JUnit
52.1.2.1. Exécution des tests dans la console
52.1.2.2. Exécution des tests dans une application graphique
52.1.3. Ecriture des cas de tests JUnit
52.1.3.1. Définition de la classe de tests
52.1.3.2. Définition des cas de tests
52.1.3.3. La création et la destruction d'objets
52.1.4. Les suites de tests
52.1.5. L'automatisation des tests avec Ant
52.1.6. Les extensions de JUnit
52.2. Cactus
53. Des bibliothèques open source
53.1. JFreeChart
54. Des outils open source pour faciliter le développement
54.1. CheckStyle
54.1.1. Installation
54.1.2. Utilisation avec Ant
54.1.3. Utilisation en ligne de commandes
54.2. Jalopy
54.2.1. Utilisation avec Ant
54.2.2. Les conventions
54.3. XDoclet
54.4. Middlegen


50. Ant

Ant est un projet du groupe Apache-Jakarta. Son but est de fournir un outil écrit en Java pour permettre la construction d'applications (compilation, exécution de tâches post et pré compilation ... ). Ces processus de construction d'applications sont très importants car ils permettent d'automatiser des opérations répétitives tout au long du cycle de développement de l'application (développement, tests, recettes, mises en production ... ). Le site officiel de l'outil Ant est http://jakarta.apache.org/ant/index.html.

Ant pourrait être comparé au célèbre outil make sous Unix. Il a été développé pour fournir un outil de construction indépendant de toute plate-forme. Ceci est particulièrement utile pour des projets développés sur et pour plusieurs systèmes ou pour migrer des projets d'un système sur un autre. Il est aussi très efficace pour de petits développements.

Ant repose sur un fichier de configuration XML qui décrit les différentes tâches qui devront être exécutées par l'outil. Ant fournit un certain nombre de tâches courantes qui sont codées sous forme d'objets développés en Java. Ces tâches sont donc indépendantes du système sur lequel elles seront exécutées. De plus, il est possible d'ajouter ces propres tâches en écrivant de nouveaux objets Java respectant certaines spécifications.

Le fichier de configuration contient un ensemble de cibles (target). Chaque cible contient une ou plusieurs tâches. Chaque cible peut avoir une dépendance envers une ou plusieurs autres cibles pour pouvoir être exécutée.

Les environnements de développement intégrés proposent souvent un outil de construction propriétaire qui son généralement moins souple et moins puissant que Ant. Ainsi des plug-ins ont été développés pour la majorité d'entre eux (JBuilder, Forte, Visual Age ...) pour leur permettre d'utiliser Ant, devenu un standard de fait.

Ant possède donc plusieurs atouts : multi plate-forme, configurable grâce à un fichier XML, open source et extensible.

Pour obtenir plus de détails sur l'utilisation de Ant, il est possible de consulter la documentation de la version courante à l'url suivante : http://jakarta.apache.org/ant/manual/index.html

Une version 2 de Ant est en cours de développement.

Ce chapitre contient plusieurs sections :

  • Installation de Ant
  • Exécuter ant
  • Le fichier build.xml
  • Les tâches (task)

50.1. Installation de Ant

Pour pouvoir utiliser Ant, il faut avoir un JDK 1.1 ou supérieur et installer Ant sur la machine.


50.1.1. Installation sous Windows

Le plus simple est de télécharger la distribution binaire de Ant pour Windows : jakarta-ant-version-bin.zip sur le site de Ant.

Il suffit ensuite de :

  • dézipper le fichier (un répertoire jakarta-ant-version est créer, contenant l'outil et sa documentation)
  • ajouter le chemin complet au répertoire bin de Ant à la variable système PATH (pour pouvoir facilement appeler Ant n'importe ou dans l'arborescence du système)
  • s'assurer que la variable JAVA_HOME pointe sur le répertoire contenant le JDK
  • créer une variable d'environnement ANT_HOME qui pointe sur le répertoire jakarta-ant-version créé lors de la décompression du fichier
  • il peut être nécessaire d'ajouter les fichiers .jar contenus dans le répertoire lib de Ant à la variable d'environnement CLASSPATH
Exemple de lignes contenues dans le fichier autoexec.bat :
... set JAVA_HOME=c:\jdk1.3 set ANT_HOME=c:\java\ant set PATH=%PATH%;%ANT_HOME%\bin ...

50.2. Exécuter ant

Ant s'utilise en ligne de commande avec la syntaxe suivante :

ant [options] [cible]

Par défaut, Ant recherche un fichier nommé build.xml dans le répertoire courant. Ant va alors exécuter la cible par défaut définie dans le projet de ce fichier build.xml.

Il est possible de préciser le nom du fichier de configuration en utilisant l'option -buildfile et en la faisant suivre du nom du fichier de configuration.

Exemple :
ant -buildfile monbuild.xml
Il est possible de préciser une cible précise à exécuter. Dans ce cas, Ant exécute les cibles dont dépend la cible précisée et exécute cette dernière.

Il est possible de préciser une cible précise à exécuter. Dans ce cas, Ant exécute les cibles dont dépend la cible précisée et exécute cette dernière.
ant clean
Ant possède plusieurs options dont voici les principales :

Option Rôle
-quiet fourni un minimum d'informations lors de l'execution
- verbose fourni un maximum d'informations lors de l'exécution
- version affiche la version de ant
-projecthelp affiche les cibles définis avec leur description
-buildfile permet de préciser le nom du fichier de configuration
-Dnom=valeur permet de définir une propriété dont le nom et le valeur sont séparés par un caractère =

50.3. Le fichier build.xml

Le fichier build est un fichier XML qui contient la description du processus de construction de l'application.

Comme tout document XML, le fichier débute par un prologue :

<?xml version="1.0">

L'élément principal de l'arborescence du document est le projet représenté par le tag <project> qui est donc le tag racine du document.

A l'intérieur du projet, il faut définir les éléments qui le compose :

  • les cibles (targets) : ce sont des étapes du projet de construction
  • les propriétés (properties) : ce sont des variables qui contiennent des valeurs utilisables par d'autres éléments (cibles ou tâches)
  • les tâches (tasks) : ce sont des traitements unitaires à réaliser dans une cible donnée
Pour permettre l'exécution sur plusieurs plate-formes, les chemins de fichiers utilisés dans le fichier build.xml doivent utiliser la caractère slash '/' comme séparateur même sous Windows qui utilise le caractère anti-slash '\'.


50.3.1. Le projet

Il est défini par le tag racine <project> dans le fichier build.

Ce tag possède plusieurs attributs :

  • name : cet attribut précise le nom du projet
  • default : cet attribut précise la cible par défaut à exécuter si aucune cible n'est précisée lors de l'exécution
  • basedir : cet attribut précise le répertoire qui servira de référence pour l'utilisation de localisation relative des autres répertoires.
Exemple :
<project name="mon projet" default="compile" basedir=".">

50.3.2. Les commentaires

Les commentaires sont inclus dans un tag <!-- -->.

Exemple :
<!-- Exemple de commentaires -->

50.3.3. Les propriétés

Le tag <property> permet de définir une propriété qui pourra être utilisée dans le projet : c'est souvent la définition d'un répertoire ou d'une variable qui sera utilisée par certaines tâches. Leur définition en tant que propriété permet de facilement changer leur valeur une seule fois même si la valeur de la propriété est utilisée plusieurs fois dans le projet.

Exemple
<property name= "nom_appli" value= "monAppli"/>

Les propriétés sont immuables et peuvent être définies de deux manières :

  • avec le tag <property>
  • avec l'option -D sur la ligne de commande lors de l'appel de la commande ant
Pour utiliser une propriété sur la ligne de commande, il faut utiliser l'option -D immediatement suivi du nom de la propriété, suivi du caractère =, suivi de la valeur, le tout sans espace.

Le tag <property> possède plusieurs attributs :

  • name : cet attribut défini le nom de la propriété
  • value : cet attribut défini la valeur de la propriété
  • location : cet attribut permet de définir un fichier avec son chemin absolu. Il peut être utilisé à la place de l'attribut value
  • file : cet attribut permet de préciser le nom d'un fichier qui contient la définition d'un ensemble de propriétés. Ce fichier sera lu et les propriétés qu'il contient seront définies.
L'utilisation de l'attribut file est particulièrement utile car il permet de séparer la définition des propriétés du fichier build. Le changement d'un paramètre ne nécessite alors pas de modifications dans le fichier xml build.

Exemple :
<property file="mesproprietes.properties" /> <property name="repSources" value="src" /> <property name="projet.nom" value="mon_projet" /> <property name="projet.version" value="0.0.10" />
L'ordre de définition d'une propriété est très important : Ant gère une priorité sur l'ordre de définition d'une propriété. La règle est la suivante : la première définition d'une propriété est prise en compte, les suivantes sont ignorées.

Ainsi, les propriétés définies via la ligne de commande sont prioritaires par rapport à celles définies dans le fichier build. Il est aussi préférable de mettre le tag <property> contenant un attribut file avant les tag <property> définissant des variables.

Pour utiliser une propriété définie dans le fichier, il faut utiliser la syntaxe suivante :
${nom_propriete}

Exemple
${repSources}
Il existe aussi des propriétés pré-définies par Ant et utilisables dans chaque fichier build :

Propriété Rôle
basedir chemin absolu du répertoire de travail (cette valeur est précisée dans l'attribut basedir du tag project)
ant.file chemin absolu du fichier build en cours de traitement
ant.java.version version de la JVM qui exécute ant
ant.project.name nom du projet en cours d'utilisation

50.3.4. Les ensembles de fichiers

Le tag <fileset> permet de définir un ensemble de fichiers. Cet ensemble de fichier sera utilisé dans une autre tâche. La définition d'un tel ensemble est réalisé grace à des attributs du tag <fileset> :

Attribut Rôle
dir Définit le répertoire de départ de l'ensemble de fichiers
includes Liste des fichiers à inclure
excludes Liste des fichiers à exclure
L'expression **/ permet de désigner tous les sous répertoires du répertoire défini dans l'attribut dir.

Exemple :
<fileset dir="src" includes="**/*.java">

50.3.5. Les ensembles de motifs

Le tag <patternset> permet de définir un ensemble de motifs pour sélectionner des fichiers.

La définition d'un tel ensemble est réalisée grace à des attributs du tag <patternset> :

Attribut Rôle
id Définit un identifiant pour l'ensemble qui pourra ainsi être réutilisé
includes Liste des fichiers à inclure
excludes Liste des fichiers à exclure
refid Demande la réutilisation d'un ensemble dont l'identifiant est fourni comme valeur
L'expression **/ permet de désigner tous les sous répertoires du répertoire définit dans l'attribut dir. Le caractère ? représente un unique caractère quelconque et le caractère * représente zéro ou n caractères quelconques.

Exemple :
<fileset dir="src"> <patternset id="source_code"> <includes="**/*.java"/> </patternset> </fileset>

50.3.6. Les listes de fichiers

Le tag <filelist> permet de définir une liste de fichiers finis. Chaque fichier est nommément ajouté dans laliste, séparé chacun par une virgule. La définition d'un tel élément est réalisée grace à des attributs du tag <filelist> :
Attribut Rôle
id Définit un identifiant pour la liste qui pourra ainsi être réutilisé
dir Définit le répertoire de départ de la liste de fichiers
files liste des fichiers séparés par une virgule
refid Demande la réutilisation d'une liste dont l'identifiant est fourni comme valeur
Exemple :
<filelist dir="texte" files="fichier1.txt,fichier2.txt" />

50.3.7. Les éléments de chemins

Le tag <pathelement> permet de définir un élément qui sera ajouter à la variable classpath. La définition d'un tel élément est réaliser grace à des attributs du tag <pathelement> :

Attribut Rôle
location Défini un chemin d'une ressource qui sera ajoutée
path  
Exemple :
<classpath> <pathelement location="bin/mabib.jar"> <pathelement location="lib/"> </classpath>
Il est préférable pour assurer une meilleure compatibilité entre plusieurs systèmes d'utiliser des chemins relatifs par rapport au répertoire de base de projet.


50.3.8. Les cibles

Le tag <target> définit une cible. Une cible est un ensemble de tâches à réaliser dans un ordre précis. Cet ordre correspond à celui des tâches décrites dans la cible.

Le tag possède plusieurs attributs :

  • name : contient le nom de la cible. Cet attribut est obligatoire
  • description : contient une brève description de la cible. Cet attribut est optionnel mais il est recommandé de l'utiliser car la plupart des IDE l'affiche lors de l'utilisation de ant
  • if : permet de conditionner l'exécution par l'existence d'une propriété. Cet attribut est optionnel
  • unless : permet de conditionner l'exécution par l'inexistance de la définition d'une propriété. Cet attribut est optionnel
  • depends : permet de définir la liste des cibles dont dépend la cible. Cet attribut est optionnel
Il est possible de faire dépendre une cible d'une ou plusieurs autres cibles du projet. Lorsqu'une cible doit être exécutée, Ant s'assure que les cibles dont elle dépend ont été complétement exécutées préalablement depuis l'exécution de Ant. Une dépendance est définie grace à l'attribut depends. Plusieurs cibles dépendantes peuvent être listées dans l'attribut depends. Dans ce cas, chaque cible doit être séparée avec une virgule.


50.4. Les tâches (task)

Une tâche est une unité de traitements contenue dans une classe Java qui implémente l'interface org.apache.ant.Task. Dans le fichier de configuration, une tâche est un tag qui peut avoir des paramètres pour configurer le traitement à réaliser. Une tâche est obligatoirement incluse dans une cible.

Ant fournit en standard un certain nombre de tâches pour des traitements courants lors du développement en Java :

Catégorie Nom de la tâche Rôle
Tâches internes echo Afficher un message
  dependset Définir des dépendances entre fichiers
  taskdef Définir une tâche externe
  typedef Définir un nouveau type de données
Gestion des propriétés available Définir une propriété si une ressource existe
  condition Définir une propriété si une condition est vérifiée
  pathconvert Définir une propriété avec la conversion d'un chemin de fichier spécifique à un OS
  property Définir une propriété
  tstamp Initialiser les propriétés DSTAMP, TSTAMP et TODAY avec la date et heure courante
  uptodate Définir une propriété en comparant la date de modification de fichiers
tâches Java java Exécuter une application dans la JVM
  javac Compiler des sources Java
  javadoc Générer la documentation du code source
  rmic Générer les classes stub et skeleton nécessaires à la technologie rmi
  signjar Signer un fichier jar
Gestion des archives ear Créer une archive contenant une application J2EE
  gunzip Décompresser une archive
  gzip Compresser dans une archive
  jar Créer une archive de type jar
  tar Créer une archive de type tar
  unjar Décompresser une archive de type jar
  untar Décompresser une archive de type tar
  unwar Décompresser une archive de type war
  unzip Décompresser une archive de type zip
  war Créer une archive de type war
  zip Créer une archive de type zip
tâches diverses apply Exécuter une commande externe appliquée à un ensemble de fichiers
  cvs Gérer les sources dans CVS
  cvspass  
  exec Exécuter une commande externe
  genkey Générer une clé dans un trousseau de clé
  get Obtenir une ressource à partir d'une URL
  mail Envoyer un courrier électronique
  replace Remplacer une chaîne de caractères par une autre
  sql Exécuter une requête SQL
  style Appliquer une feuille de style XSLT à un fichier XML
Gestion des fichiers chmod Modifier les droits d'un fichier
  copy Copier un fichier
  delete Supprimer un fichier
  mkdir Créer un répertoire
  move Déplacer ou renommer un fichier
  touch Modifier la date de modification du fichier avec la date courante
Gestion de l'exécution de Ant ant Exécuter un autre fichier de build
  antcall Exécuter une cible
  fail Stopper l'exécution de Ant
  parallel Exécuter une tâche en parallèle
  record Enregistrer les traitements de l'exécution dans un fichier journal
  sequential Exécuter une tâche en séquentielle
  sleep Faire une pause dans les traitements
Certaines de ces tâches seront détaillées dans les sections suivantes : pour une référence complète de ces tâches, il est nécessaire de consulter la documentation de Ant.


50.4.1. echo

La tâche <echo> permet d'écrire dans un fichier ou d'afficher un message ou des informations durant l'exécution des traitements.

Les données à utiliser peuvent être fournies dans un attribut dédié ou dans le corps du tag <echo>.

Cette tâche possède plusieurs attributs dont les principaux sont :

Attribut Rôle
message Message à afficher
file Fichier dans lequel le message sera inséré
append Booléen qui précise si le message est ajouté à la fin du fichier (true) ou si le fichier doit être écrasé avec le message fourni (false)
Exemple :
<?xml version="1.0" encoding="ISO-8859-1"?> <project name="Test avec Ant" default="init" basedir="."> <!-- =================================================================== --> <!-- Initialisation --> <!-- =================================================================== --> <target name="init"> <echo message="Debut des traitements" /> <echo> Fin des traitements du projet ${ant.project.name} </echo> <echo file="${basedir}/log.txt" append="false" message="Debut des traitements" /> <echo file="${basedir}/log.txt" append="true" > Fin des traitements </echo> </target> </project>
Résultat :
C:\java\test\testant>ant Buildfile: build.xml init: [echo] Debut des traitements [echo] [echo] Fin des traitements du projet Test avec Ant [echo] BUILD SUCCESSFUL Total time: 2 seconds C:\java\test\testant>type log.txt Debut des traitements Fin des traitements C:\java\test\testant>

50.4.2. mkdir

La tâche <mkdir> permet de créer un répertoire avec éventuellement ses répertoires pères ci ceux ci n'existent pas.

Cette tâche possède un seul attribut:

Attribut Rôle
dir Précise le chemin et le nom du répertoire à créer
Exemple :
<?xml version="1.0" encoding="ISO-8859-1"?> <project name="Test avec Ant" default="init" basedir="."> <!-- =================================================================== --> <!-- Initialisation --> <!-- =================================================================== --> <target name="init"> <mkdir dir="${basedir}/gen" /> </target> </project>
Résultat :
C:\java\test\testant>ant Buildfile: build.xml init: [mkdir] Created dir: C:\java\test\testant\gen BUILD SUCCESSFUL Total time: 2 seconds C:\java\test\testant>

50.4.3. delete

La tâche <delete> permet de supprimer des fichiers ou des répertoires.

Cette tâche possède plusieurs attributs dont les principaux sont :

Attribut Rôle
file Permet de préciser le fichier à supprimer
dir Permet de préciser le répertoire à supprimer
verbose Booléen qui permet d'afficher la liste des éléments supprimés
quiet Booléen qui permet de ne pas afficher les messages d'erreurs
includeEmptyDirs Booléen qui permet de supprimer les répertoires vides
Exemple :
<?xml version="1.0" encoding="ISO-8859-1"?> <project name="Test avec Ant" default="init" basedir="."> <!-- =================================================================== --> <!-- Initialisation --> <!-- =================================================================== --> <target name="init"> <delete dir="${basedir}/gen" /> <delete file="${basedir}/log.txt" /> <delete> <fileset dir="${basedir}/bin" includes="**/*.class" /> </delete> </target> </project>
Résultat :
C:\java\test\testant>ant Buildfile: build.xml init: [delete] Deleting directory C:\java\test\testant\gen [delete] Deleting: C:\java\test\testant\log.txt BUILD SUCCESSFUL Total time: 2 seconds C:\java\test\testant>

50.4.4. copy

La tâche <copy> permet de copier un ou plusieurs fichiers dans le cas ou ils n'existent pas dans la cible ou si ils sont plus récents dans la cible.

Cette tâche possède plusieurs attributs dont les principaux sont :

Attribut Rôle
file Désigne le fichier à copier
todir Permet de préciser le répertoire cible dans lequel les fichiers seront copiés
overwrite Booléen qui permet d'écraser les fichiers cibles si ils sont plus récents (false par défaut)
L'ensemble des fichiers concernés par la copie doit être précisé avec un tag fils <fileset>.

Exemple :
<project name="utilisation de hbm2java" default="init" basedir="."> <!-- Definition des proprietes du projet --> <property name="projet.sources.dir" value="src"/> <property name="projet.bin.dir" value="bin"/> <!-- Initialisation des traitements --> <target name="init" description="Initialisation"> <!-- Copie des fichiers de mapping et parametrage --> <copy todir="${projet.bin.dir}" > <fileset dir="${projet.sources.dir}" > <include name="**/*.properties"/> <include name="**/*.hbm.xml"/> <include name="**/*.cfg.xml"/> </fileset> </copy> </target> </project>
Résultat :
C:\java\test\testhibernate>ant Buildfile: build.xml init: [copy] Copying 3 files to C:\java\test\testhibernate\bin BUILD SUCCESSFUL Total time: 3 seconds

50.4.5. tstamp

La tâche <tstamp> permet de définir trois propriétés :

  • DSTAMP : cette propriété est initialisée avec la date du jour au format AAAMMJJ
  • TSTAMP : cette propriété est initialisée avec l'heure actuelle sous la forme HHMM
  • TODAY : cette propriété est initialisée avec la date du jour au format long
Cette tâche ne possède pas d'attributs.

Exemple :
<?xml version="1.0" encoding="ISO-8859-1"?> <project name="Test avec Ant" default="init" basedir="."> <!-- =================================================================== --> <!-- Initialisation --> <!-- =================================================================== --> <target name="init"> <tstamp/> <echo message="Nous sommes le ${TODAY}" /> <echo message="DSTAMP = ${DSTAMP}" /> <echo message="TSTAMP = ${TSTAMP}" /> </target> </project>
Résultat :
C:\java\test\testant>ant Buildfile: build.xml init: [echo] Nous sommes le August 25 2004 [echo] DSTAMP = 20040825 [echo] TSTAMP = 1413 BUILD SUCCESSFUL Total time: 2 seconds

50.4.6. java

La tâche <java> permet de lancer une machine virtuelle pour exécuter une application compilée.

Cette tâche possède plusieurs attributs dont les principaux sont :

Attribut Rôle
classname nom pleinement qualifié de la classe à exécuter
jar nom du fichier de l'application à exécuter
classpath classpath pour l'exécution. Il est aussi possible d'utiliser un tag fils <classpath> pour le spécifier
classpathref utilisation d'un classpath précédemment défini dans le fichier de build
fork lancer l'exécution dans une JVM dédiée au lieu de celle ou l'exécute Ant
output enregistrer les sorties de la console dans un fichier
Le tag fils <arg> permet de fournir des paramètres à l'exécution.

Le tag fils <classpath> permet de définir le classpath à utiliser lors de l'exécution

Exemple :
<project name="testhibernate1" default="TestHibernate1" basedir="."> <!-- Definition des proprietes du projet --> <property name="projet.sources.dir" value="src"/> <property name="projet.bin.dir" value="bin"/> <property name="projet.lib.dir" value="lib"/> <!-- Definition du classpath du projet --> <path id="projet.classpath"> <fileset dir="${projet.lib.dir}"> <include name="*.jar"/> </fileset> <pathelement location="${projet.bin.dir}" /> </path> <!-- Execution de TestHibernate1 --> <target name="TestHibernate1" description="Execution de TestHibernate1" > <java classname="TestHibernate1" fork="true"> <classpath refid="projet.classpath"/> </java> </target> </project>

50.4.7. javac

La tâche <javac> permet la compilation de fichiers source contenus dans une arborescence de répertoires.

Cette tâche possède plusieurs attributs dont les principaux sont :

Attribut Rôle
srcdir précise le répertoire racine de l'arborescence du répertoire contenant les sources
destdir précise le répertoire où les résultats des compilations seront stockés
classpath classpath pour l'exécution. Il est aussi possible d'utiliser un tag fils <classpath> pour le spécifier
classpathref utilisation d'un classpath précédemment défini dans le fichier de build
nowarn précise si les avertissements du compilateur doivent être affichés. La valeur par défaut est off
debug précise si le compilateur doit inclure les informations de débogage dans les fichiers compilés. La valeur par défaut est off
optimize précise si le compilateur doit optimiser le code compilé qui sera généré. La valeur par défaut est off
deprecation précise si les avertissements du compilateur concernant l'usage d'éléments deprecated doivent être affichés. La valeur par défaut est off
target précise la version de la plate-forme Java cible (1.1, 1.2, 1.3, 1.4, ...)
fork lance la compilation dans une JVM dédiée au lieu de celle ou s'exécute Ant. La valeur par défaut est false
failonerror précise si les erreurs de compilations interrompent l'exécution du fichier de build. La valeur par défaut est true
source version des sources java : particulièrement utile pour Java 1.4 et 1.5 qui apportent des modifications à la grammaire du langage Java
Exemple :
<project name="compiltation des classes" default="compile" basedir="."> <!-- Definition des proprietes du projet --> <property name="projet.sources.dir" value="src"/> <property name="projet.bin.dir" value="bin"/> <property name="projet.lib.dir" value="lib"/> <!-- Definition du classpath du projet --> <path id="projet.classpath"> <fileset dir="${projet.lib.dir}"> <include name="*.jar"/> </fileset> <pathelement location="${projet.bin.dir}" /> </path> <!-- Compilation des classes du projet --> <target name="compile" description="Compilation des classes"> <javac srcdir="${projet.sources.dir}" destdir="${projet.bin.dir}" debug="on" optimize="off" deprecation="on"> <classpath refid="projet.classpath"/> </javac> </target> </project>
Résultat :
C:\java\test\testhibernate>ant Buildfile: build.xml compile: [javac] Compiling 1 source file to C:\java\test\testhibernate\bin [javac] C:\java\test\testhibernate\src\TestHibernate1.java:9: cannot resolve symbol [javac] symbol : class configuration [javac] location: class TestHibernate1 [javac] Configuration config = new configuration(); [javac] ^ [javac] 1 error BUILD FAILED file:C:/java/test/testhibernate/build.xml:22: Compile failed; see the compiler e rror output for details. Total time: 9 seconds

50.4.8. javadoc

La tâche <javadoc> permet de demander la génération de la documentation au format javadoc des classes incluses dans une arborescence de répertoires.

Cette tâche possède plusieurs attributs dont les principaux sont :

Attribut Rôle
sourcepath précise le répertoire de base qui contient les sources dont la documentation est à générer
destdir précise le répertoire qui va contenir les fichiers de documentation générés
Exemple :
<?xml version="1.0" encoding="ISO-8859-1"?> <project name="Test avec Ant" default="javadoc" basedir="."> <!-- ================================================--> <!-- Génération de la documentation Javadoc --> <!-- ================================================--> <target name="javadoc"> <javadoc sourcepath="src" destdir="doc" > <fileset dir="src" defaultexcludes="yes"> <include name="**" /> </fileset> </javadoc> </target> </project>
Résultat :
C:\java\test\testant>ant Buildfile: build.xml javadoc: [javadoc] Generating Javadoc [javadoc] Javadoc execution [javadoc] Loading source file C:\java\test\testant\src\MaClasse.java... [javadoc] Constructing Javadoc information... [javadoc] Standard Doclet version 1.4.2_02 [javadoc] Building tree for all the packages and classes... [javadoc] Building index for all the packages and classes... [javadoc] Building index for all classes... BUILD SUCCESSFUL Total time: 9 seconds

50.4.9. jar

La tâche <jar> permet la création d'une archive de type jar.

Cette tâche possède plusieurs attributs dont les principaux sont :

Attribut Rôle
jarfile nom du fichier .jar à créer
basedir précise de répertoire qui contient les éléments à ajouter dans l'archive
compress précise si le contenu de l'archive doit être compressé ou non. La valeur par défaut est true
manifest précise le fichier manifest qui sera utilisé dans l'archive
Exemple :
<?xml version="1.0" encoding="ISO-8859-1"?> <project name="Test avec Ant" default="packaging" basedir="."> <!-- =================================================================== --> <!-- Génération de l'archive jar --> <!-- =================================================================== --> <target name="packaging"> <jar jarfile="test.jar" basedir="src" /> </target> </project>
Résultat :
C:\java\test\testant>ant Buildfile: build.xml packaging: [jar] Building jar: C:\java\test\testant\test.jar BUILD SUCCESSFUL Total time: 2 seconds
La suite de ce chapitre sera développée dans une version future de ce document


51. Maven

Maven permet de faciliter et d'automatiser certaines tâches de la gestion d'un projet Java.

Le site officiel est http://maven.apache.org

Il permet notamment :

  • d'automatiser certaines tâches : compilation, tests unitaires et déploiement des applications qui composent le projet
  • de gérer des dépendances vis à vis des bibliothèques nécessaires au projet
  • de générer des documentations concernant le projet
Au premier abord, il est facile de croire que Maven fait double emploi avec Ant. Ant et Maven sont tous les deux développés par le groupe Jakarta, ce qui prouve bien que leur utilité n'est pas aussi identique.

Ant dont le but est d'automatiser certaines tâches répétitives est plus ancien que Maven. Maven propose non seulement ces fonctionnalités mais en propose de nombreuses autres.

Pour gérer les dépendances du projet vis à vis de bibliothèques, Maven utilise un ou plusieurs repositorys qui peuvent être locaux (.maven/repository) ou distants (http://www.ibiblio.org/maven par défaut)

Maven est extensible grâce à un mécanisme de plug in qui permet d'ajouter des fonctionnalités.


51.1. Installation

Il faut télécharger le fichier maven-1.0-rc2.exe sur le site de Maven et l'exécuter.

Un assistant permet de fournir les informations concernant l'installation :

  • sur la page « Licence Agreement » : lire la licence et si vous l'acceptez cliquer sur le bouton « I Agree ».
  • sur la page « Installations Options » : sélectionner les éléments à installer et cliquer sur le bouton « Next ».
  • sur la page « Installation Folder » : sélectionner le répertoire dans lequel Maven va être installé et cliquer sur le bouton « Install ».
  • une fois les fichiers copiés, il suffit de cliquer sur le bouton « Close ».
Sous Windows, un élément de menu nommé « Apache Software Foundation / Maven 1.0-rc2 » est ajouté dans le menu « Démarrer / Programmes ».

Pour utiliser Maven, la variable d'environnement système nommée MAVEN_HOME doit être définie avec comme valeur le chemin absolu du répertoire dans lequel Maven est installé. Par défaut, cette variable est configurée automatiquement lors de l'installation sous Windows.

Il est aussi particulièrement pratique d'ajouter le répertoire %MAVEN_HOME%/bin à la variable d'environnement PATH. Maven étant un outil en ligne de commande, cela évite d'avoir à saisir son chemin complet lors de son exécution.

Enfin, il faut créer un repository local en utilisant la commande ci dessous dans une boîte de commandes DOS :

Exemple :
C:\>install_repo.bat %HOMEDRIVE%%HOMEPATH%
Pour s'assurer de l'installation correcte de Maven, il suffit de saisir la commande :

Exemple :
C:\>maven -v __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0-rc2 C:\>
Lors de la première exécution de Maven, ce dernier va constituer le repository local (une connexion internet est nécessaire).

Exemple :
| \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0-rc2 Le rÚpertoire C:\Documents and Settings\Administrateur\.maven\repository n'exist e pas. Tentative de crÚation. Tentative de tÚlÚchargement de commons-lang-1.0.1.jar. ................................. . Tentative de tÚlÚchargement de commons-net-1.1.0.jar. ................................................................................ ........ . Tentative de tÚlÚchargement de dom4j-1.4-dev-8.jar. ................................................................................ ................................................................................ ................................................................................ .............................................................. . Tentative de tÚlÚchargement de xml-apis-1.0.b2.jar. ........................................................

51.2. Les plug-ins

Toutes les fonctionnalités de Maven sont proposées sous la forme de plug-ins.

Le fichier maven.xml permet de configurer les plug-ins installés.


51.3. Le fichier project.xml

Maven est orienté projet, donc le projet est l'entité principale gérée par Maven. Il est nécessaire de fournir à Maven une description du projet (Project descriptor) sous la forme d'un document XML nommé project.xml et situé à la racine du répertoire contenant le projet.

Exemple : un fichier minimaliste
<project> <id>P001</id> <name>TestMaven</name> <currentVersion>1.0</currentVersion> <shortDescription>Test avec Maven</shortDescription> <developers> <developer> <name>Jean Michel D.</name> <id>jmd</id> <email>jmd@test.fr</email> </developer> </developers> <organization> <name>Jean-Michel</name> </organization> </project>
Il est possible d'inclure la valeur d'un tag défini dans le document dans un autre tag.

Exemple :
... <shortDescription>${pom.name} est un test avec Maven</shortDescription> ...
Il est possible d'hériter d'un fichier project.xml existant dans lequel des caractéristiques communes à plusieurs projets sont définies. La déclaration dans le fichier du fichier père se fait avec le tag <extend>. Dans le fichier fils, il suffit de redéfinir ou de définir les tags nécessaires.


51.4. Exécution de Maven

Maven s'utilise en ligne de commande sous la forme suivante :

Maven plugin:goal

Il faut exécuter Maven dans le répertoire qui contient le fichier project.xml.

Si les paramètres fournis ne sont pas corrects, une exception est levée :

Exemple :
C:\java\test\testmaven>maven compile __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0-rc2 com.werken.werkz.NoSuchGoalException: No goal [compile] at com.werken.werkz.WerkzProject.attainGoal(WerkzProject.java:190) at org.apache.maven.plugin.PluginManager.attainGoals(PluginManager.java: 531) at org.apache.maven.MavenSession.attainGoals(MavenSession.java:265) at org.apache.maven.cli.App.doMain(App.java:466) at org.apache.maven.cli.App.main(App.java:1117) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl. java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces sorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at com.werken.forehead.Forehead.run(Forehead.java:551) at com.werken.forehead.Forehead.main(Forehead.java:581) Total time: 4 seconds Finished at: Tue May 18 14:17:18 CEST 2004
Pour obtenir une liste complète des plug-ins à disposition de Maven, il suffit d'utiliser la commande maven –g

Voici quelques uns des nombreux plug-in avec leurs goals principaux :

Plug in Goal Description
ear ear construire une archive de type ear
  deploy déployer un fichier ear dans un serveur d'application
ejb ejb  
  deploy  
jalopy format  
java compile compiler des sources
  jar créer une archive de type .jar
javadoc    
jnlp    
pdf   générer la documentation du projet au format PDF
site generate générer le site web du projet
  deploy copier le site web sur un serveur web
test match exécuter des tests unitaires
war init  
  war  
  deploy  
La commande maven clean permet d'effacer tous les fichiers générés par Maven.

Exemple :
C:\java\test\testmaven>maven clean __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0-rc2 build:start: clean:clean: [delete] Deleting directory C:\java\test\testmaven\target [delete] Deleting: C:\java\test\testmaven\velocity.log BUILD SUCCESSFUL Total time: 2 minutes 7 seconds Finished at: Tue May 25 14:19:03 CEST 2004 C:\java\test\testmaven>

51.5. Génération du site du projet

Maven propose une fonctionnalité qui permet de générer automatique un site web pour le projet regroupant un certain nombre d'informations utiles le concernant.

Pour demander la génération du site, il suffit de saisir la commande

maven site:generate

Lors de l'exécution de cette commande, un répertoire target/docs est créé contenant les différents éléments du site.

Exemple :
C:\java\test\testmaven\target\docs>dir Le volume dans le lecteur C s'appelle MACHINE Le numéro de série du volume est 3T78-19E4 Répertoire de C:\java\test\testmaven\target\docs 25/05/2004 14:21 <DIR> . 25/05/2004 14:21 <DIR> .. 25/05/2004 14:21 <DIR> apidocs 25/05/2004 14:21 5 961 checkstyle-report.html 25/05/2004 14:21 1 637 cvs-usage.html 25/05/2004 14:21 1 954 dependencies.html 25/05/2004 14:21 <DIR> images 25/05/2004 14:21 1 625 index.html 25/05/2004 14:21 1 646 issue-tracking.html 25/05/2004 14:21 3 119 javadoc.html 25/05/2004 14:21 9 128 jdepend-report.html 25/05/2004 14:21 2 494 license.html 25/05/2004 14:21 5 259 linkcheck.html 25/05/2004 14:21 1 931 mail-lists.html 25/05/2004 14:21 4 092 maven-reports.html 25/05/2004 14:21 3 015 project-info.html 25/05/2004 14:21 <DIR> style 25/05/2004 14:21 2 785 task-list.html 25/05/2004 14:21 3 932 team-list.html 25/05/2004 14:21 <DIR> xref 14 fichier(s) 48 578 octets 6 Rép(s) 207 151 616 octets libres
Par défaut, le site généré contient un certain nombre de pages accessibles via le menu de gauche.

La partie « Project Info » regroupe trois pages : la mailing liste, la liste des développeurs et les dépendances du projet.

La partie « Project report » permet d'avoir accès à des comptes rendus d'exécution de certaines tâches : javadoc, tests unitaires, ... Certaines de ces pages ne sont générées qu'en fonction des différents éléments générés par Maven.

Le contenu du site pourra donc être réactualisé facilement en fonction des différents traitements réalisés par Maven sur le projet.


51.6. Compilation du projet

Dans le fichier project.xml, il faut rajouter un tag <build> qui va contenir les informations pour la compilation des éléments du projet.

Les sources doivent être contenues dans un répertoire dédié, par exemple src

Exemple :
... <build> <sourceDirectory> ${basedir}/src </sourceDirectory> </build> ...
Pour demander la compilation à Maven, il faut utiliser la commande

Exemple :
Maven java :compile C:\java\test\testmaven>maven java:compile __ __ | \/ |__ _Apache__ ___ | |\/| / _` \ V / -_) ' \ ~ intelligent projects ~ |_| |_\__,_|\_/\___|_||_| v. 1.0-rc2 Tentative de tÚlÚchargement de commons-jelly-tags-antlr-20030211.143720.jar. ..... . build:start: java:prepare-filesystem: [mkdir] Created dir: C:\java\test\testmaven\target\classes java:compile: [echo] Compiling to C:\java\test\testmaven/target/classes [javac] Compiling 1 source file to C:\java\test\testmaven\target\classes BUILD SUCCESSFUL Total time: 12 seconds Finished at: Tue May 18 14:19:12 CEST 2004
Le répertoire « target/classes » est créé à la racine du répertoire du projet. Les fichiers .class issus de la compilation sont stockés dans ce répertoire.

La commande maven jar permet de demander la génération du packaging de l'application.

Exemple :
build:start: java:prepare-filesystem: java:compile: [echo] Compiling to C:\java\test\testmaven/target/classes java:jar-resources: test:prepare-filesystem: [mkdir] Created dir: C:\java\test\testmaven\target\test-classes [mkdir] Created dir: C:\java\test\testmaven\target\test-reports test:test-resources: test:compile: [echo] No test source files to compile. test:test: [echo] No tests to run. jar:jar: [jar] Building jar: C:\java\test\testmaven\target\P001-1.0.jar BUILD SUCCESSFUL Total time: 2 minutes 42 seconds Finished at: Tue May 18 14:25:39 CEST 2004
Par défaut, l'appel à cette commande effectue une compilation des sources, un passage des tests unitaires si il y en a et un appel à l'outil jar pour réaliser le packaging.

Le nom du fichier jar créé est composé de l'id du projet et du numéro de version. Il est stocké dans le répertoire racine du projet.


52. Les frameworks de tests

L'utilisation de frameworks dédiés à l'automatisation des test unitiaires permet d'assurer une meilleure qualité et fiabilité du code. Cette automatisation facilite aussi le passage de tests de non regression notamment lors des nombreuses mises à jour du code. De plus, l'utilisation de ces frameworks ne nécessite aucune modification dans le code à tester ce qui sépare clairement les traitements représentés dans le code de leur test.

Ce chapitre contient plusieurs sections :

  • JUnit
  • Cactus

52.1. JUnit

JUnit est un framework open source pour réaliser des tests unitaires sur du code Java. Le principal intérêt est de s'assurer que le code répond toujours au besoin même après d'éventuelles modifications. Plus généralement, ce type de tests est appellé tests unitaires de non régression.

Il a été initialement développé par Erich Gamma and Kent Beck.

Le but est d'automatiser les tests. Ceux ci sont exprimés dans des classes sous la forme de cas de tests avec leurs résultats attendus. JUnit exécute ces tests et les comparent avec ces résultats.

Cela permet de séparer le code de la classe, du code qui permet de la tester. Souvent pour tester une classe, il est facile de créer une méthode main() qui va contenir les traitements de tests. L'inconvénient est que ce code "superflu" aux traitements proprement dit est qu'il soit inclus dans la classe. De plus, son exécution doit se faire à la main.

Avec Junit, l'unité de test est une classe dédiée qui regroupe des cas de tests. Ces cas de tests exécutent les tâches suivantes :

  • création d'une instance de la classe et de tout autre objet nécessaire aux tests
  • appel de la méthode à tester avec les paramètres du cas de test
  • comparaison du résultat obtenu avec le résultat attendu : en cas d'échec, une exception est levée
JUnit est particulièrement adapté pour être utilisé avec la méthode eXtreme Programming puisque de cette méthode préconise entre autre l'automatisation des tâches de tests unitaires qui ont été définis avant l'écriture du code.

La dernière version de JUnit peut être téléchargée sur le site www.junit.org. Pour l'installer, il suffit de dézipper l'archive. Le plus simple pour pouvoir utiliser JUnit est de copier le fichier junit.jar dans le répertoire JAVA_HOME\jre\lib\ext .

La version utilisée dans ce chapitre est la 3.8.1.


52.1.1. Un exemple très simple

L'exemple utilisé dans cette section est la classe suivante :

Exemple :
public class MaClasse{ public static int calculer(int a, int b) { int res = a + b; if (a == 0){ res = b * 2; } if (b == 0) { res = a * a; } return res; } }
Il faut compiler cette classe : javac MaClasse.java

Il faut ensuite écrire une classe qui va contenir les différents tests à réaliser par JUnit. L'exemple est volontairement simpliste en ne définissant qu'un seul cas de test.

Exemple :
import junit.framework.*; public class MaClasseTest extends TestCase{ public void testCalculer() throws Exception { assertEquals(2,MaClasse.calculer(1,1)); } }
Il faut compiler cette classe : javac MaClasseTest.java (le fichier junit.jar doit être dans le classpath).

Enfin, il suffit d'appeler JUnit pour qu'il exécute la séquence de tests.

Exemple :
java -cp junit.jar;. junit.textui.TestRunner MaClasseTest C:\java\testjunit>java -cp junit.jar;. junit.textui.TestRunner MaClasseTest . Time: 0,01 OK (1 test)
Attention : le respect de la casse dans le nommage des méthodes de tests est très important. Les méthodes de tests doivent obligatoirement commencer par test en minuscule.

Exemple :
import junit.framework.*; public class MaClasseTest extends TestCase{ public void TestCalculer() throws Exception { assertEquals(2,MaClasse.calculer(1,1)); } }
L'utilisation de cette classe avec JUnit produit le résultat suivant :

Exemple :
C:\java\testjunit>java -cp junit.jar;. junit.textui.TestRunner MaClasseTest .F Time: 0,01 There was 1 failure: 1) warning(junit.framework.TestSuite$1)junit.framework.AssertionFailedError: No tests found in MaClasseTest FAILURES!!! Tests run: 1, Failures: 1, Errors: 0

52.1.2. Exécution des tests avec JUnit

JUnit propose trois applications différentes nommées TestRunner pour exécuter les tests :

  • une application console : junit.textui.TestRunner.
  • une application graphique avec une interface Swing : junit.swingui.TestRunner
  • une application graphique avec une interface AWT : junit.awtui.TestRunner
Quelque soit l'application utilisée, le fichier junit.jar doit obligatoirement être inclus dans le CLASSPATH.

L'échec d'un cas de test peut avoir deux origines :

  • le cas de test est mal défini
  • le code exécuté contient un ou plusieurs bugs.
Suite à l'exécution d'un cas de test, celui ci peut avoir un des trois états suivants :

  • échoué : une exception de type AssertionFailedError est levée
  • en erreur : une exception non émise par le framework et non capturée a été levée dans les traitements
  • passé avec succès
L'échec d'un seul cas de test entraine l'échec du test complet.


52.1.2.1. Exécution des tests dans la console

L'utilisation de l'application console nécessite quelques paramètres lors de son utilisation :

Exemple :
C:\>java -cp junit.jar;. junit.textui.TestRunner MaClasseTest
Le seul paramètre obligatoire est le nom de la classe de tests. Celle ci doit obligatoirement être sous la forme pleinement qualifiée avec la notation Java si elle appartient à un package.

Exemple :
C:\>java -cp junit.jar;. junit.textui.TestRunner com.moi.test.junit.MaClasseTest
Il est possible de faire appel au TestRunner dans une application en utilisant sa méthode run() avec en paramètre un objet de type Class qui encapsule la classe de tests à exécuter.

Exemple :
public class TestJUnit1 { public static void main(String[] args) { junit.textui.TestRunner.run(MaClasseTest.class); } }

52.1.2.2. Exécution des tests dans une application graphique

Pour utiliser des classes de tests avec ces applications graphiques, il faut obligatoirement que les classes de tests et toutes celles dont elles dépendent soient incluses dans le CLASSPATH. Elles doivent obligatoirement être sous la forme de fichier .class non incluses dans un fichier jar.

C:\java\testjunit>java -cp junit.jar;. junit.swingui.TestRunner MaClasseTest

Il suffit de cliquer sur le bouton "Run" pour lancer l'exécution des tests.

C:\java\testjunit>java -cp junit.jar;. junit.awtui.TestRunner MaClasseTest

La case à cocher "Reload classes every run" indique à JUnit de recharger les classes à chaque exécution. Ceci est très pratique car cela permet de modifier les classes et de laisser l'application de test ouverte.


52.1.3. Ecriture des cas de tests JUnit


52.1.3.1. Définition de la classe de tests
Pour écrire les cas de tests, il faut écrire une classe qui étende la classe junit.framework.TestCase. Le nom de cette classe est le nom de la classe à tester suivi par "Test".

Exemple :
import junit.framework.*; public class MaClasseTest extends TestCase{ public void testCalculer() throws Exception { fail("Cas de test a ecrire"); } }

Dans cette classe, il faut écrire une méthode dont le nom commence par "test" en minuscule suivi du nom de chaque méthode de la classe à tester. Chacune de ces méthodes doit avoir les caractèrisques suivantes :

  • elle doit être déclarée public
  • elle ne doit renvoyer aucune valeur
  • elle ne doit pas posséder de paramètres.
Par introspection, JUnit va automatiquement rechercher toutes les méthodes qui respectent cette convention.

Le respect de ces règles est donc important pour une bonne exécution des tests par JUnit.

Exemple : la méthode commence par T et non t
import junit.framework.*; public class MaClasseTest extends TestCase{ public void TestCalculer() throws Exception { // assertEquals(2,MaClasse.calculer(1,1)); fail("Cas de test a ecrire"); } }
Résultat :
C:\>java -cp junit.jar;. junit.textui.TestRunner MaClasseTest .F Time: 0,01 There was 1 failure: 1) warning(junit.framework.TestSuite$1)junit.framework.AssertionFailedError: No tests found in MaClasseTest FAILURES!!! Tests run: 1, Failures: 1, Errors: 0

52.1.3.2. Définition des cas de tests
La classe suivante sera utilisée dans les exemples de cette section :

Exemple :
public class MaClasse2{ private int a; private int b; public MaClasse2(int a, int b) { this.a = a; this.b = b; } public int getA() { return a; } public int getB() { return b; } public void setA(int unA) { this.a = unA; } public void setB(int unB) { this.b = unB; } public int calculer() { int res = a + b; if (a == 0){ res = b * 2; } if (b == 0) { res = a * a; } return res; } public int sommer() throws IllegalStateException { if ((a == 0) && (b==0)) { throw new IllegalStateException("Les deux valeurs sont nulles"); } return a+b; } }
Les cas de tests utilisent des affirmations (assertion en anglais) sous la forme de méthodes nommées assertXXX() proposées par le framework. Il existe de nombreuses méthodes de ce type qui sont héritées de la classe junit.framework.Assert :

Méthode Rôle
assertEquals() Vérifier l'égalité de deux valeurs de type primitif. Il existe de nombreuses surcharges de cette méthode pour chaque type primitif, pour un objet de type Object et pour un objet de type String
assertFalse() Vérifier que la valeur fournie en paramètre est fausse
assertNotNull() Vérifier que l'objet fourni en paramètre ne soit pas null
assertSame() Vérifier que les deux objets fournis en paramètre font référence à la même entité
assertTrue() Vérifier que la valeur fournie en paramètre est vraie
Chacune de ces méthodes possède une version surchargée qui accepte un paramètre supplémentaire sous la forme d'une chaîne de caractères indiquant un message qui sera affiché en cas d'échec du cas de test.

Exemple : un cas de test simple
import junit.framework.*; public class MaClasse2Test extends TestCase{ public void testCalculer() throws Exception { MaClasse2 mc = new MaClasse2(1,1); assertEquals(2,mc.calculer()); } }
L'ordre des paramètres contenant la valeur attendue et la valeur obtenue est important pour obtenir un message d'erreur fiable en cas d'échec du cas de test.

La méthode fail() permet de forcer le cas de test à échouer. Une version surchargée permet de préciser un message qui sera affiché.

Il est aussi souvent utile lors de la définition des cas de tests de devoir tester si une exception est levée lors de l'exécution des traitements.

Exemple :
import junit.framework.*; public class MaClasse2Test extends TestCase{ public void testSommer() throws Exception { MaClasse2 mc = new MaClasse2(0,0); mc.sommer(); } }
Résultat :
C:\>java -cp junit.jar;. junit.textui.TestRunner MaClasse2Test .E Time: 0,01 There was 1 error: 1) testSommer(MaClasse2Test)java.lang.IllegalStateException: Les deux valeurs so nt nulles at MaClasse2.sommer(MaClasse2.java:42) at MaClasse2Test.testSommer(MaClasse2Test.java:31) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl. java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces sorImpl.java:25) FAILURES!!! Tests run: 2, Failures: 0, Errors: 1
Avec JUnit, pour réaliser de tels cas de tests, il suffit d'appeler la méthode avec les conditions qui doivent lever une exception, d'encapsuler cet appel dans un bloc try/catch et d'appler la méthode fail() si l'exception désirée n'est pas levée.

Exemple :
import junit.framework.*; public class MaClasse2Test extends TestCase{ public void testSommer() throws Exception { MaClasse2 mc = new MaClasse2(1,1); // cas de test 1 assertEquals(2,mc.sommer()); // cas de test 2 try { mc.setA(0); mc.setB(0); mc.sommer(); fail("Une exception de type IllegalStateException aurait du etre levee"); } catch (IllegalStateException ise) { } } }

52.1.3.3. La création et la destruction d'objets
Il est fréquent que les cas de tests utilisent une instance d'un même objet ou nécessitent l'usage de ressources particulières tel qu'une instance d'une classe pour l'accès à une base de données.

Pour réaliser ces opérations de créations et de destructions d'objets, la classe TestCase contient les méthodes setUp() et tearDown() qui sont respectivement appelées avant et après l'appel de chaque méthode contenant un cas de test.

Il suffit simplement de redéfinir en fonction de ces besoins ces deux méthodes.


52.1.4. Les suites de tests

Les suites de tests permettent de regrouper plusieurs tests dans une même classe. Ceci permet l'automatisation de l'ensemble des tests inclus dans la suite et de préciser leur ordre d'exécution.

Pour créer une suite, il suffit de créer une classe de type TestSuite et d'appeler la méthode addTest() pour chaque classe de test à ajouter. Celle ci attend en paramètre une instance de la classe de tests qui sera ajoutée à la suite. L'objet de type TestSuite ainsi créé doit être renvoyé par une méthode dont la signature doit obligatoirement être public static Test suite(). Celle ci sera appellée par introspection par le TestRunner.

Il peut être pratique de définir une méthode main() dans la classe qui encapsule la suite de tests pour pouvoir exécuter le TestRunner de la console en exécutant directement la méthode statique Run(). Ceci évite de lancer JUnit sur la ligne de commandes.

Exemple :
import junit.framework.*; public class ExecuterLesTests { public static Test suite() { TestSuite suite = new TestSuite("Tous les tests"); suite.addTestSuite(MaClasseTest.class); suite.addTestSuite(MaClasse2Test.class); return suite; } public static void main(String args[]) { junit.textui.TestRunner.run(suite()); } }
Deux versions surchargées des constructeurs permettent de donner un nom à la suite de tests.

Un constructeur de la classe TestSuite permet de créer automatiquement par instrospection une suite de tests contenant tous les tests de la classe fournie en paramètre.

Exemple :
import junit.framework.*; public class ExecuterLesTests2 { public static Test suiteDeTests() { TestSuite suite = new TestSuite(MaClasseTest.class,"Tous les tests"); return suite; } public static void main(String args[]) { junit.textui.TestRunner.run(suiteDeTests()); } }

52.1.5. L'automatisation des tests avec Ant

L'automatisation des tests fait par JUnit au moment de la génération de l'application est particulièrement pratique. Ainsi Ant propose une tâche optionnelle particulière nommée junit pour exécuter un TestRunner dans la console.

Pour pouvoir utiliser cette tache, les fichiers junit.jar (fourni avec JUnit) et optional.jar (fourni avec Ant) doivent être accessibles dans le CLASSSPATH.

Cette tâche possède plusieurs attributs dont aucun n'est obligatoire et les principaux sont :

Attibut Rôle Valeur par défaut
printsummary affiche un résumé statistique de l'exécution de chaque test off
fork exécution du TestRunner dans un JVM séparée off
haltonerror arrêt de la génération en cas d'erreur off
haltonfailure arrêt de la génération en cas d'échec d'un test off
outfile base du nom du fichier qui va contenir les résultats de l'exécution  
La tache <junit> peut avoir les élément fils suivants : <jvmarg>, <sysproperty>, <env>, <formatter>, <test>, <batchtest>

L'élément <formatter> permet de préciser le format de sortie des résultats de l'exécution des tests. Il possède l' attribut type qui précise le format (valeurs : xml, plain ou brief) et l'attribut usefile qui précise si les résultats doivent être envoyés dans un fichier (valeurs : true ou false)

L'élément <test> permet de préciser un cas de test simple ou une suite de test selon le contenu de la classe précisée par l'attribut name. Cet élément possède de nombreux attributs et il est possible d'utiliser un élément fils de type <formatter> pour définir le format de sortie du test.

L'élément <batchtest> permet de réaliser toute une série de tests. Cet élément possède de nombreux attributs et il est possible d'utiliser un élément fils de type <formatter> pour définir le format de sortie des tests. Les différentes classes dont les tests sont à exécuter sont précisées par un élément fils <fileset>.

La tache <junit> doit être exécutée après la compilation des classes à tester.

Exemple : extrait d'un fichier build.xml pour Ant
<?xml version="1.0" encoding="ISO-8859-1" ?> <project name="TestAnt1" default="all"> <description>Génération de l'application</description> <property name="bin" location="bin"/> <property name="src" location="src"/> <property name="build" location="build"/> <property name="doc" location="${build}/doc"/> <property name="lib" location="${build}/lib"/> <property name="junit_path" value="junit.jar"/> ... <target name="test" depends="compil" description="Executer les tests avec JUnit"> <junit fork="yes" haltonerror="true" haltonfailure="on" printsummary="on"> <formatter type="plain" usefile="false" /> <test name="ExecuterLesTests"/> <classpath> <pathelement location="${bin}"/> <pathelement location="${junit_path}"/> </classpath> </junit> </target> ... </project>
Cet exemple exécute les tests de la suite de tests encapsulés dans la classe ExecuterLesTests


52.1.6. Les extensions de JUnit

Junit est utilisé dans un certain nombre de projets qui proposent d'étendre les fonctionnalités de JUnit :

  • Cactus : un framework open source de tests pour des composants serveur
  • JunitReport : une tache Ant pour générer un rapport des tests effectués avec JUnit sous Ant
  • JWebUnit : un framework open source de tests pour des applications web
  • StrutsTestCase : extension de JUnit pour les tests d'application utilisant Struts 1.0.2 et 1.1
  • XMLUnit : extension de JUnit pour les tests sur des documents XML

52.2. Cactus

Cactus est un framework open source de tests pour des composants serveur. Il est développé en s'appuyant sur JUnit par le projet Jakarta du groupe Apache.

La dernière version de Cactus peut être téléchargée sur le site http://jakarta.apache.org/cactus/.


53. Des bibliothèques open source


53.1. JFreeChart

JFreeChart est une bibliothèque open source qui permet de créer des données statistiques sous la forme de graphiques. Elle possède plusieurs formats dont le camembert, les barres ou les lignes et propose de nombreuses options de configuration pour personnaliser le rendu des graphiques. Elle peut s'utiliser dans des applications standalone ou des applications web et permet également d'exporter le graphique sous la forme d'une image.


La version utilisée dans cette section est la 0.9.18.

Pour l'utiliser, il faut télécharger le fichier jfreechart-0.9.18.zip et le décompresser. Son utilisation nécessite l'ajout dans le classpath des fichiers jfreechart-0.9.18.zip et des fichiers .jar présents dans le répertoire lib décompressé.

Les données utilisées dans le graphique sont encapsulées dans un objet de type Dataset. Il existe plusieurs sous type de cette classe en fonction du type de graphique souhaité.

Un objet de type JFreechart encapsule le graphique. Une instance d'un tel objet est obtenue en utilisant une des méthodes de la classe ChartFactory.

Un exemple avec un graphique en forme de camembert
import java.awt.*; import java.awt.event.*; import javax.swing.*; import org.jfree.chart.*; import org.jfree.chart.plot.*; import org.jfree.data.*; public class TestPieChart extends JFrame { private JPanel pnl; public TestPieChart() { addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); pnl = new JPanel(new BorderLayout()); setContentPane(pnl); setSize(400, 250); DefaultPieDataset pieDataset = new DefaultPieDataset(); pieDataset.setValue("Valeur1", new Integer(27)); pieDataset.setValue("Valeur2", new Integer(10)); pieDataset.setValue("Valeur3", new Integer(50)); pieDataset.setValue("Valeur4", new Integer(5)); JFreeChart pieChart = ChartFactory.createPieChart("Test camembert", pieDataset, true, true, true); ChartPanel cPanel = new ChartPanel(pieChart); pnl.add(cPanel); } public static void main(String args[]) { TestPieChart tpc = new TestPieChart(); tpc.setVisible(true); } }
Pour chaque graphique, il existe de nombreuses possibilités de configuration.

Exemple :
... JFreeChart pieChart = ChartFactory.createPieChart("Test camembert", pieDataset, true, true, true); PiePlot piePlot = (PiePlot) pieChart.getPlot(); piePlot.setExplodePercent(1, 0.5); Legend legend = pieChart.getLegend(); legend.setAnchor(Legend.EAST_NORTHEAST); ChartPanel cPanel = new ChartPanel(pieChart); ...
Il est très facile d'exporter le graphique dans un flux.

Exemple : enregistrement du graphique dans un fichier
... File fichier = new File("image.png"); try { ChartUtilities.saveChartAsPNG(fichier, pieChart, 400, 250); } catch (IOException e) { e.printStackTrace(); } ...
JFreeChart propose aussi plusieurs autres types de graphiques dont les graphiques en forme de barres.

Exemple : un graphique sous formes de barres
import java.awt.*; import java.awt.event.*; import javax.swing.*; import org.jfree.chart.*; import org.jfree.chart.plot.*; import org.jfree.data.*; public class TestBarChart extends JFrame { private JPanel pnl; public TestBarChart() { addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); pnl = new JPanel(new BorderLayout()); setContentPane(pnl); setSize(400, 250); DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(120000.0, "Produit 1", "2000"); dataset.addValue(550000.0, "Produit 1", "2001"); dataset.addValue(180000.0, "Produit 1", "2002"); dataset.addValue(270000.0, "Produit 2", "2000"); dataset.addValue(600000.0, "Produit 2", "2001"); dataset.addValue(230000.0, "Produit 2", "2002"); dataset.addValue(90000.0, "Produit 3", "2000"); dataset.addValue(450000.0, "Produit 3", "2001"); dataset.addValue(170000.0, "Produit 3", "2002"); JFreeChart barChart = ChartFactory.createBarChart("Evolution des ventes", "", "Unité vendue", dataset, PlotOrientation.VERTICAL, true, true, false); ChartPanel cPanel = new ChartPanel(barChart); pnl.add(cPanel); } public static void main(String[] args) { TestBarChart tbc = new TestBarChart(); tbc.setVisible(true); } }
JFreechart peut aussi être mis en oeuvre dans une application web, le plus pratique étant d'utiliser une servlet qui renvoie dans la réponse une image générée par JfreeChart.

Exemple : JSP qui affiche le graphique
<%@ page language="java" %> <!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en"> <html> <head> <title>Test JFreeChart</title> </head> <body bgcolor="#FFFFFF"> <H1>Exemple de graphique avec JFreeChart</h1> <img src="/testlomboz2/ServletBarChart"> </body> </html>
Dans l'exemple précédent, l'image contenant le graphique est généré par une sevlet.

Exemple : servlet qui générère l'image
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import org.jfree.chart.*; import org.jfree.chart.plot.*; import org.jfree.data.*; public class ServletBarChart extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { DefaultCategoryDataset dataset = new DefaultCategoryDataset(); dataset.addValue(120000.0, "Produit 1", "2000"); dataset.addValue(550000.0, "Produit 1", "2001"); dataset.addValue(180000.0, "Produit 1", "2002"); dataset.addValue(270000.0, "Produit 2", "2000"); dataset.addValue(600000.0, "Produit 2", "2001"); dataset.addValue(230000.0, "Produit 2", "2002"); dataset.addValue(90000.0, "Produit 3", "2000"); dataset.addValue(450000.0, "Produit 3", "2001"); dataset.addValue(170000.0, "Produit 3", "2002"); JFreeChart barChart = ChartFactory.createBarChart("Evolution des ventes", "", "Unité vendue", dataset, PlotOrientation.VERTICAL, true, true, false); OutputStream out = response.getOutputStream(); response.setContentType("image/png"); ChartUtilities.writeChartAsPNG(out, barChart, 400, 300); } }
Cette section n'a proposé qu'une introduction à JFreeChart en proposant quelques exemples très simple sur les nombreuses possibilités de cette puissante bibliothèque.


54. Des outils open source pour faciliter le développement

La communauté open source propose de nombreuses bibliothèques mais aussi des outils dont le but est de faciliter le travail des dévelopeurs. Certains de ces outils sont détaillés dans des chapitres dédiés notamment Ant, Maven et JUnit. Ce chapitre va présenter d'autres outils open source pouvant être regroupés dans plusieurs catégories : contrôle de la qualité des sources et génération et mis en forme de code.

La génération de certains morceaux de code ou de fichiers de configuration peut parfois être fastidieuse voir même répétitif dans certains cas. Pour faciliter le travail des développeurs, des outils open source ont été développés par la communauté afin de générer certains morceaux de code. Ce chapitre présente deux outils open source : XDoclet et Middlegen.

La qualité du code source est un facteur important pour tous développements. Ainsi certains outils permettent de faire des vérifications sur des règles de codification dans le code source. C'est le cas pour l'outil CheckStyle.

Ce chapitre contient plusieurs sections :

  • CheckStyle
  • Jalopy
  • XDoclet
  • Middlegen

54.1. CheckStyle

CheckStyle est un outil open source qui propose de puissantes fonctionnalités pour appliquer des contrôles sur le respect de règles de codifications.

Pour définir les contrôles réalisés lors de son exécution CheckStyle utilise une configuration qui repose sur des modules. Cette configuration est définie dans un fichier XML qui précise les modules utilisés et pour chacun d'entre eux leurs paramètres.

Le plus simple est d'utiliser le fichier de configuration nommé sun_checks.xml fourni avec CheckStyle. Cette configuration propose d'effectuer des contrôles de respect des normes de codification proposée par Sun. Il est aussi possible de définir son propre fichier de configuration.

Le site officiel de CheckStyle est à l'URL : http://checkstyle.sourceforge.net/

La version utilisée dans cette section est la 3.4


54.1.1. Installation

Il faut télécharger le fichier checkstyle-3.4.zip sur le site de ChekStyle et le décompresser dans un répertoire du système.

La décompression de ce fichier créé un répertoire checkstyle-3.4 contenant lui même les bibliothèques utiles et deux répertoires (docs et contrib).

CheckStyle peut s'utiliser de deux façons :

  • en ligne de commande
  • comme une tâche Ant ce qui permet d'automatiser son exécution

54.1.2. Utilisation avec Ant

Pour utiliser CheckStyle, le plus simple est d'ajouter la bibliothèque checkstyle-all-3.4.jar au classpath.

Dans les exemples de cette section, la structure de répertoires suivante est utilisée :

Structure des répertoires
/bin /lib /outils /outils/lib /outils/checkstyle /src /temp /temp/checkstyle
Le fichier checkstyle-all-3.4.jar est copié dans le répertoire outils/lib et le fichier sun_checks.xml fourni par CheckStyle est copié dans le répertoire outils/checkstyle.

Il faut déclarer le tag CheckStyle dans Ant en utilisant le tag <taskdef> et définir une tâche qui va utiliser le tag <CheckStyle>.

Exemple : fichier source de test
public class MaClasse { public static void main() { System.out.println("Bonjour"); } }
Le fichier de build ci-dessous sera exécuté par Ant.

Exemple :
<project name="utilisation de checkstyle" default="compile" basedir="."> <!-- Definition des proprietes du projet --> <property name="projet.sources.dir" value="src"/> <property name="projet.bin.dir" value="bin"/> <property name="projet.lib.dir" value="lib"/> <property name="projet.temp.dir" value="temp"/> <property name="projet.outils.dir" value="outils"/> <property name="projet.outils.lib.dir" value="${projet.outils.dir}/lib"/> <!-- Definition du classpath du projet --> <path id="projet.classpath"> <fileset dir="${projet.lib.dir}"> <include name="*.jar"/> </fileset> <fileset dir="${projet.outils.lib.dir}"> <include name="*.jar"/> </fileset> <pathelement location="${projet.bin.dir}" /> </path> <!-- Declaration de la tache Ant permettant l'execution de checkstyle --> <taskdef resource="checkstyletask.properties" classpathref="projet.classpath" /> <!-- execution de checkstyle --> <target name="checkstyle" description="CheckStyle"> <checkstyle config="outils/checkstyle/sun_checks.xml"> <fileset dir="${projet.sources.dir}" includes="**/*.java"/> <formatter type="plain"/> </checkstyle> </target> <!-- Compilation des classes du projet --> <target name="compile" depends="checkstyle" description="Compilation des classes"> <javac srcdir="${projet.sources.dir}" destdir="${projet.bin.dir}" debug="on" optimize="off" deprecation="on"> <classpath refid="projet.classpath"/> </javac> </target> </project>
Résultat :
C:\java\test\testcheckstyle>ant Buildfile: build.xml checkstyle: [checkstyle] C:\java\test\testcheckstyle\src\package.html:0: Missing package doc umentation file. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:0: File does not end with a newline. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:2: Missing a Javadoc comment. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:2:1: Utility classes should not have a public or default constructor. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:4:3: Missing a Javado c comment. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:5: Line has trailing spaces. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:5:35: La ligne contie nt un caractÞre tabulation. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:7: Line has trailing spaces. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:7:1: La ligne contien t un caractÞre tabulation. BUILD FAILED file:C:/java/test/testcheckstyle/build.xml:27: Got 9 errors. Total time: 7 seconds
Le tag <checkstyle> possède plusieurs attributs :

Nom Rôle
file précise le nom de l'unique fichier à vérifier. Pour préciser un ensemble defichiers, il faut définir un ensemble de fichiers grâce à un tag fils<fileset>
config précise le nom du fichier de configuration des modules de ChecksStyle
failOnViolation précise si les traitements de Ant doivent être stoppés en cas d'échec des contrôles. La valeur par défaut est true
failureProperty précise le nom d'une propriété qui sera valorisée en cas d'échec des contrôles
Exemple :
... <!-- execution de checkstyle --> <target name="checkstyle" description="CheckStyle"> <checkstyle config="outils/checkstyle/sun_checks.xml" failOnViolation="false"> <fileset dir="${projet.sources.dir}" includes="**/*.java"/> <formatter type="plain"/> </checkstyle> </target> ...
Résultat :
C:\java\test\testcheckstyle>ant Buildfile: build.xml checkstyle: [checkstyle] C:\java\test\testcheckstyle\src\package.html:0: Missing package doc umentation file. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:2: Missing a Javadoc comment. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:2:1: Utility classes should not have a public or default constructor. [checkstyle] C:\java\test\testcheckstyle\src\MaClasse.java:4:3: Missing a Javado c comment. compile: [javac] Compiling 1 source file to C:\java\test\testcheckstyle\bin BUILD SUCCESSFUL Total time: 11 seconds
Il est possible de préciser deux types de format de sortie des résultats lors de l'exécution de CheckStyle. Le format de sortie des résultats est précisé par un tag fils <formatter>. Ce tag possède deux attributs :

Nom Rôle
type précise le type. Deux valeurs sont possibles : plain (par défaut) et xml
toFile préciseun fichier qui va contenir les résultats dont le format correspondra autype (par défaut la sortie standard de la console)
Exemple
... <!-- execution de checkstyle --> <target name="checkstyle" description="CheckStyle"> <checkstyle config="outils/checkstyle/sun_checks.xml" failOnViolation="false"> <fileset dir="${projet.sources.dir}" includes="**/*.java"/> <formatter type="xml" toFile="${projet.temp.dir}/checkstyle_erreurs.xml"/> </checkstyle> </target> ...
Il est alors possible d'appliquer une feuille de style sur le fichier XML généré afin de créer un rapport dans un format dédié. L'exemple suivant utilise une feuille de style fournie par CheckStyle dans le répertoire contrib : cette feuille, nommée checkstyle-frames.xsl, est copiée dans le répertoire outils/checkstyle.

Exemple :
... <!-- execution de checkstyle --> <target name="checkstyle" description="CheckStyle"> <checkstyle config="${projet.outils.dir}/checkstyle/sun_checks.xml" failOnViolation="false"> <fileset dir="${projet.sources.dir}" includes="**/*.java"/> <formatter type="xml" toFile="${projet.temp.dir}/checkstyle/checkstyle_erreurs.xml"/> </checkstyle> <style in="${projet.temp.dir}/checkstyle/checkstyle_erreurs.xml" out="${projet.temp.dir}/checkstyle/checkstyle_rapport.htm" style="${projet.outils.dir}/checkstyle/checkstyle-frames.xsl"/> </target> ...
Résultat :
C:\java\test\testcheckstyle>ant Buildfile: build.xml checkstyle: [style] Processing C:\java\test\testcheckstyle\temp\checkstyle\checkstyle_er reurs.xml to C:\java\test\testcheckstyle\temp\checkstyle\checkstyle_rapport.htm [style] Loading stylesheet C:\java\test\testcheckstyle\outils\checkstyle\che ckstyle-frames.xsl compile: BUILD SUCCESSFUL Total time: 8 seconds
Il est possible d'utiliser d'autres feuilles de style fournies par CheckStyle ou de définir sa propre feuille de style.


54.1.3. Utilisation en ligne de commandes

Pour utiliser CheckStyle en ligne de commandes, il faut ajouter le fichier checkstyle-all-3.4.jar au classpath par exemple en utilisant l'option –cp de l'interpréteur Java.

La classe à exécuter est com.puppycrawl.tools.checkstyle.Main

CheckStyle accepte plusieurs paramètres pour son exécution :

Option Rôle
-c fichier_de_configuration précise le fichier de configuration
-f format précise le format (plain ou xml)
-o fichier précise le fichier qui va contenir les résultats
-r précise le répertoire dont les fichiers sources vont être récursivement traités
Exemple :
java -cp outils\lib\checkstyle-all-3.4.jar com.puppycrawl.tools.checkstyle.Main -c outils\checkstyle/sun_checks.xml -r src
Exemple :
... C:\java\test\testcheckstyle>java -cp outils\lib\checkstyle-all-3.4.jar com.puppy crawl.tools.checkstyle.Main -c outils\checkstyle/sun_checks.xml -r src Starting audit... C:\java\test\testcheckstyle\src\package.html:0: Missing package documentation fi le. src\MaClasse.java.bak:0: File does not end with a newline. src\MaClasse.java:2: Missing a Javadoc comment. src\MaClasse.java:2:1: Utility classes should not have a public or default const ructor. src\MaClasse.java:4:3: Missing a Javadoc comment. Audit done. ...

54.2. Jalopy

Jalopy est un outil open source qui propose de formater les fichiers source selon des règles définies.

Le site web officiel de Jalopy est http://jalopy.sourceforge.net

Jalopy propose entre autre les fonctionnalités suivantes :

  • formatage des accolades selon plusieurs format (C, Sun, GNU)
  • indentation du code
  • gestion des sauts de ligne
  • génération automatique ou vérification des commentaires Javadoc
  • ordonnancement des éléments qui composent la classe
  • ajout de texte au début et la fin de chaque fichier
  • des plug in pour une intégration dans plusieurs outils : ant, Eclipse, Jbuilder, …
  • ...
Pour connaître les règles de formatage à appliquer, Jalopy utilise une convention qui est un ensemble de paramètres.

Jalopy peut être utilisé grâce à ces plug ins de plusieurs façons notamment avec Ant, en ligne commande ou avec certains IDE.

La version de Jalopy utilisée dans cette section est la 1.0.B10


54.2.1. Utilisation avec Ant

Le plus simple est d'utiliser Jalopy avec Ant pour automatiser son utilisation : pour cela, il faut télécharger le fichier jalopy-ant-0.6.2.zip et le décompresser dans un répertoire du système.

La structure de l'arborescence du projet utilisé dans cette section est la suivante :

Arborescence du projet
/bin /lib /outils /outils/lib /src
Le répertoire src contient les sources Java à formater.

Les fichiers du répertoires lib de Jalopy sont copiés dans le répertoire outils/lib du projet.

Exemple : le fichier source qui sera formaté
public class MaClasse {public static void main() { System.out.println("Bonjour"); }}
Il faut définir un fichier build.xml pour Ant qui va contenir les différentes tâches du projet dont une permettant l'appel à Jalopy.

Exemple :
<project name="utilisation de jalopy" default="jalopy" basedir="."> <!-- Definition des proprietes du projet --> <property name="projet.sources.dir" value="src"/> <property name="projet.bin.dir" value="bin"/> <property name="projet.lib.dir" value="lib"/> <property name="projet.temp.dir" value="temp"/> <property name="projet.outils.dir" value="outils"/> <property name="projet.outils.lib.dir" value="${projet.outils.dir}/lib"/> <!-- Definition du classpath du projet --> <path id="projet.classpath"> <fileset dir="${projet.lib.dir}"> <include name="*.jar"/> </fileset> <fileset dir="${projet.outils.lib.dir}"> <include name="*.jar"/> </fileset> <pathelement location="${projet.bin.dir}" /> </path> <!-- Declaration de la tache Ant permettant l'execution de jalopy --> <taskdef name="jalopy" classname="de.hunsicker.jalopy.plugin.ant.AntPlugin" classpathref="projet.classpath" /> <!-- execution de jalopy --> <target name="jalopy" description="Jalopy" depends="compile" > <jalopy loglevel="info" threads="2" classpathref="projet.classpath"> <fileset dir="${projet.sources.dir}"> <include name="**/*.java" /> </fileset> </jalopy> </target> <!-- Compilation des classes du projet --> <target name="compile" description="Compilation des classes"> <javac srcdir="${projet.sources.dir}" destdir="${projet.bin.dir}" debug="on" optimize="off" deprecation="on"> <classpath refid="projet.classpath"/> </javac> </target> </project>
Exemple :
C:\java\test\testjalopy>ant Buildfile: build.xml compile: [javac] Compiling 1 source file to C:\java\test\testjalopy\bin jalopy: [jalopy] Jalopy Java Source Code Formatter 1.0b10 [jalopy] Format 1 source file [jalopy] C:\java\test\testjalopy\src\MaClasse.java:0:0: Parse [jalopy] 1 source file formatted BUILD SUCCESSFUL Total time: 9 seconds
Suite à l'exécution de Jalopy, le code du fichier est reformaté.

Exemple :
public class MaClasse { public static void main() { System.out.println("Bonjour"); } }
Il est fortement recommandé de réaliser la tâche de compilation des sources avant leur formatage car pour assurer un formatage correct les sources doivent être corrects syntaxiquement parlant.


54.2.2. Les conventions

Jalopy est hautement paramétrable. Les options utilisées sont regroupées dans une convention.

Tous ses paramètres sont stockés dans le sous répertoire .jalopy du répertoire Home de l'utilisateur.

Pour faciliter la gestion de ces paramètres, Jalopy propose un outil graphique qui permet de gérer les conventions.

Pour exécuter cet outil, il suffit de lancer le script preferences dans le répertoire bin de Jalopy (preferences.bat sous Windows et preferences.sh sous Unix).

Toutes les nombreuses options de formatage d'une convention peuvent être réglées via cet outil. Consultez la documentation fournie avec Jalopy pour un détail de chaque option.

Une fonctionnalité particulièrement utile de cet outil est de proposer une pré-visualisation d'un exemple mettant en oeuvre les options sélectionnées.

Voici un exemple avec quelques personnalisations notamment une gestion des clauses import, la génération des commentaires Javadoc :

Exemple :
import java.util.*; public class MaClasse { public static void main() { List liste = new ArrayList(); System.out.println("Bonjour"); } /** * */ private int maMethode(int valeur) { return valeur * 2; } }
Résultat :
C:\java\test\testjalopy>ant Buildfile: build.xml compile: [javac] Compiling 1 source file to C:\java\test\testjalopy\bin jalopy: [jalopy] Jalopy Java Source Code Formatter 1.0b10 [jalopy] Format 1 source file [jalopy] C:\java\test\testjalopy\src\MaClasse.java:0:0: Parse [jalopy] C:\java\test\testjalopy\src\MaClasse.java:1:0: On-demand import "jav a.util.List" expanded [jalopy] C:\java\test\testjalopy\src\MaClasse.java:1:0: On-demand import "jav a.util.ArrayList" expanded [jalopy] C:\java\test\testjalopy\src\MaClasse.java:11:1: Generated Javadoc co mment [jalopy] C:\java\test\testjalopy\src\MaClasse.java:18:3: Generated Javadoc co mment [jalopy] 1 source file formatted BUILD SUCCESSFUL Total time: 10 seconds
Voici le source du code reformaté :

Exemple :
//============================================================================== // fichier : MaClasse.java // projet : $project$ // // Modification : date : $Date$ // auteur : $Author$ // revision : $Revision$ //------------------------------------------------------------------------------ // copyright: JMD //============================================================================== import java.util.ArrayList; import java.util.List; /** * DOCUMENT ME! * * @author $author$ * @version $Revision$ */ public class MaClasse { /** * DOCUMENT ME! */ public static void main() { List liste = new ArrayList(); System.out.println("Bonjour"); System.out.println(""); } /** * Calculer le double * * @param valeur DOCUMENT ME! * * @return DOCUMENT ME! */ private int maMethode(int valeur) { return valeur * 2; } } // fin du fichier

54.3. XDoclet

La suite de ce chapitre sera développée dans une version future de ce document


54.4. Middlegen

La suite de ce chapitre sera développée dans une version future de ce document



Copyright (C) 1999-2004 DOUDOUX Jean Michel Vous pouvez copier, redistribuer et/ou modifier ce document selon les termes de la Licence de Documentation Libre GNU, Version 1.1 ou toute autre version ultérieure publiée par la Free Software Foundation; les Sections Invariantes étant constitués du chapitre Préambule, aucun Texte de Première de Couverture, et aucun Texte de Quatrième de Couverture. Une copie de la licence est incluse dans la section GNU FreeDocumentation Licence. La version la plus récente de cette licence est disponible à l'adresse : GNU Free Documentation Licence.

Responsables bénévoles de la rubrique Java : Mickael Baron - Robin56 -