Failsafe plugin Maven

De EjnTricks

Pour les projets Maven, il est courant de mettre en place des tests unitaires. Ceux-ci sont exxécutés avant la création du paquet, fichier jar / war ...

La notion de tests d'intégrations concernent les tests exécutés après la création du paquet. Le plugin maven-failsafe-plugin va permettre d'exécuter ceux-ci. Cet article présente l'utilisation du plugin.

Les exemples décrits sont disponibles sous ce lien : http://www.svn.jouvinio.net/study/trunk/maven/maven-failsafe-plugin


Hand-icon.png Votre avis

Nobody voted on this yet

 You need to enable JavaScript to vote


Study icon.png Objectifs

Le plugin a été utilisé suite à l'étude des fichiers MANIFEST.MF pour récupérer la version du projet, et comment y accéder lors de l'exécution des tests.. Un test unitaire est mis en place valider la récupération de l'information depuis la propriété Implementation-Version.

Or dans le cadre des tests unitaires, les classes sont chargés depuis le répertoire de compilation. Or lors que la classe se trouve en dehors d'un paquet jar, cela ne sert à rien de mettre un fichier MANIFEST.MF, il ne sera pas pris en compte.

Il est donc nécessaire de pouvoir exécuter le test sur le paquet généré.


Add-file-icon.png Répertoires de source

Pour mémoire, les repertoires standards d'un proet Maven sont les suivants.

  • src/main/java
  • src/main/resources
  • src/test/java
  • src/test/resources

Il serait possible de placer les tests d'intégration dans src/test/java. Or, il est intéressant de le placer dans une arborescence spécifique tout ce qui a un lien avec les tests d'intégration.

  • src/it/java
  • src/it/resources

L'utilisation du plugin build helper va permettre de rajouter le nouveau répertoire de source.

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>build-helper-maven-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <id>add-test-source</id>
            <phase>generate-test-sources</phase>
            <goals>
              <goal>add-test-source</goal>
            </goals>
            <configuration>
              <sources>
                <source>src/it/java</source>
              </sources>
            </configuration>
          </execution>
        </executions>
      </plugin>

Le répertoire de reources est ajouté avec la confguration testResources classqique dans les fichiers pom.xml.

    <testResources>
      <testResource>
        <directory>src/test/resources</directory>
      </testResource>
      <testResource>
        <directory>src/it/resources</directory>
      </testResource>
    </testResources>

Jar format icon.png Génération Jar

L'objectif est de lire la version depuis le MANIFEST.MF. Celui-ci est généré à l'aide du plugin jar en demandant l'ajout des implémentation par défaut.

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <configuration>
          <archive>
            <manifest>
              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
            </manifest>
          </archive>
        </configuration>
      </plugin>


Java format icon.png Classe example

La classe VersionDisplay utilisée pour la constitution du paquet, et qui sera testée, contient une seule fonction de lecture de l'information.

package fr.ejn.tutorial.maven.version;

import org.apache.commons.lang3.StringUtils;

/**
 * Sample class for integration test.
 *
 * @author Etienne Jouvin
 *
 */
public final class VersionDisplay {

  /**
   * Read the implementation version from the manifest.
   *
   * @return Implementation version number, or <i>Unknown Version</i>.
   */
  public static String getVersionFromPackage() {
    Package pkg = VersionDisplay.class.getPackage();
    String version = null;
    if (pkg != null) {
      version = pkg.getImplementationVersion();
    }
    return StringUtils.defaultString(version, "Unknown Version");
  }

  /**
   * Private constructor.
   */
  private VersionDisplay() {
  }

}


Test-paper-icon.png Tests unitaires

Icon-Configuration-Settings.png Configuration pom

Dans cet exemple, aucune configuration spécifique n'est mise en place dans le fichier pom.xml. Les exécutions standards de Maven sont prises en compte.

Java format icon.png Implémentation

Le test unitaire est mis en place dans la classe fr.ejn.tutorial.maven.version.VersionDisplayTest, stocké dans le répertoire de source src/test/java, avec la fonction testGetVersionFromPackage.

  @Test
  public void testGetVersionFromPackage() throws Exception {
    String expected = "Unknown Version";
    String actual = VersionDisplay.getVersionFromPackage();

    assertThat(actual).isEqualTo(expected);
  }

Dans ce cas, le fichier MANIFEST.MF n'est pas disponible dans le context d'exécution du test. La valeur attendue est donc Unknown Version.


Test-paper-icon.png Tests d' intégration

Icon-Configuration-Settings.png Configuration pom

Les tests d'intégration sont simplement déclenchés par le plugin maven-failsafe-plugin qu'il faut déclarer dans le fichier pom.xml ainsi.

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>2.20.1</version>
        <executions>
          <execution>
            <id>integration-test</id>
            <goals>
              <goal>integration-test</goal>
              <goal>verify</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

Java format icon.png Implémentation

Le test d'intégration est mis en place dans la classe fr.ejn.test.tutorial.maven.version.VersionDisplayIT, stocké dans le répertoire de source src/it/java, avec la fonction testGetVersionFromPackage.

  @Test
  public void testGetVersionFromPackage() throws Exception {
    String expected = "0.0.1-SNAPSHOT";
    String actual = VersionDisplay.getVersionFromPackage();

    assertThat(actual).isEqualTo(expected);
  }

A noter l'emplacement de la classe de test dans le nouveau répertoire de sources, ainsi que le package qui est différent de celui de la classe testée. que la valeur attendue correspond à la version définie dans el fichier pom.xml du projet et qui est injecté dans le MANIFEST.MF.

Dans ce cas, le fichier MANIFEST.MF est généré dans le package et donc disponible dans le context d'exécution du test. La valeur attendue est donc celle définie dans le fichier pom.xml.

Start-icon.png Exécution

Afin de déclencher les tests d'intégration, il suffit d'exécution le goal test-integration qui se délcenche après la génération du paquet.

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Study Failsafe plugin 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-failsafe-plugin ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ maven-failsafe-plugin ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- build-helper-maven-plugin:3.0.0:add-test-source (add-test-source) @ maven-failsafe-plugin ---
[INFO] Test Source directory: C:\workspaces\studyMaven\maven-failsafe-plugin\src\it\java added.
[INFO] 
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ maven-failsafe-plugin ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO] Copying 0 resource
[INFO] 
[INFO] --- maven-compiler-plugin:3.7.0:testCompile (default-testCompile) @ maven-failsafe-plugin ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ maven-failsafe-plugin ---
[INFO] Surefire report directory: C:\workspaces\studyMaven\maven-failsafe-plugin\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running fr.ejn.tutorial.maven.version.VersionDisplayTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.167 sec

Results :

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

[INFO] 
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ maven-failsafe-plugin ---
[INFO] Building jar: C:\workspaces\studyMaven\maven-failsafe-plugin\target\maven-failsafe-plugin-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- maven-failsafe-plugin:2.20.1:integration-test (integration-test) @ maven-failsafe-plugin ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running fr.ejn.test.tutorial.maven.version.VersionDisplayIT
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.153 s - in fr.ejn.test.tutorial.maven.version.VersionDisplayIT
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.480 s
[INFO] Finished at: 2017-11-18T22:17:36+01:00
[INFO] Final Memory: 14M/170M
[INFO] ------------------------------------------------------------------------


Examples-icon.png Points remarquables

Run-icon.png Exécution

Par défaut, les plugin maven-failsafe-plugin, ainsi que maven-surefire-plugin, créé un fichier jar avec un fichier MANIFEST.MF référençant tous les éléments pour le classpath.

En utilisation l'argument de debug -X, des informations permettent d'identifier ce fichier jar comme dans l'exemple suivant.

[DEBUG] Determined Maven Process ID 18992
[DEBUG] boot classpath:  C:\Apps\maven\repository\org\apache\maven\surefire\surefire-booter\2.20.1\surefire-booter-2.20.1.jar  
C:\Apps\maven\repository\org\apache\maven\surefire\surefire-api\2.20.1\surefire-api-2.20.1.jar  
C:\Apps\maven\repository\org\apache\maven\surefire\surefire-logger-api\2.20.1\surefire-logger-api-2.20.1.jar  
C:\workspaces\studyMaven\maven-failsafe-plugin\target\test-classes  
C:\workspaces\studyMaven\maven-failsafe-plugin\target\maven-failsafe-plugin-0.0.1-SNAPSHOT.jar  
C:\Apps\maven\repository\org\apache\commons\commons-lang3\3.5\commons-lang3-3.5.jar  
C:\Apps\maven\repository\junit\junit\4.12\junit-4.12.jar  C:\Apps\maven\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar  
C:\Apps\maven\repository\org\assertj\assertj-core\2.7.0\assertj-core-2.7.0.jar  
C:\Apps\maven\repository\org\apache\maven\surefire\surefire-junit4\2.20.1\surefire-junit4-2.20.1.jar
[DEBUG] boot(compact) classpath:  surefire-booter-2.20.1.jar  surefire-api-2.20.1.jar  surefire-logger-api-2.20.1.jar  test-classes  
maven-failsafe-plugin-0.0.1-SNAPSHOT.jar  commons-lang3-3.5.jar  junit-4.12.jar  hamcrest-core-1.3.jar  assertj-core-2.7.0.jar  surefire-junit4-2.20.1.jar
[DEBUG] Forking command line: cmd.exe /X /C "C:\Apps\Java\jdk1.8.0_144\jre\bin\java -jar C:\Users\etienne\AppData\Local\Temp\surefire7372957568823426124\surefirebooter4424685134111681834.jar 
C:\Users\etienne\AppData\Local\Temp\surefire7372957568823426124 2017-11-18T22-19-46_050-jvmRun1 surefire7885618917913514612tmp surefire_07852901924048378666tmp"
[INFO] Running fr.ejn.test.tutorial.maven.version.VersionDisplayIT
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.457 s - in fr.ejn.test.tutorial.maven.version.VersionDisplayIT

La remière information instructive concerne le classpath, où l'on note que le répertoire test-classes et le paquet maven-failsafe-plugin-0.0.1-SNAPSHOT.jar sont pris en compte.

La second information concerne le fichier jar généré dont on peut connaître l'emplacement. Celui-ci contient uniquement un fichier <ocde>MANIFEST.MF</code> dont le contenu est le suivant.

Manifest-Version: 1.0
Class-Path: file:/C:/Apps/maven/repository/org/apache/maven/surefire/s
 urefire-booter/2.20.1/surefire-booter-2.20.1.jar file:/C:/Apps/maven/
 repository/org/apache/maven/surefire/surefire-api/2.20.1/surefire-api
 -2.20.1.jar file:/C:/Apps/maven/repository/org/apache/maven/surefire/
 surefire-logger-api/2.20.1/surefire-logger-api-2.20.1.jar file:/C:/wo
 rkspaces/studyMaven/maven-failsafe-plugin/target/test-classes/ file:/
 C:/workspaces/studyMaven/maven-failsafe-plugin/target/maven-failsafe-
 plugin-0.0.1-SNAPSHOT.jar file:/C:/Apps/maven/repository/org/apache/c
 ommons/commons-lang3/3.5/commons-lang3-3.5.jar file:/C:/Apps/maven/re
 pository/junit/junit/4.12/junit-4.12.jar file:/C:/Apps/maven/reposito
 ry/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar file:/C:/Apps
 /maven/repository/org/assertj/assertj-core/2.7.0/assertj-core-2.7.0.j
 ar file:/C:/Apps/maven/repository/org/apache/maven/surefire/surefire-
 junit4/2.20.1/surefire-junit4-2.20.1.jar
Main-Class: org.apache.maven.surefire.booter.ForkedBooter

Icon-log.png Package test

Le package du test d'intégration est fr.ejn.test.tutorial.maven.version différent de celui de la classe testée, soit fr.ejn.tutorial.maven.version. En fait, il est important que le package de la classe testée ne soit pas préalablement chargé. Sinon lors de l'accès au fichier MANIFEST.MF, le package serait référencé comme étant dans le répertoire de compilation des tests, soit target/test-classes et non pas le fichier jar.

Icon Personnalisation.png Nomenclature

La nomenclature par défaut des tests d'intégration est similaire à celle des tests unitaires. A savoir que le nom des classes doit respecté un des patterns suivants.

  • IT*.java
  • *IT.java
  • *ITCase.java

Ceci est explicité dans la documentation des inclusions et exclusions.


Viewer icon.png Voir aussi

Documentation officielle: https://maven.apache.org/surefire/maven-failsafe-plugin/