Voilà, c’est notre deuxième participation au DevoxxFR (sur deux éditions) et, bien qu’il y ait des redondances d’une année sur l’autre, l’impression qui s’en dégage est celle d’un souffle de fraîcheur et une volonté positive de bouger les lignes; Concrètement, être confronté à la fine fleur du développement et ses retours d’expérience sur des cas très pointus ne peut qu’être profitable :

  • Cela ouvre l’esprit quant à l’application sur nos projets présents ou à venir,
  • On capte indéniablement l’énergie positive qui se dégage de ces success story (… On peut aussi apprendre à la ‘Failure Conference’ http://france.thefailcon.com/) ,
  • On entrevoit notamment ce qui fait les succès des ‘Grands Du Web’ et comment on peut en tirer parti pour nos projets qui doivent composer avec un historique pas toujours simple à adresser

Comprendre les technologies qui motorisent les grands du Web

Exemple : L’utilisation de briques BigData pour booster son architecture et lui permettre de faire face aux défis de volumétrie que nous observons et qui n’en finiront plus de déferler :

  • Hadoop / Storm / Mahout,
  • Implémentation de solutions ‘Cloud’ : CloudBees, Google App Engine…
  • Du SQL au NoSQL (avec des morceaux de ElasticSearch dedans)

Bien plus que Java et la JVM

Toucher concrètement du doigt les nouvelles technologies (plus ou moins matures… il faut savoir faire le tri) donne une furieuse envie de faire bouger les lignes parfois un peu trop rigides (Architecture, Pratiques de développement)… à faire avec discernement bien entendu.

Par exemple : On a pu observer la poursuite de la montée en puissance du JavaScript et sa professionnalisation; on peut naturellement retenir cette approche pour :

  • L’écriture de tests d’acceptance (KarmaJS, PhantomJS, Mocha, Chai…),
  • La réalisation d’applications pures JS + CSS / HTML5 avec Angular / Ember /Backbone.

Autre observation: on en finit plus également de constater les mérites des langages fonctionnels pour leur expressivité et leur robustesse (Scala , Haskell…) et globalement les bénéfices de regarder plus loin que le seul langage Java.
Les combats épiques de Frameworks (Grails vs Play ! ) et de langages ont été à la fois réjouissants et instructifs : il faut juger constamment les technologies qu’on utilise ou qu’on pourrait utiliser et les mettre en perspective de nos propres enjeux.

et après DevoxxFR ?

Dans les jours à venir, nous reviendrons en détail sur un certain nombre de conférences et ateliers, en attendant notre conclusion est la suivante :

Il est nécessaire de cultiver son ouverture aux technologies et méthodes qui nous permettent de mieux répondre aux défis posés par nos projets :

  • C’est plus valorisant de constater qu’une de nos propositions a pu répondre positivement à une problématique (Performance, Accélération des livraisons, Qualité globale),
  • C’est une manière concrète de montrer à notre client et à nos collègues la valeur ajoutée que l’on apporte, au-delà du rôle frustrant à terme de ‘simple réalisateur’.

Cette curiosité et ce savoir-faire se cultivent continuellement (blogs, tutoriaux, projets), mais également au travers des Groupes d’utilisateurs (Java UG, Hadoop UG, Mongo UG, Android UG….) et DevoxxFR constitue un des moments incontournables pour avoir un aperçu de l’effervescence de ces éco-systèmes.

ou ‘Un coup d’œil aux gestionnaires de code source distribué’

Dans le domaine des solutions d’hébergement de projet autour du gestionnaire de source Git, deux solutions tiennent le devant de la scène aujourd’hui : Github et Bitbucket.

Voici un petit comparatif des forces et faiblesses pour vous aider à choisir, en fonction de vos attentes et de votre organisation.

Pour parler popularité, Github concentre la plus grande partie des dépôts de sources (plus de 2 millions, avec une grande représentation de projets ‘stars’ : Grails & spring sont sur Github). L’avance prise sur BitBucket s’explique notamment par les fonctionnalités et innovations apportées à ce qui est véritablement une plateforme de développement… BitBucket faisant surtout du suivisme.

Il est important de noter que BitBucket est supporté par Atlassian, qui a une certaine assise dans le monde open source (JIRA, Confluence ….)

Ils partagent une caractéristique commune et étonnante : la taille illimitée des espaces réservés au code source. Cela s’explique facilement par la nature décentralisée de Git et Mercurial et donc par la volumétrie intrinsèquement modeste du code et des méta-données.

Comparaison

Voici une grille de comparaison des tarifs et de caractéristiques structurantes prou des projets ‘Entreprise’

comparatif quantitatif Github BitBucket

(la soft limit pour github est là pour prévenir les abus, il n’y a pas de limite réelle sur la taille)

Sur ces données, les deux solutions sont relativement proches; l’écart se creuse en revanche sur la complétude des fonctionnalités couvertes, qui sont mieux adressées par GitHub:

comparatif qualitatif Github BitBucket

Plus éloquant, voici une liste des fonctionnalités intéressantes de Github dont ne dispose pas Bitbucket:

fonctionnalités supportées par GitHub uniquement

Pour aller plus loin

…ou la descente aux enfers d’une application JSF, RICHFACES, SPRING

Voici un retour d’expérience sur un événement projet comme on est appelé à en rencontrer beaucoup sur le cycle de vie d’une application, notamment lors de la maintenance, les enseignements à en tirer sont nombreux.

Il s’agissait de migrer de version une application développée en JSF1.2/RichFaces de navigateur Internet Explorer 8 (IE8) vers IE9.

Pour avoir passé il y a peu la redoutable montée de version de IE6 vers IE8, l’équipe en charge du développement, parfaitement rompue à ce contexte technique, avançait avec confiance sur ce sujet. Tout au plus devait-il s’agir d’ajustements cosmétiques isolés…. Mais ce petit battement d’aile de papillon a provoqué une belle tornade sur toute l’application, dont voici les détails.

Cadre technique: l’application en question est conçue selon une architecture multicouche avec les librairies & versions suivantes, qui ont leur importance pour la suite des événements :

dépendances JSF, Spring, RichFaces, JUnit

Après un premier test rapide, les comportements Ajax qui sont massivement utilisés par RichFaces ne fonctionnent pas sous IE9. C’est étonnant à double titre :

  • Les appels ajax sont motorisés par jQuery dont la portabilité est un gros point fort,
  • Les développements jQuery faits par ailleurs ne présentent aucune régression

RichFaces fonctionnant en ‘boîte noire’, il a été décidé de migrer en version 4.0, réputée compatible avec IE9.

Dépendances JSF, RichFaces, Spring, Junit 2

Des changements en cascade

Comme représenté ci-dessus, RichFaces 4 ne se branche que sur du JSF 2.0 : ce sera donc notre première étape de montée de version collatérale.

Puis s’enchainent les étapes suivantes :

  • JSF2.0 impose Spring Web Flow 2.3
  • Spring Web Flow nécessite Spring (Core & Security)>=3.0 et Spring Faces >=2.3.0
  • Spring 3.0 nécessite de passer JUnit en 4.9 ; en effet, le chargement du fichier de contexte applicatif bloquait lors des lancements de test.

En arrivant à la situation où les briques au cœur de notre application ont été remplacées… ainsi que celles qui sont plus ‘périphériques’ :

Dépendances JSF, RichFaces, Spring, JUnit 3

Il faut surtout se figurer que chacune de ces montées de version a provoqué de difficultés :

  • Bugs notoires ( a4j :commandLink non opérationnels dans Spring faces 2.3.0) : application d’un patch ou bien attente de la version corrective ? c’est selon vos priorités.
  • Changement de configuration xml (faces-config.xml, web.xml, tous ces fichiers au cœur de l’application sont impactés),
  • Incompatibilité de versions de servlet avec Tomcat,
  • Modification de certaines balises JSF : impact sur toutes les JSPs,
  • Perte des espaces de nom sous Eclipse (entrant en confilt au niveau des xsd préalablement utilisés : Une montée de version du plugin spring d’eclipse peut corriger ces problèmes
  • …et encore bien d’autres plus ou moins intrusives

De plus, ces incohérences étaient parfois à l’origine de problèmes rencontrés seulement à l’exécution du serveur au travers d’exceptions NoSuchMethodException et java.lang.UnsupportedOperationException pour lesquelles la difficulté était de trouver la librairie en cause. Elles survenaient au chargement de l’application ou bien au détour d’une page, ce qui exigeait de faire des tests exhaustifs.

Voici quelques conclusions que nous pouvons en tirer :

1) Basique : IE9 et RichFaces 3.3.3 ne font pas bon ménage !

2) Architecture : les applications composites sont une approche rationnelle pour tirer profit des innombrables librairies adressant chacune au mieux le rôle pour lequel elles ont été créées. Si elles mettent effectivement à disposition une grande richesse de fonctionnalités, elles peuvent se révéler instables quand on doit en modifier un élément technique.

3) JSF (et autres frameworks Web à forte cohésion avec le serveur): la structuration d’applications JSF est intrinsèquement orientée serveur (règles de navigation, de contrôle, cycle de vie des Beans…) et de ce fait entraîne des changements profonds dans les cas problématiques comme celui-ci. Les pistes désormais explorées vers une séparation plus nette entre client Web et un serveur orienté REST permettra de clarifier certaines pratiques et alléger la responsabilité du serveur dans la génération de l’interface utilisateur.

4) Gestion des dépendances : engagés dans une application composite, il faudra couvrir les versions parfois conflictuelles de librairies, d’implémentations. Même outillée avec Maven, cela reste difficile quand c’est à l’exécution, avec des erreurs absconses, que cela se caractérise.

5) Tests : sur une application riche fonctionnellement, qui va traverser malgré elle quelques générations techniques, un portefeuille de tests automatisés sera le garant d’une bonne maîtrise de la non régression (Unitaires, Fonctionnels) ; Dans ce cas présent, l’application dispose d’un riche panel de tests JUnit à connotation ‘Intégration’, faute de scripts Selenium exhaustifs (seuls quelques uns on été créés).

6) Projet : De la difficulté récurrente de connaître l’impact d’une évolution, même sur un environnement technique et fonctionnel bien maîtrisé.

7) Open source : à la fois riche et ouvert, il peut se rendre problématique pour des demandes de support. Nous sommes dans le cas de communautés très importantes, très réactives, ce qui facilite la prise en compte des anomalies / évolutions ; mais cela sera dommageable sur des librairies de niches, peu documentée ou suivies…. La pérennité est à prendre en compte.

« Jeter un regard objectif sur la qualité du code de l’application, pour en évaluer le niveau de maintenabilité »

Le contexte du projet

Une application connait plusieurs vies : la conception, la définition des principes d’architecture, l’implémentation, la mise en production du projet, puis la maintenance.
On définit classiquement en début de projet les éléments d’architectures logicielles, le rôle des différents composants, packages ou sous-projets et les bonnes pratiques à appliquer.

De manière très schématique, le projet aboutit à une version stabilisée lors de la première mise en production, avec une équipe ayant une connaissance métier et technique importante pour avoir initié et réalisé cette première phase. Mais quand vient la période des premières maintenances correctives et évolutives, l’équipe en place a été réduite ou remplacée, et les nouvelles réalisations doivent le plus souvent être réalisées par une équipe qui ne possède pas ou incomplètement la « mémoire » du projet.

A cela s’ajoute un phénomène classique lorsque le projet a connu une évolution conséquente de son périmètre fonctionnel lors de la réalisation :

  • Contraint par les délais, la date de livraison n’est pas modifiée,
  • L’équipe est sous pression pour livrer l’application à temps en jonglant entre : la couverture fonctionnelle, la maîtrise technique et la documentation,
  • Les phases de recette et les dispositifs consacrés à la qualité (lecture croisée du code, exécution et analyse de la qualimétrie, documentation) sont sacrifiés au profit du respect du jalon.

Dérive Coût Qualité Délai

Les audits de codes servent la viabilité du projet et peuvent être menés :

  1. Périodiquement pendant les développements pour surveiller la stabilité du niveau de qualité,
  2. A des moments clés : transmission de responsabilité du projet à un nouveau fournisseurou à une nouvelle équipe, passage du mode projet en mode maintenance, opération de benchmark.

La finalité est d’éviter ce que l’on rencontre le plus souvent sur des projets nés dans la difficulté (et ils sont nombreux…) et dont la maintenance a été chaotique : un mille-feuille de code instable, où l’on détecte les interventions de multiples intervenants qui impriment leur approche personnelle du codage, des normes, et leur interprétation des règles métier.

Les enjeux de l’audit de code

Lorsque nous initions un audit de code complet, nous nous attachons à le mener selon :

  • 1. Un axe ‘Architecture technique globale’ où nous étudions le découpage en sous-projets, en couches techniques, l’industrialisation et le respect dans le temps des normes et méthodes en vigueur ;
  • 2. Un axe métier, en sélectionnant un échantillon de fonctionnalités critiques qui sont représentatives de l’application :
    • De par la complexité et le nombre des règles de gestion impliquées,
    • De par la fréquence d’utilisation de la fonctionnalité lors de l’activité normale des utilisateurs,
    • De par la spécificité liée au métier : forte transversalité (comme la gestion d’un workflow), forte réutilisation attendue ;
  • 3. Un axe ‘outillage’ reposant sur des mesures automatisées avec un usage pondéré et personnalisé des outils :

Quelques généralités :
L’audit de code ne doit pas être dogmatique et il est nécessaire de savoir faire la part des choses exigibles selon la typologie du projet : complexité, criticité pour les métiers, ou en fonction des jalons dans la vie du projet (début, maintenance, fin).

Audit par échantillonnage fonctionnel

A partir des fonctionnalités identifiées, on vérifie que le couple « documentation + code » nous fournit les points d’entrée et la lisibilité nécessaires pour une activité de maintenance :

  • Nécessité d’identifier où se trouvent les fonctionnalités, comment elles sont organisées ;
  • Nécessité d’avancer en confiance dans le code en sachant comment les traitements de validation, contrôle, métier, ou persistance sont implémentés. A ce titre, il est impératif de vérifier que les règles de nommage sont homogènes et pertinentes et que la Javadoc est correctement renseignée.

Diagnostic audit d'échantillon fonctionnel

L’équipe d’audit détecte ainsi les forces et faiblesses du code de l’application sur les pans les plus sensibles et qui seront les plus concernés par la maintenance évolutive, laquelle pourrait apporter une certaine instabilité en cas de non maîtrise des fondamentaux techniques et fonctionnels.

La prochaine évolution sera-t-elle la carte qui provoquera la chute de ce qui tenait en équilibre jusqu’à présent ?

Audit par outillage

Cette approche permet de couvrir l’exhaustivité de l’application( avec certes moins de discernement que par échantillonnage), et de relever toutes les non conformités existantes avec différents niveaux de criticité : informatif, mineur et majeur.

En Java, les outils FindBugs et Checkstyle sont, par exemple, une première étape nécessaire pour révéler l’état de santé globale de l’application au regard des bonnes pratiques de codage.
On peut juger de manière globale chacun des domaines suivants :

  • Complétude de la JavaDoc,
  • Bonnes pratiques de codage (robustesse: default dans un switch, gestions des cas aux limites, des valeurs nulles),
  • Complexité du code : respect des tailles (nb de lignes par classe, par méthode, …), imbrications de boucles, lisibilité,
  • Duplication de code,
  • Règles de nommage
    • Pour plus de pertinence, l’équipe procède à une exécution par passes successives pour:

      • sélectionner les critères et calibrer les seuils,
      • avoir une vue plus précise en écartant temporairement les éventuels métriques tombés en alerte.

      Résultats synthétiques de l'audit avec CheckStyle

      En croisant les informations avec l’audit par échantillonnage, on dispose d’un maillage dense entre :

      • Le type de non conformités rencontrées,
      • L’homogénéité (ou non) de la répartition de ces manquements aux bonnes pratiques.

      Pour aller plus loin dans le détail et pouvoir juger dans la durée de l’évolution de la qualité du projet, nous utilisons InfoScope Source. Ce produit nous permet de donner une profondeur à plusieurs dimensions à notre audit technique :

      • 1. Une dimension technique
        InfoScope Source offre la possibilité d’ajouter / enlever des métriques, de définir des seuils de gravité.
      • 2. Une dimension de composants auscultés
        On observe au travers de l’outil les notes depuis une vue globale, par Projet, puis en profondeur :
        Projet > Package > Classe > Méthode

        A chaque niveau son tableau de bord récapitulatif.

      • 3. Une dimension temporelle
        InfoScope Source offre un suivi des tendances de la qualimétrie d’un projet dans le temps pour observer les progrès ou dérives.

      Stabilité parfaite de la qualité entre deux mesures

      Le résultat est une restitution navigable dans l’outil qui donne à chaque niveau le degré de maintenabilité du domaine observé ainsi que le détail des non-conformités entrant en jeu.


      Exemple de restitution exploitant Infoscope Source :

      Les problèmes se concentrent essentiellement dans les packages ‘services’ du projet. Cependant, ces classes sont notées très négativement et déprécient de ce fait la note globale. De plus, elles regroupent l’essentiel des lignes de code du projet et des règles métier, ce qui leur donne encore plus de poids dans la note finale.
      Les non-conformités les plus rencontrées sont :
      i. Non respect de la syntaxe des boucles ‘if’.
      ii. Complexité cyclomatique (imbrication de règles fonctionnelles, de boucles de traitement, de conditions) importante, voir extrêmement élevée.
      iii. Nombre de méthodes et du nombre de lignes par méthode non maîtrisé
      iv. Taux de commentaire insuffisant (notamment sur les classes les plus volumineuses et les plus importantes fonctionnellement)

      Les pré-requis pour mener un audit

      Les membres de l’équipe doivent disposer d’un solide bagage technique, c’est évident. Non seulement il faut avoir connaissance des bonnes pratiques générales pour pouvoir juger du code, mais il faut encore avoir travaillé sur suffisamment de projets et d’environnements pour comprendre les spécificités techniques et les choix d’architecture pour prendre le recul nécessaire.

      Il faut également connaître la façon dont fonctionne une équipe de développement, en mode projet ou en maintenance, pour identifier :

      • 1. Les raisons des dérives qui seraient observées,
      • 2. Pour caractériser la gravité de certaines non-conformités en termes d’impact sur l’organisation,
      • 3. Planifier de manière argumentée et priorisée les actions correctives.

      En sortie d’audit…

      L’équipe consolide les informations au travers de préconisations organisées selon leurs priorités : gravité de la non-conformité, ou impact potentiel sur l’application.
      On peut citer à titre d’exemple :

      • Renforcer la couverture de tests unitaires (en ciblant préférentiellement les classes au cœur de l’application),
      • Harmoniser et compléter la documentation de façon pertinente,
      • Respecter absolument l’inclusion des traitements cohérents dans une seule et même transaction (ACID),
      • Réduire les points et anomalies relevés par FindBugs et CheckStyle.

      Les équipes de maintenance disposent alors des éléments nécessaires pour faire vivre et évoluer l’application dans les meilleures conditions de sécurité, de coûts et de productivité.

      Enfin, Il est préconisé de mener ces audits de façon régulière, avant que la dérive n’exige un travail de mise à niveau trop conséquent et finalement décourageant.

Intégrer une base de données HSQL DB dans une persistance JPA / Hibernate

cet article fait suite à la mise en place de tests fonctionnels automatisés avec CARGO et Maven

HSQLDB est une base de données Java résidant en mémoire, créée et peuplée par de simples scripts SQL. Cette base embarquée est recréée lors de chaque cycle et met ainsi à disposition des tests des jeux de données identiques d’une exécution sur l’autre.

Il faut tout d’abord ajouter HSQLDB aux dépendances du projet Maven:

<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.8patch02-brew</version>
<scope>compile</scope>
</dependency>

Nous devons ensuite modifier la déclaration de la datasource. Parmi les très nombreuses options qui peuvent être mises en place suivant le client sql utilisé, nous avons retenu celle qui n’interfère pas avec la configuration du livrable final, par ajout d’un module de persistance consacré aux tests.
Voici la configuration d’origine de la datasource pointant sur une base de données ORACLE :


<!-- Creates a EntityManagerFactory for use with the Hibernate JPA provider and a simple in-memory data source populated with test data -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource" p:persistence-unit-name="appli-jpa">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:databasePlatform="org.hibernate.dialect.Oracle10gDialect"
p:database="ORACLE" p:showSql="true"/>
</property>
</bean>
<!-- Creates a EntityManagerFactory for use with the Hibernate JPA provider and a simple in-memory data source populated with test data -->
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/appli_ds" />

Et la configuration de la partie persistance dans le dossier META-INF du projet:


<persistence-unit name="appli-jpa">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>
</properties>
</persistence-unit>
<persistence-unit name="appli-jpa-test">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>
</properties>
</persistence-unit>

La partie « appli-jpa » est la configuration pour l’exploitation et la partie « appli-jpa-test » est celle utilisée pour les tests fonctionnels sous HSQLDB.
Pour utiliser la base de données HSQLDB, il faut modifier la configuration de la datasource, le but étant d’automatiser la modification sans aucun recours manuel. Nous modifions donc le pom.xml du livrable responsable de la partie persistance en lui ajoutant une tâche Ant avec le profil utilisé pour réaliser les tests fonctionnels.

<profile>
<id>selenium</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>token replace</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>REPLACE TOKEN</echo>
<replace
file="${basedir}/target/classes/data-access-config.xml">
<replacetoken><![CDATA[appli-jpa]]></replacetoken>
<replacevalue><![CDATA[appli-jpa-test]]></replacevalue>
</replace>
<replace
file="${basedir}/target/classes/data-access-config.xml">
<replacetoken><![CDATA[Oracle10gDialect]]></replacetoken>
<replacevalue><![CDATA[HSQLDialect]]></replacevalue>
</replace>
<replace
file="${basedir}/target/classes/data-access-config.xml">
<replacetoken><![CDATA[ORACLE]]></replacetoken>
<replacevalue><![CDATA[HSQL]]></replacevalue>
</replace>
</tasks>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ant</groupId>
<artifactId>ant-commons-net</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>1.4.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>

Ce profil modifie le fichier où est configuré la datasource pour utiliser HSQLDB lors des tests fonctionnels.
Dans le cadre de projets dont la configuration de la persistance est faite par annotation, HSQLDB génère le modèle à partir de ces annotations.

Pour l’initialisation de la base de données il suffit d’inclure dans le classpath du war un fichier nommé précisément « import.sql » dans lequel on consigne toutes les instructions d’insertions.
Il ne reste plus alors qu’à modifier notre container pour lui indiquer la configuration de la datasource pointée par jndi ; il faut pour cela ajouter des propriétés dans la configuration de cargo :


<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>1.0.3</version>
<configuration>
<wait>false</wait>
<container>
<containerId>tomcat6x</containerId>
<home>${env.CATALINA_HOME}</home>
<dependencies>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
</dependency>
</dependencies>
</container>
<configuration>
<home>${project.build.directory}/tomcat6x/container</home>
<properties>
<cargo.servlet.port>8095</cargo.servlet.port>
<cargo.logging>high</cargo.logging>
<cargo.datasource.datasource>
cargo.datasource.driver=org.hsqldb.jdbcDriver|
cargo.datasource.url=jdbc:hsqldb:mem:appliTest|
cargo.datasource.jndi=jdbc/appli_ds|
cargo.datasource.username=sa|
cargo.datasource.password=|
cargo.datasource.type=javax.sql.DataSource
</cargo.datasource.datasource>
</properties>
</configuration>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>

À ce stade l’exécution d’un “mvn clean install –P selenium” (considérant que l’id du profil Maven utilisé est « selenium ») permet de confirmer la bonne configuration du container.

Conclusion

En conjuguant la systématisation des tests unitaires et d’intégration avec un jeu de données constant, nous établissons un environnement de validation complet. Les bénéfices apportés sont considérables sur la durée de vie d’une application: nous avons pu raccourcir nos délais de livraison et diminuer drastiquement le nombre de régressions.