Chapitre en accès libre

Installer Maven et vérifier la chaîne complète

18 min de travail — lecture et pratique

Ce que vous allez obtenir

À la fin de ce chapitre, trois choses seront vraies sur votre poste :

  1. La commande mvn -v répond, et elle affiche votre JDK 11.
  2. Un projet Maven existe sur votre disque, avec un pom.xml que vous comprenez ligne par ligne.
  3. La commande mvn test se termine par BUILD SUCCESS.

C’est la chaîne d’outils que vous utiliserez pendant tout le parcours. Chaque projet Selenium des modules suivants repartira exactement de ce squelette. Si cette étape est propre, vous n’y reviendrez plus. Si elle est bancale, elle vous coûtera du temps à chaque module.

Prérequis. Un JDK 11 installé et java -version qui répond (chapitre précédent). Si ce n’est pas le cas, arrêtez-vous ici : Maven ne sert à rien sans JDK. Et plusieurs des pannes listées plus bas dans ce chapitre sont en réalité des pannes de JDK, pas de Maven.

Durée. Comptez une vingtaine de minutes, dont plusieurs minutes d’attente pendant le premier build. Ce n’est pas du temps perdu : la section sur le dépôt local explique ce qui se passe pendant cette attente.


Pourquoi Maven, avant de l’installer

Vous savez déjà compiler un fichier Java avec javac et l’exécuter avec java. Tant que vous avez un fichier, ça marche. Le problème arrive dès que le projet grossit.

Un test Selenium a besoin de la bibliothèque Selenium. Selenium a besoin d’autres bibliothèques. Chacune a une version. Sans outil, vous téléchargez les fichiers .jar un par un, vous les rangez quelque part, et vous écrivez une longue ligne de commande pour les passer en -classpath. Puis un collègue récupère votre projet et ne peut pas le lancer, parce que ses .jar ne sont pas au même endroit.

Maven prend en charge trois choses, et ce sont celles qui nous intéressent ici :

Ce que Maven fait Concrètement
Gestion des dépendances Vous écrivez quelques lignes de XML nommant une bibliothèque et sa version. Maven la télécharge, et télécharge aussi tout ce dont elle dépend.
Structure de projet standard Le code va dans src/main/java, les tests dans src/test/java. Toujours, sur n’importe quel projet Maven.
Cycle de vie de build mvn test veut dire : résoudre les dépendances, compiler le code, compiler les tests, exécuter les tests. Toujours dans cet ordre, toujours la même commande.

C’est aussi ce qui permet à une machine d’intégration continue de lancer vos tests sans que vous soyez devant : ce dont le build a besoin est décrit dans le pom.xml, pas dans la configuration de votre poste. Cela ne garantit pas qu’un build qui passe chez vous passera ailleurs — la version du JDK, le système d’exploitation ou l’accès réseau peuvent différer — mais cela supprime une cause d’écart majeure : les bibliothèques rangées à la main. C’est pour ça qu’on travaille avec mvn test dès maintenant, et pas seulement avec le bouton « Run » de VS Code.


Installer Maven

Maven se distribue sous forme d’archive à décompresser. Il n’y a pas d’installateur, pas d’assistant, rien à cocher. Vous décompressez un dossier et vous indiquez à votre système où le trouver. C’est déroutant la première fois, et c’est tout.

Rendez-vous sur la page de téléchargement officielle : https://maven.apache.org/download.cgi et prenez le Binary zip archive (Windows) ou le Binary tar.gz archive (macOS, Linux) de la dernière version 3.9.x. Les exemples ci-dessous utilisent 3.9.9 : remplacez par le numéro que vous avez effectivement téléchargé.

Ne prenez pas le « Source » : c’est le code source de Maven lui-même, il faudrait le compiler. Vous voulez le « Binary ».

Windows

Décompressez l’archive dans un dossier sans espace ni accent dans le chemin. Les espaces dans les chemins sont une source classique d’échecs silencieux avec les scripts .cmd. Utilisez par exemple :

C:\outils\apache-maven-3.9.9

Vous devez obtenir un dossier C:\outils\apache-maven-3.9.9\bin contenant un fichier mvn.cmd. Si votre chemin ressemble à C:\outils\apache-maven-3.9.9\apache-maven-3.9.9\bin, vous avez un dossier de trop : remontez d’un niveau.

Ensuite, ajoutez ce bin au PATH :

  1. Touche Windows, tapez variables d environnement, ouvrez Modifier les variables d’environnement système.
  2. Bouton Variables d’environnement….
  3. Dans Variables utilisateur, sélectionnez Path, puis Modifier….
  4. Nouveau, et collez : C:\outils\apache-maven-3.9.9\bin
  5. OK, OK, OK.

Point critique, et c’est la première chose à vérifier quand ça ne marche pas : une fenêtre de terminal déjà ouverte ne voit pas les nouvelles variables d’environnement. Fermez complètement votre terminal (et VS Code) et rouvrez-en un neuf. Sinon vous testerez pendant dix minutes une configuration qui est déjà correcte.

Si vous préférez un gestionnaire de paquets et que vous avez les droits nécessaires :

winget install Apache.Maven

Le paquet ajoute normalement Maven au PATH. Ouvrez un terminal neuf, lancez mvn -v, et si la commande n’est pas reconnue, repérez le dossier d’installation et ajoutez son bin au PATH à la main, comme ci-dessus.

macOS

Avec Homebrew, si vous l’avez déjà :

brew install maven

Homebrew place mvn dans le PATH tout seul. Vous pouvez passer directement à la vérification.

Sans Homebrew, en manuel. Attention : sous macOS, le dossier de téléchargement s’appelle Downloads sur le disque, même si le Finder l’affiche en français.

cd ~/Downloads
tar xzvf apache-maven-3.9.9-bin.tar.gz
sudo mv apache-maven-3.9.9 /usr/local/apache-maven
echo 'export PATH=/usr/local/apache-maven/bin:$PATH' >> ~/.zshrc
source ~/.zshrc

Attention aux guillemets dans la ligne echo : ce sont des apostrophes simples droites. Avec des guillemets doubles, $PATH serait remplacé par sa valeur au moment de l’écriture, et votre .zshrc figerait un PATH obsolète.

Si votre shell est bash et non zsh (macOS antérieur à Catalina, ou configuration personnelle), remplacez ~/.zshrc par ~/.bash_profile. Pour savoir lequel vous utilisez :

echo $SHELL

Linux

Selon votre bureau et votre langue, le dossier de téléchargement s’appelle Downloads ou Téléchargements. Vérifiez avec ls ~ avant de lancer la première ligne.

cd ~/Downloads
tar xzvf apache-maven-3.9.9-bin.tar.gz
sudo mv apache-maven-3.9.9 /opt/apache-maven
echo 'export PATH=/opt/apache-maven/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

Pourquoi pas sudo apt install maven ? Deux raisons. D’abord, la version packagée par votre distribution est généralement plus ancienne que celle publiée par Apache. Ensuite, le paquet maven tire un JDK ou un JRE en dépendance ; selon ce qui est déjà installé, cela peut changer le java par défaut du système et vous faire quitter le JDK 11 sans que vous l’ayez demandé. C’est une panne pénible à diagnostiquer. L’archive manuelle ne touche à rien d’autre.

Le cas M2_HOME

Beaucoup de tutoriels vous demandent de définir une variable M2_HOME. Ce n’est plus nécessaire. Les scripts de lancement de Maven 3.9 ne lisent plus du tout M2_HOME : ils déterminent leur propre répertoire d’installation et renseignent MAVEN_HOME eux-mêmes. C’était une obligation de Maven 2, et l’habitude a survécu.

Une variable M2_HOME qui traîne n’empêchera donc pas mvn de démarrer. En revanche, des outils tiers plus anciens la lisent encore — scripts d’intégration, anciennes configurations d’IDE — et si elle pointe vers une installation que vous avez supprimée, ces outils-là échoueront avec un message parlant d’un répertoire introuvable. Pour voir ce que vous avez :

# macOS / Linux
echo $M2_HOME
echo $MAVEN_HOME
REM Windows (invite de commandes)
echo %M2_HOME%
echo %MAVEN_HOME%

Si ça n’affiche rien (ou %M2_HOME% tel quel sous Windows), il n’y a rien à faire. Si ça affiche un chemin vers un dossier qui n’existe plus, supprimez la variable.

Ce qui compte, c’est le PATH. Pas M2_HOME.


Critère de réussite n° 1 : mvn -v

Ouvrez un terminal neuf et lancez :

mvn -v

Vous devez voir cinq lignes de cette forme :

Apache Maven 3.9.9 (<un long identifiant de commit>)
Maven home: C:\outils\apache-maven-3.9.9
Java version: 11.0.22, vendor: Eclipse Adoptium, runtime: C:\Program Files\Eclipse Adoptium\jdk-11.0.22.7-hotspot
Default locale: fr_FR, platform encoding: UTF-8
OS name: "windows", version: "10.0", arch: "amd64", family: "windows"

Les chemins, les numéros et l’encodage affiché seront différents chez vous : platform encoding vaut souvent Cp1252 sous Windows et UTF-8 sous macOS et Linux, et ce n’est pas un problème à ce stade. Deux éléments seulement sont à vérifier, et ils sont non négociables :

  • La première ligne commence par Apache Maven 3.
  • La troisième ligne dit Java version: 11.

Cette troisième ligne est la vraie information de ce chapitre. Maven vous dit avec quel JDK il va compiler, qui n’est pas forcément celui que vous croyez avoir installé.

Quand ça rate

mvn : commande introuvable / 'mvn' n'est pas reconnu en tant que commande interne ou externe

Le PATH n’est pas pris en compte. Dans l’ordre :

  1. Avez-vous ouvert un terminal neuf depuis la modification du PATH ? Commencez par là : fermez tout, y compris VS Code, et rouvrez.
  2. Le chemin que vous avez ajouté existe-t-il vraiment, avec un mvn.cmd (ou mvn) dedans ?

winget install Apache.Maven
0

# macOS / Linux
ls /opt/apache-maven/bin
  1. Vérifiez ce que votre système voit :
REM Windows
where mvn
# macOS / Linux
which mvn

The JAVA_HOME environment variable is not defined correctly

Maven a démarré, mais il ne trouve pas de JDK. Vérifiez la valeur :

# macOS / Linux
echo $JAVA_HOME
REM Windows
echo %JAVA_HOME%

Le chemin affiché doit être la racine du JDK, pas son dossier bin. Il doit contenir un sous-dossier bin et un sous-dossier lib. Une erreur classique est de pointer ...\jdk-11\bin au lieu de ...\jdk-11.

mvn -v répond, mais affiche Java version: 17. (ou 8, ou 21)

C’est le piège le plus coûteux de ce chapitre, parce que tout semble fonctionner. Votre machine a plusieurs JDK et Maven prend le mauvais. Il faut forcer JAVA_HOME sur le JDK 11.

# macOS
export JAVA_HOME=$(/usr/libexec/java_home -v 11)
# Linux : lister les JDK installés, puis choisir
ls /usr/lib/jvm
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64

Le nom exact du dossier varie selon la distribution et le fournisseur du JDK : reprenez celui que ls affiche chez vous.

Sous Windows, reprenez Variables d’environnement et corrigez JAVA_HOME pour qu’il pointe sur le dossier de votre JDK 11.

Ces export ne valent que pour le terminal courant : ajoutez la ligne à votre ~/.zshrc ou ~/.bashrc pour la rendre permanente, puis source le fichier.

Relancez mvn -v jusqu’à voir Java version: 11.. Ne passez pas à la suite avant.


Le dépôt local .m2, et pourquoi le premier build est long

Avant de créer le projet, comprenez ce qui va se passer, sinon la prochaine étape ressemblera à un plantage.

Quand Maven a besoin d’une bibliothèque, il regarde d’abord dans un dossier sur votre disque appelé le dépôt local. S’il ne l’y trouve pas, il la télécharge depuis le dépôt central (repo.maven.apache.org) et l’enregistre dans le dépôt local. La fois suivante, il ne téléchargera plus rien.

Le dépôt local se trouve ici :

Système Emplacement
Windows C:\Users\<votre-nom>\.m2\repository
macOS /Users/<votre-nom>/.m2/repository
Linux /home/<votre-nom>/.m2/repository

Le dossier .m2 commence par un point. Sous macOS et Linux, cette convention le rend masqué : Cmd + Maj + . affiche les fichiers cachés dans le Finder, et ls -a les liste dans un terminal. Sous Windows, il est visible dans l’explorateur ; le plus rapide reste de taper %USERPROFILE%\.m2 dans la barre d’adresse.

Conséquences pratiques, et elles vont vous servir tout le parcours :

  • Le premier build est long — plusieurs minutes, avec de nombreuses lignes Downloading from central:. Maven ne télécharge pas seulement JUnit : il télécharge aussi ses propres greffons de compilation, d’exécution de tests, de nettoyage. Ce n’est pas un blocage, c’est le fonctionnement normal. Laissez tourner.
  • Les builds suivants sont rapides — quelques secondes, sans aucun téléchargement.
  • Si vous voyez encore des téléchargements au troisième build, quelque chose ne va pas : soit le réseau coupe en cours de route et laisse des fichiers incomplets, soit vous avez une dépendance en version SNAPSHOT que Maven revérifie à chaque fois.
  • Un dépôt local corrompu (réseau coupé pendant un téléchargement) produit des erreurs incompréhensibles du type Could not resolve dependencies alors que le réseau fonctionne. Le remède : supprimer le sous-dossier fautif de .m2/repository et relancer. En dernier recours, supprimer .m2/repository en entier — vous ne perdez rien d’autre que du temps de retéléchargement.

Le proxy d’entreprise

Cette section ne concerne que les postes derrière un réseau d’entreprise. Si vous travaillez depuis chez vous, sautez-la — mais lisez le premier paragraphe : le jour où vous serez en mission, vous saurez où chercher.

Reconnaître le symptôme

Derrière un proxy non configuré, Maven ne dit pas « proxy ». Il ne dit rien pendant très longtemps, puis il affiche une erreur de connexion. Elle a cette forme (le libellé final peut être traduit dans la langue de votre système) :

[ERROR] Failed to execute goal on project qa-socle: Could not resolve dependencies...
Could not transfer artifact org.junit.jupiter:junit-jupiter:pom:5.10.2
from/to central (https://repo.maven.apache.org/maven2):
Connect to 10.255.255.1:8080 [/10.255.255.1] failed: Connection timed out

Trois signatures à reconnaître, toutes les trois de nature réseau :

Ce que vous lisez Ce que ça veut dire
Connection timed out après une longue attente Le trafic sortant est filtré. Il faut un proxy.
Connection refused immédiatement Rien n’écoute à l’adresse indiquée : l’hôte ou le port du proxy est faux.
PKIX path building failed: unable to find valid certification path Le proxy déchiffre le HTTPS et présente son propre certificat, que votre JDK ne connaît pas.

Configurer le proxy : settings.xml

Maven lit sa configuration personnelle dans un fichier settings.xml placé dans le dossier .m2, à côté de repository. Ce fichier n’existe pas par défaut : vous le créez.

  • Windows : C:\Users\<votre-nom>\.m2\settings.xml
  • macOS / Linux : ~/.m2/settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

  <proxies>
    <proxy>
      <id>proxy-entreprise</id>
      <active>true</active>
      <protocol>http</protocol>
      <host>proxy.mon-entreprise.local</host>
      <port>8080</port>
      <username>mon-identifiant</username>
      <password>mon-mot-de-passe</password>
      <nonProxyHosts>localhost|127.0.0.1|*.mon-entreprise.local</nonProxyHosts>
    </proxy>
  </proxies>

</settings>

Quatre pièges à connaître :

  1. <protocol>http</protocol> même pour du HTTPS. Ce champ décrit le protocole pour joindre le proxy, pas celui de la ressource demandée. Un proxy d’entreprise classique s’atteint en HTTP. Mettre https ici est une erreur fréquente.
  2. Le mot de passe est en clair dans le fichier. C’est un vrai problème. Si votre mot de passe de proxy est votre mot de passe de session Windows, ne l’écrivez pas ici : demandez à votre IT s’il existe un compte de service ou un proxy sans authentification pour les outils de développement. Maven sait aussi chiffrer ce mot de passe (mvn --encrypt-password, qui suppose d’avoir créé au préalable un mot de passe maître avec mvn --encrypt-master-password) ; cela protège d’une lecture accidentelle, pas d’un vol de fichier.
  3. <nonProxyHosts> est séparé par des barres verticales |, pas par des virgules.
  4. Un caractère spécial dans le mot de passe (&, <, >) casse le XML. & s’écrit &amp;, < s’écrit &lt;, > s’écrit &gt;.

Si vous ne connaissez ni l’hôte ni le port de votre proxy, vous pouvez souvent les lire dans les paramètres réseau de votre navigateur d’entreprise, ou dans le fichier de configuration automatique que votre poste utilise.

Le certificat interne (erreur PKIX)

Si vous obtenez PKIX path building failed, le proxy réécrit le trafic HTTPS. Il faut ajouter son certificat racine au magasin de confiance de votre JDK 11. Il vous faut deux choses que vous n’avez pas forcément : le fichier de certificat, distribué par votre service informatique, et les droits d’écriture dans le répertoire du JDK.

Une fois le fichier en main, la commande est celle-ci — terminal administrateur sous Windows, sudo sous macOS et Linux :

brew install maven
0

-cacerts désigne le magasin de confiance du JDK courant (option disponible à partir du JDK 9). changeit est le mot de passe par défaut de ce magasin ; s’il a été modifié sur votre poste, votre IT vous donnera le bon. Vérifiez ensuite que l’alias est bien présent :

keytool -list -cacerts -storepass changeit -alias proxy-entreprise

Dites-le clairement à votre IT : « J’ai besoin que repo.maven.apache.org soit joignable depuis mon poste, et du certificat racine du proxy pour l’ajouter au truststore de mon JDK. »

Si vous n’avez pas les droits

Soyez lucide : sans autorisation réseau, ce chapitre est bloqué, et aucun texte ne le débloquera. Ce n’est ni votre faute ni un défaut de la formation. Trois issues :

  1. Ouvrir un ticket auprès de votre IT en demandant précisément l’accès à repo.maven.apache.org (et les coordonnées du proxy). Formulez la demande dans ces termes-là : c’est un besoin standard pour un poste de développement Java.
  2. Demander si l’entreprise dispose déjà d’un miroir interne (Nexus, Artifactory). Si oui, votre IT vous donnera une URL à mettre dans un bloc <mirror> de settings.xml, et tout fonctionnera sans toucher au proxy.
  3. Faire ce parcours sur un poste personnel, si vous en avez un. Vous évitez d’emblée toute la catégorie de pannes décrite dans cette section.

Créer le projet

Pourquoi pas l’archétype

Maven sait générer un projet tout fait avec une commande. Nous n’allons pas l’utiliser comme point de départ, et voici pourquoi — ce n’est pas une question de goût.

L’archétype maven-archetype-quickstart en version 1.4 produit un pom.xml qui contient ceci :

<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>

et cette dépendance :

<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>

C’est-à-dire : Java 7 et JUnit 4. Nous travaillons en Java 11 et JUnit 5. Il faudrait donc générer le projet, puis corriger plusieurs endroits du fichier — en sachant lesquels. Écrire le fichier soi-même est plus court, et surtout vous saurez ce que fait chaque ligne, ce qui vous servira à chaque fois qu’un build échouera.

L’archétype ajoute aussi une dépendance au réseau supplémentaire : il faut le télécharger avant de pouvoir générer quoi que ce soit. Derrière un proxy, c’est un point de panne de plus, et un point de panne qui survient avant même que vous ayez un projet à déboguer.

Pour information, la commande existe et vous la croiserez : mvn archetype:generate -DgroupId=fr.stratest.qa -DartifactId=demo -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false. Sans -DinteractiveMode=false, elle vous pose une série de questions dans le terminal et vous propose une très longue liste d’archétypes. Ne la lancez pas maintenant.

L’arborescence

Créez la structure suivante. Le nom qa-socle est celui que nous reprendrons dans les chapitres suivants.

qa-socle
├── pom.xml
└── src
    ├── main
    │   └── java
    │       └── fr
    │           └── stratest
    │               └── qa
    │                   └── Environnement.java
    └── test
        └── java
            └── fr
                └── stratest
                    └── qa
                        └── ChaineOutilsTest.java

Deux règles à respecter dans cette arborescence :

  • Le nom du fichier doit être exactement celui de la classe publique qu’il contient, extension .java comprise. Environnement.java pour class Environnement. C’est une erreur de compilation franche si vous vous trompez, et elle est facile à lire : class Environnement is public, should be declared in a file named Environnement.java.
  • L’imbrication fr/stratest/qa doit correspondre à la ligne package fr.stratest.qa; en tête des fichiers. Attention ici : si le dossier ne correspond pas, Maven compile quand même sans rien dire et range la classe d’après la déclaration package. Vous ne verrez donc pas d’erreur tout de suite — seulement VS Code qui souligne le fichier, et un projet que personne ne retrouve. Respectez la convention dès le départ.

En une commande :

# macOS / Linux
mkdir -p ~/projets/qa-socle/src/main/java/fr/stratest/qa
mkdir -p ~/projets/qa-socle/src/test/java/fr/stratest/qa
cd ~/projets/qa-socle
REM Windows (invite de commandes)
mkdir %USERPROFILE%\projets\qa-socle\src\main\java\fr\stratest\qa
mkdir %USERPROFILE%\projets\qa-socle\src\test\java\fr\stratest\qa
cd /d %USERPROFILE%\projets\qa-socle

Ouvrez ensuite ce dossier dans VS Code : Fichier > Ouvrir le dossier…, et sélectionnez qa-socle. Important : ouvrez le dossier qa-socle lui-même, pas son parent, sinon l’extension Java de VS Code ne reconnaîtra pas le projet.

Le pom.xml

À la racine de qa-socle, créez pom.xml avec exactement ce contenu :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>fr.stratest.qa</groupId>
  <artifactId>qa-socle</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.10.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.13.0</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.2.5</version>
      </plugin>
    </plugins>
  </build>

</project>

Ligne par ligne, ce qui compte :

Élément Rôle
modelVersion Toujours 4.0.0. C’est la version du format du fichier, pas de votre projet.
groupId Votre « espace de noms », par convention un nom de domaine à l’envers.
artifactId Le nom du projet. Il donne son nom au fichier .jar produit.
version SNAPSHOT signifie « en cours de développement, non figée ».
project.build.sourceEncoding Sans cette ligne, Maven utilise l’encodage de la machine et vous obtenez un avertissement ; surtout, vos accents deviennent illisibles sur une autre machine.
maven.compiler.source / target Compiler en Java 11. C’est ce qui relie ce fichier à l’exigence du parcours.
junit-jupiter JUnit 5. L’artefact junit-jupiter est un agrégat : il tire l’API, le moteur d’exécution et les tests paramétrés en une seule déclaration.
<scope>test</scope> Cette bibliothèque n’est disponible que dans src/test/java, et n’est pas embarquée dans le livrable.
maven-compiler-plugin Fixé en 3.13.0.
maven-surefire-plugin C’est lui qui exécute les tests. Fixé en 3.2.5, compatible avec JUnit 5.10.

Pourquoi fixer explicitement la version des deux greffons ? Parce que sans cette indication, la version employée est celle que votre version de Maven associe par défaut à la phase. Elle n’est pas la même partout : Maven 3.6.3 utilise maven-compiler-plugin 3.1 et maven-surefire-plugin 2.12.4, tandis que Maven 3.9.9 utilise 3.13.0 et 3.2.5. Le même pom.xml ne se comporterait donc pas de la même façon chez vous et sur le serveur — et avec Surefire 2.12.4, vos tests JUnit 5 ne seraient tout simplement pas exécutés. Fixer les versions rend le build reproductible.

Ce pom.xml est votre point de départ pour tout le parcours. Dans les chapitres Selenium, vous y ajouterez une dépendance, et une seule.

Les deux fichiers Java

src/main/java/fr/stratest/qa/Environnement.java :

package fr.stratest.qa;

public class Environnement {

    public static String versionJava() {
        return System.getProperty("java.specification.version");
    }

    public static void main(String[] args) {
        System.out.println("JDK detecte : " + versionJava());
    }
}

src/test/java/fr/stratest/qa/ChaineOutilsTest.java :

package fr.stratest.qa;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class ChaineOutilsTest {

    @Test
    void mavenCompileEtExecuteUnTest() {
        assertEquals(4, 2 + 2);
    }

    @Test
    void leBuildTourneSurUnJdk11OuSuperieur() {
        String version = Environnement.versionJava();
        System.out.println(">>> JDK utilise par le build : " + version);
        int majeur = Integer.parseInt(version.split("\\.")[0]);
        assertTrue(majeur >= 11, "JDK trop ancien : " + version);
    }
}

Un mot sur la ligne version.split("\\.")[0]. Depuis Java 9, la propriété java.specification.version vaut 11, 17, 21 — un simple nombre. Mais sur un JDK 8 elle vaut 1.8, et un Integer.parseInt("1.8") lèverait une NumberFormatException : le test partirait en erreur au lieu d’afficher le message que nous avons écrit. En découpant sur le point, 1.8 devient 1, la comparaison 1 >= 11 est fausse, et vous lisez JDK trop ancien : 1.8. Un test doit échouer proprement, surtout celui qui sert à diagnostiquer votre installation.

Ces deux tests ne testent rien d’intéressant, et c’est volontaire. Le premier prouve que la chaîne compile et exécute du code de test. Le second prouve que la classe de src/main/java est bien visible depuis src/test/java, et affiche le JDK réellement utilisé par le build.

Notez qu’il n’y a aucun accent dans les chaînes de caractères. C’est délibéré pour ce chapitre : tant que l’encodage du terminal n’est pas vérifié, un accent mal affiché vous ferait croire à une panne qui n’existe pas.


Critère de réussite n° 2 : mvn test

Depuis le dossier qa-socle — celui qui contient pom.xml — lancez :

cd ~/Downloads
tar xzvf apache-maven-3.9.9-bin.tar.gz
sudo mv apache-maven-3.9.9 /usr/local/apache-maven
echo 'export PATH=/usr/local/apache-maven/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
0

Le premier lancement prend plusieurs minutes et affiche de nombreuses lignes Downloading from central:. C’est le remplissage du dépôt local décrit plus haut. Ne l’interrompez pas : une interruption laisse des fichiers incomplets qu’il faudra nettoyer.

À la fin, vous devez voir ceci — les durées varieront, le reste non :

[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running fr.stratest.qa.ChaineOutilsTest
>>> JDK utilise par le build : 11
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.042 s -- in fr.stratest.qa.ChaineOutilsTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Les quatre points à vérifier :

  1. >>> JDK utilise par le build : 11
  2. Tests run: 2 — et pas Tests run: 0
  3. Failures: 0, Errors: 0
  4. BUILD SUCCESS

Si ces quatre lignes sont là, votre chaîne d’outils est en place. C’est l’objectif du chapitre, et il est atteint.

Quand ça rate

Message Cause Ce que vous faites
The goal you specified requires a project to execute but there is no POM in this directory Vous n’êtes pas dans le bon dossier. ls (ou dir) et vérifiez que pom.xml est là. Sinon, cd vers qa-socle.
Non-parseable POM ... expected START_TAG XML mal formé : une balise non fermée, ou des guillemets typographiques collés depuis un traitement de texte. Recopiez le pom.xml depuis ce chapitre. Les guillemets doivent être des " droits.
Tests run: 0 et BUILD SUCCESS Surefire n’a pas trouvé vos tests. Trois causes : le fichier ne finit pas par Test.java ; il n’est pas sous src/test/java ; la version de maven-surefire-plugin est antérieure à 2.22, la première à savoir exécuter JUnit 5 — ce qui arrive si vous avez omis le bloc <plugin> et que votre Maven associe par défaut la 2.12.4.
package org.junit.jupiter.api does not exist La dépendance n’est pas résolue, ou l’import est mauvais. Vérifiez le bloc <dependencies>, puis relancez avec mvn -U test pour forcer la revérification.
Could not transfer artifact ... Connection timed out Réseau ou proxy. Reprenez la section sur le proxy d’entreprise.
Fatal error compiling: invalid target release: 11 Maven compile avec un JDK antérieur à 11. mvn -v et corrigez JAVA_HOME.
warning: unmappable character for encoding Encodage. Vérifiez la présence de project.build.sourceEncoding et enregistrez vos fichiers en UTF-8 dans VS Code (indicateur en bas à droite de la fenêtre).
WARNING: system modules path not set in conjunction with -source 11 Vous compilez avec un JDK plus récent que 11. Avertissement sans conséquence ici, mais c’est le signe que vous n’êtes pas sur le JDK 11 demandé. Corrigez JAVA_HOME.

Deux commandes de diagnostic à connaître :

mvn -X test

Mode débogage : très verbeux, mais il affiche le settings.xml lu, le dépôt local utilisé et chaque URL contactée. C’est l’outil pour comprendre un problème de réseau.

mvn -o test

Mode hors ligne : Maven n’utilise que le dépôt local. Si cette commande réussit alors que mvn test échoue, votre problème est un problème de réseau, pas un problème de projet.

Vérifier ce qui a été produit

Un dossier target est apparu à côté de pom.xml. Il contient :

  • target/classes — vos classes compilées de src/main/java
  • target/test-classes — vos classes de test compilées
  • target/surefire-reports — les rapports d’exécution, en .txt et en .xml

Ce dossier est entièrement reconstructible : il ne se sauvegarde pas et ne se versionne jamais. Pour le supprimer :

mvn clean

Et pour tout refaire de zéro, la commande que vous taperez le plus souvent du parcours :

mvn clean test

Récapitulatif : votre poste est-il prêt ?

Cochez les six points. Tous, pas cinq sur six.

  • [ ] java -version affiche une version 11
  • [ ] mvn -v affiche Apache Maven 3.
  • [ ] La ligne Java version: de mvn -v affiche 11.
  • [ ] Le dossier .m2/repository existe et n’est pas vide
  • [ ] mvn test se termine par BUILD SUCCESS
  • [ ] La sortie affiche Tests run: 2, Failures: 0, Errors: 0

Si un seul point manque, traitez-le maintenant. Les chapitres suivants supposent ces six points acquis, et une panne d’environnement qui remonte trois modules plus loin est beaucoup plus difficile à diagnostiquer, parce qu’elle se déguise en erreur Selenium.


Ce que ce chapitre ne couvre pas

Pour que ce soit dit, plutôt que découvert à la mauvaise heure :

  • Les autres phases du cycle de vie Maven. package, install, deploy, site ne sont pas abordées. Vous n’en avez pas besoin pour exécuter des tests.
  • La portée des dépendances au-delà de test (compile, provided, runtime), et la résolution des conflits de versions transitives. Vues au module Maven/TestNG.
  • La propriété maven.compiler.release, qui remplace le couple source/target depuis le JDK 9 et vérifie en plus que vous n’utilisez pas d’API trop récente. Nous restons sur source/target, plus répandu dans les projets existants que vous rencontrerez.
  • Le fichier testng.xml et les suites TestNG. Ce chapitre installe JUnit 5. TestNG arrivera plus tard, et cohabitera avec JUnit dans le même pom.xml.
  • Les dépendances Selenium. Elles ne sont pas encore dans ce pom.xml : c’est l’objet du premier chapitre Selenium. Rien à ajouter pour l’instant.
  • Le Maven Wrapper (mvnw), qui permet de figer la version de Maven par projet.
  • Les dépôts privés d’entreprise (Nexus, Artifactory) au-delà de la mention faite plus haut, et la publication d’artefacts.
  • Git et le .gitignore. Le dossier target ne doit pas être versionné, mais le versionnement est traité dans son propre module.

Ce qu’il faut retenir

Trois idées, et elles vous serviront bien après ce chapitre :

mvn -v vous dit quel JDK Maven utilise. Pas quel JDK vous avez installé : celui qu’il utilise. Quand un build se comporte de façon inexplicable, c’est la première commande à lancer.

Le dépôt local .m2 explique la lenteur du premier build et la rapidité des suivants. Quand une résolution de dépendance échoue sans raison apparente, supprimer le sous-dossier concerné est souvent le remède le plus rapide.

Un pom.xml écrit à la main est un pom.xml que vous savez réparer. Vous venez d’en écrire un dont vous connaissez chaque balise, et dont les versions de greffons sont fixées — donc dont le comportement ne dépend pas de la version de Maven installée sur la machine.

Au chapitre suivant, vous ajouterez une dépendance à ce pom.xml et vous écrirez le code qui ouvre un navigateur tout seul.

STRATLEARN est l’activité de formation de STRATEST SARL. Mentions légales