Framework de test unitaire Java JUnit
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 :
- Détection précoce des problèmes: Découvrir et corriger les erreurs pendant le développement
- Qualité de code améliorée: Encourage les développeurs à écrire du code plus modulaire et testable
- Valeur de documentation: Les cas de test eux-mêmes sont la meilleure documentation du comportement du code
- Filet de sécurité pour le refactoring: Garantit que la modification du code ne casse pas les fonctionnalités existantes
- 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
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
@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
@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 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 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
@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 :
@BeforeAllExécution de méthode (une seule fois)- 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
@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.Suite;
@Suite
@SelectClasses({CalculatorTest.class, AnotherTest.class})
public class TestSuite {
}
Bonnes pratiques
- Nommage des tests: Les noms des méthodes de test doivent clairement exprimer leur intention, par exemple
shouldReturnTrueWhenInputIsValid() - Responsabilité unique: Chaque méthode de test ne doit tester qu'une seule fonctionnalité
- Tests indépendants: Les tests ne doivent pas avoir de dépendances entre eux
- Retour rapide: Veillez à ce que les tests s'exécutent rapidement
- Couverture des tests: Visez une couverture raisonnable, mais ne poursuivez pas aveuglément 100%
- Données de test: Utilisez des données de test significatives
- É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 du
org.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 :
- Faites un clic droit sur la classe de test ou la méthode dans l'IDE et sélectionnez "Run"
- Avec Maven :
mvn test - Utilisation de Gradle :
gradle test - 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 :
- Utilisation de la réflexion
- 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
- 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.
Autres extensions
Bibliothèques communes Java