Framework de test unitaire Java JUnit

Java 常用类库Bibliothèques communes Java


JUnit est l'un des frameworks de test unitaire les plus populaires pour le langage de programmation Java, utilisé pour écrire et exécuter des tests automatisés reproductibles.

JUnit a été créé par Kent Beck et Erich Gamma et fait partie de la famille xUnit. Le test unitaire est le processus de vérification et de validation des plus petites parties testables d'un logiciel, généralement des méthodes ou des classes.

Les principales fonctionnalités de JUnit incluent :

  • Fournit des annotations pour identifier les méthodes de test
  • Fournit des assertions pour vérifier les résultats attendus
  • Prend en charge les suites de tests
  • Fournit un exécuteur de tests

Pourquoi avons-nous besoin de tests unitaires ?

Les tests unitaires sont une partie indispensable du développement logiciel moderne. Ils apportent les avantages suivants :

  1. Détection précoce des problèmes: Découvrir et corriger les erreurs pendant le développement
  2. Qualité de code améliorée: Encourage les développeurs à écrire du code plus modulaire et testable
  3. Valeur de documentation: Les cas de test eux-mêmes sont la meilleure documentation du comportement du code
  4. Filet de sécurité pour le refactoring: Garantit que la modification du code ne casse pas les fonctionnalités existantes
  5. Temps de débogage réduit: Localiser rapidement les problèmes

Utilisation de JUnit dans les projets

Pour JUnit 5 :

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

Pour JUnit 4 :

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

Les bases de JUnit 5

JUnit 5 est la dernière version, composée de trois modules principaux :

  • JUnit Platform (la fondation pour exécuter les tests)
  • JUnit Jupiter (nouveau modèle de programmation et modèle d'extension)
  • JUnit Vintage (prend en charge l'exécution des tests JUnit 3 et 4)

Annotations de base

Annotations héritées :

  • @Test: Marque une méthode comme méthode de test

  • @Before: S'exécute avant chaque méthode de test

  • @After: S'exécute après chaque méthode de test

  • @BeforeClass: S'exécute avant tous les tests (méthode statique)

  • @AfterClass: S'exécute après tous les tests (méthode statique)

  • @Ignore: Ignore une méthode de test

Exemple

import org.junit.*;

public class CalculatorTest {
   
    @BeforeClass
    public static void setUpBeforeClass() {
        System.out.println("Avant tous les tests");
    }
   
    @Before
    public void setUp() {
        System.out.println("Avant chaque test");
    }
   
    @Test
    public void testAddition() {
        Calculator calculator = new Calculator();
        int result = calculator.add(2, 3);
        Assert.assertEquals(5, result);
    }
   
    @Test
    @Ignore("Pas encore implémenté")
    public void testSubtraction() {
        // code de test
    }
   
    @After
    public void tearDown() {
        System.out.println("Après chaque test");
    }
   
    @AfterClass
    public static void tearDownAfterClass() {
        System.out.println("Après tous les tests");
    }
}

JUnit 5 est la version de nouvelle génération, avec les nouvelles annotations suivantes :

  • @BeforeEachremplace@Before

  • @AfterEachremplace@After

  • @BeforeAllremplace@BeforeClass

  • @AfterAllremplace@AfterClass

  • @Disabledremplace@Ignore

Exemple

import org.junit.jupiter.api.*;

@Test
void testMethod() {
    // code de test
}

@BeforeEach
void setUp() {
    // S'exécute avant chaque méthode de test
}

@AfterEach
void tearDown() {
    // S'exécute après chaque méthode de test
}

@BeforeAll
static void initAll() {
    // S'exécute une fois avant toutes les méthodes de test
}

@AfterAll
static void tearDownAll() {
    // S'exécute une fois après toutes les méthodes de test
}

Méthodes d'assertion courantes

JUnit fournit un riche ensemble de méthodes d'assertion pour vérifier les résultats de test :

  • assertEquals(expected, actual)

  • assertTrue(condition)

  • assertFalse(condition)

  • assertNull(object)

  • assertNotNull(object)

  • assertSame(expected, actual)(Vérifie s'il s'agit du même objet)

  • assertNotSame(unexpected, actual)

  • assertArrayEquals(expectedArray, actualArray)

Exemple

import static org.junit.jupiter.api.Assertions.*;

@Test
void testAssertions() {
    // Assertion d'égalité
    assertEquals(expected, actual);
   
    // Assertion vraie
    assertTrue(condition);
   
    // Assertion de nullité
    assertNull(object);
   
    // Assertion d'exception
    assertThrows(ExpectedException.class, () -> {
        // Code qui lance une exception
    });
   
    // Assertion de délai d'attente
    assertTimeout(Duration.ofMillis(100), () -> {
        // Code qui doit se terminer dans le délai spécifié
    });
}

Écrire votre premier test JUnit

Apprenons à écrire des tests JUnit avec un exemple simple.

1. Créer la classe à tester

Exemple

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
   
    public int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("Le diviseur ne peut pas être zéro");
        }
        return a / b;
    }
}

2. Créer la classe de test

Exemple

import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    private Calculator calculator;
   
    @BeforeEach
    void setUp() {
        calculator = new Calculator();
    }
   
    @Test
    void testAdd() {
        assertEquals(5, calculator.add(2, 3));
    }
   
    @Test
    void testDivide() {
        assertEquals(2, calculator.divide(6, 3));
    }
   
    @Test
    void testDivideByZero() {
        assertThrows(ArithmeticException.class, () -> {
            calculator.divide(1, 0);
        });
    }
}

Fonctionnalités avancées de JUnit

Tests paramétrés

JUnit 5 fournit l'@ParameterizedTestannotation, permettant d'exécuter le même test plusieurs fois avec des paramètres différents :

Exemple

@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testWithValueSource(int argument) {
    assertTrue(argument > 0 && argument < 4);
}

Cycle de vie des tests

Comprendre le cycle de vie des tests JUnit est important pour écrire des tests efficaces :

  1. @BeforeAllExécution de méthode (une seule fois)
  2. Pour chaque méthode de test :
    • Créer une instance de la classe de test
    • @BeforeEachExécution de méthode
    • Exécution de la méthode de test
    • @AfterEachExécution de méthode
  3. @AfterAllExécution de méthode (une seule fois)

Suites de tests

Vous pouvez utiliser la@Suiteannotation pour combiner plusieurs classes de test à exécuter ensemble :

Exemple

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses({CalculatorTest.class, AnotherTest.class})
public class TestSuite {
}

Bonnes pratiques

  1. Nommage des tests: Les noms des méthodes de test doivent clairement exprimer leur intention, par exempleshouldReturnTrueWhenInputIsValid()
  2. Responsabilité unique: Chaque méthode de test ne doit tester qu'une seule fonctionnalité
  3. Tests indépendants: Les tests ne doivent pas avoir de dépendances entre eux
  4. Retour rapide: Veillez à ce que les tests s'exécutent rapidement
  5. Couverture des tests: Visez une couverture raisonnable, mais ne poursuivez pas aveuglément 100%
  6. Données de test: Utilisez des données de test significatives
  7. Évitez de tester les détails d'implémentation: Testez le comportement plutôt que l'implémentation

Questions fréquentes

Quelle est la différence entre JUnit 4 et JUnit 5 ?

Les principales différences incluent :

  • JUnit 5 nécessite Java 8 ou une version supérieure
  • Les annotations ont été déplacées duorg.junitpackage vers leorg.junit.jupiter.apiPaquet
  • @Beforeet@Afterremplacé par@BeforeEachet@AfterEach
  • @BeforeClasset@AfterClassremplacé par@BeforeAllet@AfterAll
  • JUnit 5 introduit un modèle d'extension pour remplacer les règles de JUnit 4

Comment exécuter les tests JUnit ?

Vous pouvez exécuter les tests JUnit des manières suivantes :

  1. Faites un clic droit sur la classe de test ou la méthode dans l'IDE et sélectionnez "Run"
  2. Avec Maven :mvn test
  3. Utilisation de Gradle :gradle test
  4. Utilisation de JUnit Console Launcher

Comment tester les méthodes privées ?

Il n'est généralement pas recommandé de tester directement les méthodes privées ; il faut plutôt les tester indirectement via des méthodes publiques. Si vous devez tester des méthodes privées, envisagez :

  1. Utilisation de la réflexion
  2. Changez la méthode en package-private (sans modificateur) et créez une classe de test avec la même structure de package dans le répertoire de test
  3. Refactorisez le code pour extraire la logique de la méthode privée dans une classe séparée

Résumé

JUnit est un outil de test essentiel pour les développeurs Java. Le maîtriser peut considérablement améliorer la qualité du code et l'efficacité du développement. Commencez par de simples tests unitaires et apprenez progressivement des fonctionnalités plus avancées, telles que les tests paramétrés et les suites de tests. N'oubliez pas que les bons tests doivent être valorisés autant que le code de production ; garder le code de test propre et maintenable est tout aussi important.

Java 常用类库Bibliothèques communes Java

Autres extensions