Pourquoi tester et premier test JUnit 6

Première leçon du cours Tests avec JUnit, en accès libre : environ 15 minutes, 3 exercices et 3 questions de quiz. C'est la leçon de base du catalogue ; dans l'espace étudiant, elle est réécrite pour ton profil.

Objectifs

  • Expliquer ce qu'apporte un test unitaire automatisé
  • Écrire un premier test JUnit 6 structuré en Arrange / Act / Assert
  • Lancer les tests avec Maven ou Gradle et lire le rapport

Tests unitairesJUnit 6 (Jupiter)Structure Arrange / Act / Assert

Vérifier son code « à la main » avec des System.out.println fonctionne une fois, mais pas après chaque modification. Un test unitaire automatisé est un petit programme qui appelle votre code et vérifie le résultat. On peut en exécuter des centaines en quelques secondes, à chaque changement : c’est un filet de sécurité qui permet de modifier le code sans peur de tout casser.

JUnit 6 dans un projet Maven

JUnit est le framework de test standard en Java. La version actuelle, JUnit 6 (sortie en septembre 2025), exige Java 17 ou plus et garde l’API Jupiter (org.junit.jupiter) introduite avec JUnit 5 : le code de test s’écrit de la même façon, et ce cours s’applique aussi à un projet resté en JUnit 5. Nouveauté pratique : tous les modules JUnit (plateforme, Jupiter) portent désormais le même numéro de version.

Créez le squelette avec l’archétype Maven, puis le Maven Wrapper (mvnw), qui fixe la version de Maven du projet pour toute l’équipe :

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 \
    -DgroupId=fr.boutique -DartifactId=boutique -DinteractiveMode=false
cd boutique
mvn wrapper:wrapper     # crée mvnw, mvnw.cmd et .mvn/ ; ensuite on utilise ./mvnw

L’archétype génère un pom.xml ciblant Java 17 et JUnit 5.11 : passez-le à Java 25 et à JUnit 6. Le BOM junit-bom fixe en un seul endroit la version de tous les modules JUnit :

<properties>
  <maven.compiler.release>25</maven.compiler.release>
</properties>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.junit</groupId>
      <artifactId>junit-bom</artifactId>
      <version>6.1.3</version> <!-- dernière version sur Maven Central lors de la rédaction -->
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId> <!-- API, moteur et tests paramétrés -->
    <scope>test</scope>
  </dependency>
</dependencies>

Dans un projet Spring Boot, ne déclarez pas de version : les starters de test de Spring Boot 4 apportent JUnit 6, Mockito et AssertJ.

Le code de production va dans src/main/java, les tests dans src/test/java, avec le même package.

Un premier test

// src/main/java/fr/boutique/Calculatrice.java
public class Calculatrice {
    public int ajouter(int a, int b) { return a + b; }
}
// src/test/java/fr/boutique/CalculatriceTest.java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

class CalculatriceTest {

    @Test
    void ajouter_deuxPositifs_renvoieLaSomme() {
        // Arrange : préparer les données et l'objet testé
        Calculatrice calc = new Calculatrice();
        // Act : exécuter le comportement testé
        int resultat = calc.ajouter(2, 3);
        // Assert : vérifier le résultat
        assertEquals(5, resultat);
    }
}
  • @Test marque une méthode de test. Depuis JUnit 5 (et toujours en JUnit 6), la classe et les méthodes peuvent rester package-private (sans public).
  • assertEquals(attendu, obtenu) : mettez toujours l’attendu en premier, sinon le message d’échec sera trompeur.
  • Le nom du test décrit le scénario : methode_situation_resultatAttendu est une convention répandue.

Lancer les tests

./mvnw test         # Maven via le wrapper (plugin Surefire) ; mvnw.cmd test sous Windows
./gradlew test      # Gradle (avec useJUnitPlatform())

Les IDE (IntelliJ IDEA, VS Code, Eclipse) affichent un bouton d’exécution à côté de chaque test. En cas d’échec, JUnit affiche un message comme expected: <5> but was: <6> avec la ligne fautive.

Le cycle rouge / vert / refactor

Le TDD (Test-Driven Development) consiste à écrire le test avant le code :

  1. Rouge : écrire un test qui échoue (la fonctionnalité n’existe pas encore) ;
  2. Vert : écrire le code le plus simple qui le fait passer ;
  3. Refactor : améliorer le code, les tests garantissant que rien ne casse.

Même sans pratiquer le TDD strict, retenez qu’un bon test est rapide, isolé, répétable et vérifie un seul comportement.

Sur cette plateforme, JUnit n’est pas installé dans l’éditeur d’exercices : vous écrirez de petits tests « maison » dans main qui reproduisent exactement la logique de JUnit (comparer attendu et obtenu, afficher PASS ou FAIL). Les exemples JUnit de la leçon sont à exécuter dans votre projet Maven.

Exercices

Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.

  1. CodeDifficulté 1Sandbox serveur2 indices

    Mon premier lanceur de tests

    Reproduisez le principe d’assertEquals. Écrivez une méthode static boolean verifierEgal(String nom, int attendu, int obtenu) qui affiche PASS nom ou FAIL nom: attendu X, obtenu Y et renvoie le résultat.

    Chaque ligne de l’entrée décrit un cas a b attendu. Pour chaque cas, appelez Calculatrice.ajouter(a, b) et vérifiez le résultat avec le nom ajouter(a, b). Terminez par Résultat : R/T tests réussis.

    import java.util.*;
    
    public class Main {
        static boolean verifierEgal(String nom, int attendu, int obtenu) {
            // TODO
            return false;
        }
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            Calculatrice calc = new Calculatrice();
            int reussis = 0, total = 0;
            // TODO : lire les cas et les vérifier
            System.out.println("Résultat : " + reussis + "/" + total + " tests réussis");
        }
    }
    
    class Calculatrice {
        int ajouter(int a, int b) { return a + b; }
    }
  2. CodeDifficulté 2Sandbox serveur2 indices

    Tester une fonction palindrome

    Implémentez static boolean estPalindrome(String s) qui ignore la casse et les espaces ("Esope reste ici et se repose" est un palindrome ; la chaîne vide aussi).

    Dans main, écrivez quatre tests maison nommés exactement motSimple ("kayak" → true), majuscules ("Radar" → true), phraseAvecEspaces (la phrase ci-dessus → true) et nonPalindrome ("java" → false), affichés PASS nom ou FAIL nom. Ensuite, pour chaque ligne de l’entrée, affichez mot -> true ou mot -> false.

    import java.util.*;
    
    public class Main {
        static boolean estPalindrome(String s) {
            // TODO
            return false;
        }
    
        static void test(String nom, boolean attendu, boolean obtenu) {
            System.out.println((attendu == obtenu ? "PASS " : "FAIL ") + nom);
        }
    
        public static void main(String[] args) {
            // TODO : les quatre tests, puis l'exploration des lignes d'entrée
        }
    }
  3. QCMDifficulté 11 indice

    Ordre des arguments

    Dans assertEquals(a, b) de JUnit, que doivent représenter a et b ?

    • a = valeur obtenue, b = valeur attendue
    • a = valeur attendue, b = valeur obtenue
    • L'ordre n'a aucune importance

Quiz de fin de leçon

  1. Quel import correspond à l’annotation @Test de JUnit 6 ?

    • org.junit.Test
    • org.junit.jupiter.api.Test
    • java.test.Test
  2. Dans quelle étape d’un test appelle-t-on la méthode testée ?

    • Arrange
    • Act
    • Assert
  3. Que signifie la phase « rouge » du TDD ?

    • Écrire un test qui échoue avant d'écrire le code
    • Supprimer les tests qui échouent
    • Corriger un bug en production

La suite du cours

  1. Les assertions JUnit et le test des exceptions18 min
  2. Cycle de vie des tests et organisation16 min
  3. Tests paramétrés16 min
  4. Isoler le code : doubles de test et Mockito20 min

Tests avec JUnit · Intermédiaire · 2 h 25