0% ont trouvé ce document utile (0 vote)
58 vues16 pages

TDD et JUnit : Guide Complet en Java

Ce document présente une introduction au test piloté par les tests (TDD) en Java. Il définit ce qu'est un test, les différents niveaux et phases de test, et compare l'approche classique du test à l'approche TDD. Le TDD consiste à écrire le test avant le code afin de concevoir une architecture testable et faiblement couplée.

Transféré par

Alaa ßrahim
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
58 vues16 pages

TDD et JUnit : Guide Complet en Java

Ce document présente une introduction au test piloté par les tests (TDD) en Java. Il définit ce qu'est un test, les différents niveaux et phases de test, et compare l'approche classique du test à l'approche TDD. Le TDD consiste à écrire le test avant le code afin de concevoir une architecture testable et faiblement couplée.

Transféré par

Alaa ßrahim
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Présentation Chiheb Ameur ABID 2/ 63

Définitions et concepts de base

Plan

1 Définitions et concepts de base


Test Driven Development en Java
2 Tests automatisés avec le framework JUnit

Dr. Ing. Chiheb Ameur ABID 3 Tests paramétrisés

Contact: [email protected] 4 Bonnes pratiques

Janvier 2023

Version 1.1

Présentation Chiheb Ameur ABID 3/ 63 Présentation Chiheb Ameur ABID 4/ 63


Définitions et concepts de base Définitions et concepts de base

Les tests Les tests

C’est quoi un test ?


➥ Le test est l’exécution ou l’évaluation d’un système ou d’un composant par des moyens
automatiques ou manuels, pour vérifier qu’il répond à ses spécifications ou identifier les
différences entre les résultats attendus et les résultats obtenus]. IEEE (Standard Glossary
Qu’est ce le test ? of Software Engineering Terminology)
➥ Test d’un système = processus d’essai des exécutions d’un système selon un certain ➥ Tester c’est réaliser l’exécution du programme
critère. L’observation de chaque exécution est comparée avec la spécification du système ➥ Oracle : résultats attendus d’une exécution du logiciel
sous test : ➥ Coût du test : 30
Z Si conforme : test passé (ACCEPT)
➥ Deux grandes familles de tests
Z Sinon : test échoué (FAIL)
Z Test fonctionnel (ou test boîte noire)
Z Test structurel (ou test boîte blanche)
➥ Cas de test (TC) : une exécution du programme déclenchée par des données de test (DT).
➥ Suite de tests (TS) : un ensemble de DT.
➥ Objectif de test (TO) : comportement de la spéc à tester.
➥ Système sous test (SUT ou IUT) : implémentation du système à tester.
Présentation Chiheb Ameur ABID 5/ 63 Présentation Chiheb Ameur ABID 6/ 63
Définitions et concepts de base Définitions et concepts de base

Les tests Les tests

Niveaux et phases
Difficultés du test ➥ Niveaux de tests
➥ Le test exhaustif est en général impossible à réaliser : Z Test unitaire = test des (petites) parties du code, séparément.
Z Test d’intégration = test d’un ensemble de parties du code qui coopèrent.
Z L’ensemble des données d’entrée est en général infini ou de très grande taille Z Test du système = test du système entier, en inspectant sa fonctionnalité.
Z La qualité du test dépend de la pertinence du choix des données de test Z Test d’acceptation = effectué par le client pour s’assurer de la conformité au besoin.
➥ Difficultés d’ordre psychologique ou culturel ➥ Phases de tests
Z Le test est un processus destructif : un bon test est un test qui trouve une erreur. Alors Z Test de régression = test réalisé pendant la maintenance aprés un changement, afin de
que l’activité de programmation est un processus constructif. s’assurer que les système continue de fonctionner correctement.
Z Test de robustesse = tester des entrées non-prévues.
Z Test sous stress = tester en conditions de surcharge.

Présentation Chiheb Ameur ABID 7/ 63 Présentation Chiheb Ameur ABID 8/ 63


Définitions et concepts de base Définitions et concepts de base

Définition et principes du TDD Définition et principes du TDD

TDD : développement piloté par le test


Approche classique du test ➥ On écrit le test avant d’écrire le code Z Réfléchir à ce que fait le code avant de coder
➥ L’approche classique du test consiste à coder puis tester à la fin ➥ Une ligne de code n’est écrite que si un test la rend nécessaire Z Impossible de livrer un
✖ Il ne reste plus de temps pour tester ! code non testé
✖ Plus le bug est détecté tard, plus il remet de choix en cause, et plus sa correction est ➥ Dans la mesure du possible on laisse l’architecture émerger au fil du développement (ce
coûteuse qui n’interdit pas une phase légère de conception à base d’UML), ce qui garantit une
✖ Comme le code est déjà écrit, on risque d’écrire — le nez sur le code — un test faux architecture testable et faiblement couplée Z le TDD est plus une approche de conception
qui valide un code faux objet de qualité que de recherche de bugs
Z Un code non ou mal testé n’a aucune valeur ➥ On considère les tests comme une documentation exécutable de l’API du système, une
spécification par l’exemple, et on les bichonne autant que son code.
Présentation Chiheb Ameur ABID 9/ 63 Présentation Chiheb Ameur ABID 10/ 63
Définitions et concepts de base Définitions et concepts de base

Définition et principes du TDD Le test dans le processus de développement

Principe du TDD

Comment un TDD peut améliorer la qualité d’un programme ? ➥ En TDD, vous allez écrire les solutions les plus basiques possibles pour faire passer vos
tests.
➥ Élaborer les tests avant chaque partie développée
➥ Une fois que vous avez écrit un bon test avec le code le plus simple possible, vous avez fini
Z Ne pas livrer un code non testé – et vous pouvez avancer au prochain test.
Z Détecter les erreur le plus tôt possible
➥ En découpant le problème en petites parties et les tester chacune à part.
TDD : les trois bonnes règles
Z Ceci réduit le taux d’erreur et augmente le temps de développement des applications.
Z Il réduit aussi le temps de maintenance. ➥ Il y a trois règles à respecter, selon Robert Martin (un leader dans le monde de TDD)
➥ Séparation entre le code de tests et le code applicatif ❶ Écrire un test qui échoue avant d’écrire votre code lui-même.
❷ Ne pas écrire un test compliqué.
❸ Ne pas écrire plus de code que nécessaire, juste assez pour faire passer le test qui
échoue.

Présentation Chiheb Ameur ABID 11/ 63 Présentation Chiheb Ameur ABID 12/ 63
Définitions et concepts de base Définitions et concepts de base

Le test dans le processus de développement Le test dans le processus de développement

Cycle de TDD
➥ Écrire un test Les gains du TDD
➥ Exécuter le test et constater qu’il échoue (barre rouge) ; si le verdict est en fait une erreur ➥ Le test unitaire fournit un retour constant sur les fonctions
due au fait que le code ne compile pas (en Java) car le code applicatif n’a pas encore été ➥ La qualité de la conception augmente, ce qui contribue davantage à un bon entretien
écrit, alors écrire le code applicatif minimal du point de vue du langage, et vérifier cette ➥ Le développement piloté par les tests agit comme un filet de sécurité contre les bogues
fois que le test échoue à cause de l’oracle
➥ TDD garantit que votre application répond réellement aux exigences définies pour elle
➥ Écrire le code applicatif le plus simple qui permet de faire passer le test, et seulement ce
code ➥ TDD a un cycle de vie de développement très court
➥ Lancer le test et vérifie qu’il passe (barre verte)
➥ Réusiner les tests et le code
Présentation Chiheb Ameur ABID 13/ 63 Présentation Chiheb Ameur ABID 14/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit

Plan Présentation du framework JUnit

Le besoin d’un framework de test ?


➥ L’utilisation d’un framework des tests automatisés augmentera la vitesse et l’efficacité des
1 Définitions et concepts de base tests d’une équipe,
➥ Améliorer la précision des tests et réduire les coûts de maintenance des tests ainsi que les
2 Tests automatisés avec le framework JUnit
risques.
Le framework JUnit 4
Le framework JUnit 5
Le framework JUnit
3 Tests paramétrisés ➥ JUnit est un framework de tests unitaires open source pour JAVA. Il est utile pour les
développeurs Java d’écrire et d’exécuter des tests reproductibles
4 Bonnes pratiques ➥ JUnit est intégré à Eclipse

Présentation Chiheb Ameur ABID 15/ 63 Présentation Chiheb Ameur ABID 16/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

Le framework JUnit 4 Tests automatisés avec le framework JUnit

Principe
➥ Une classe de tests unitaires est associée à une autre classe
➥ Une classe de tests unitaires hérite de la classe junit.framework.TestCase pour
Les annotations de JUnit
bénéficier de ses méthodes de tests
➥ Des annotations ont été introduites dans JUnit 4 rendant le code Java plus lisible et simple.
➥ Les méthodes de tests sont identifiées par des annotations Java
Z JUnit 4 est basée sur les annotations
Z Nécessite Java 5 ou supérieur
➥ Il n’est plus nécessaire d’imposer un nom pour les méthodes de test Méthodes de tests

➥ static imports pour les assertions ➥ Nom quelconque


➥ Visibilité public, type de retour void
➥ Pas de paramètre, peut lever une exception
➥ Annotée @Test
➥ Utilise des instructions de test
Présentation Chiheb Ameur ABID 17/ 63 Présentation Chiheb Ameur ABID 18/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit

Anatomie d’un test unitaire


Exécution d’un test
❶ Initialisation (Setup)
Z Définir le contexte et l’environnement du test @Test // Annotation designant la methode comme un test
public void testXXX() {
❷ Exercice (Trigger)
//Define
Z Appel de l’unité à tester Instructions de mise en contexte
❸ Vérification (Verify) //When
Z Vérification du résultat ou état produit Instruction sous test
//Then
❹ Désactivation (Teardown)
Observation et verification de l’oracle
Z Nettoyage, remettre le système dans son état initial }

Présentation Chiheb Ameur ABID 19/ 63 Présentation Chiheb Ameur ABID 20/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit

Instructions de test
Les annotations de JUnit 4
➥ Une annotation est désignée par un nom précédé du caractère @
➥ Une annotation précède l’entité qu’elle concerne
➥ Toutes les annotations sont définies dans le package org.junit

Z L’instruction la plus importante est fail() : les autres ne sont que des raccourcis
d’écriture !
Présentation Chiheb Ameur ABID 21/ 63 Présentation Chiheb Ameur ABID 22/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

Tests automatisés avec le framework JUnit 4 Tests automatisés avec le framework JUnit 4

Exemple simple
➥ Créer un nouveau projet Java Méthodes de test

➥ On désire tester la méthode ci-après où on a introduit volontairement une erreur (classe ➥ Une méthode de test est une méthode qui exécute un test unitaire
Example) ➥ Les méthodes de test sont annotées avec @Test
public static int somme(int a,int b,int c) { ➥ Convention de nommage d’une méthode de test test[méthode à tester]()
return a+b-c;
} Z Mais aucune obligation (nom quelconque possible)
➥ Publique, sans paramètre, type de retour void
➥ Créer un Junit Test Case implémentant le test suivant :
➥ Les principaux paramètres de l’annotation @Test
@Test
public void test() { Z expected : le test échoue si une exception n’est pas levée
int resultat= Example.somme(5,4,2);
assertEquals(11,resultat);
Z timeout : durée maximale spécifiée en millisecondes
}
➥ L’annotation @Ignore permet d’ignorer un test
➥ Tester le cas de test à partir du menu contextuel : choisir Run As -> JUnit Test

Présentation Chiheb Ameur ABID 23/ 63 Présentation Chiheb Ameur ABID 24/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

Tests automatisés avec le framework JUnit 4 Tests automatisés avec le framework JUnit 4

Méthodes de test : vérification de levée d’une exception


➥ On peut utiliser l’attribut expected de l’annotation @Test
@Test(expected = NullPointerException.class)
public void whenExceptionThrown_thenExpectationSatisfied() { Méthodes d’initialisation et de finalisation
String test = null;

}
test.length(); ➥ Méthodes d’initialisation utilisée avant chaque test
Z setUp() est une convention de nommage
➥ En utilisant l’annotation @Rule Z L’annotation @Before est utilisée
Z Elle permet de vérifier certaines propriétés de l’exception levée ➥ Méthodes de finalisation utilisée après chaque test
@Rule
Z tearDown() est une convention de nommage
public ExpectedException exceptionRule = ExpectedException.none(); Z L’annotation @After est utilisée
@Test
public void whenExceptionThrown_thenRuleIsApplied() {
exceptionRule.expect(NumberFormatException.class);
exceptionRule.expectMessage("For input string");
Integer.parseInt("1a");
}
Présentation Chiheb Ameur ABID 25/ 63 Présentation Chiheb Ameur ABID 26/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit

Méthodes d’initialisation et de finalisation


➥ Méthodes d’initialisation globale
Z Annotée @BeforeClass Exemple du TDD
Z Publique et statique
➥ En appliquant les principes de TDD, notre objectif est de développer une fonction
Z Exécutée une seule fois avant la première méthode de test
permettant valider un mot de passe
➥ Méthode de finalisation globale
Z Le mot de passe doit comprendre entre 5 et 10 caractères
Z Annotée @AfterClass
Z Publique et statique
Z Exécutée une seule fois après la dernière méthode de test
Z Dans les 2 cas, une seule méthode par annotation

Présentation Chiheb Ameur ABID 27/ 63 Présentation Chiheb Ameur ABID 28/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

❶ Écrire un test
➥ On commence par écrire un test ❷ Écrire le code applicatif
package j1exemple1; ➥ On écrit le code applicatif pour faire passer le test
import static org.junit.Assert.*;
import org.junit.Assert;
import org.junit.Test; package j1exemple1;
class ValidPasswordTest {
@Test public class PasswordValidator {
void test() {
PasswordValidator pv=new PasswordValidator(); public boolean isValid(String pw) {
Assert.assertEquals(true,pv.isValid("123456")); if (pw.length()>=5 && pw.length()<=10)
}
} return true;
else
➥ Pour exécuter le test, à partir du menu contextuel, choisir Run As -> JUnit Test return false;
➥ Évidemment, on est en rouge, puisque le code applicatif n’existe pas }
}

➥ Résultat de l’exécution du test : succès


Présentation Chiheb Ameur ABID 29/ 63 Présentation Chiheb Ameur ABID 30/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

❸ Reusiner
➥ On optimise notre code de test
Z Il n’est pas nécessaire de créer une instance de la classe PasswordValidator
Z Associer un message personnalisé à l’assertion ❹ Reusiner le test
package j1exemple1; ➥ On corrige le code applicatif pour passer le test
import static org.junit.Assert.*;
import org.junit.Assert; package j1exemple1;
import org.junit.Test;
public class PasswordValidator {
class ValidPasswordTest { static public boolean isValid(String pw) {
@Test if (pw.length()>=5 && pw.length()<=10)
void test() { return true;
Assert.assertEquals("Verifier longueur mot de passe ",true,PasswordValidator.isValid("123456 else
")); return false;
} }
} }

➥ Résultat de l’exécution de test : échec ➥ Résultat de l’exécution de test : succès

Présentation Chiheb Ameur ABID 31/ 63 Présentation Chiheb Ameur ABID 32/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 4 Le framework JUnit 4

Exercice : jeu de Tic-Tac-Toe


➥ On se propose de développer certaines fonctionnalités du célèbre jeu de Tic-Tac-Toe. Ce
jeu se déroule sur une grille 3x3 où deux joueurs posent leurs pions dans le but d’être le
premier à en aligner trois.
Exercice : jeu de Tic-Tac-Toe
➥ Ajouter la fonctionnalité permettant de garantir que le placement d’un pion ne s’effectue
que dans une case vide. En cas d’échec, une exception de type RuntimeException est
générée indiquant que la case est déjà occupée
➥ Réusiner le code
Z Prévoir une fonction permettant de vérifier s’il y a un dépassement sur un axe
Z Prévoir une fonction pour effectuer le placement d’un pion

➥ On désire commencer par implémenter la méthode play (int x,int y)


permettant de vérifier que les coordonnées x et y de placement d’un pion sur la grille sont
valides. Dans le cas contraire, la méthode play doit générer une exception de type
RuntimeException
Z D’abord, effectuer un test de dépassement selon l’axe des X.
Z Puis, effectuer un test de dépassement selon l’axe des Y.
Présentation Chiheb Ameur ABID 33/ 63 Présentation Chiheb Ameur ABID 34/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

Architecture de JUnit 5

JUnit5 : la nouvelle version


➥ JUnit 5 est une réécriture complète de l’API de JUnit 4 en Java 8
Z Supporte les nouveautés de Java 8
➥ Un framework modulaire
Z JUnit 4 est livré sous forme d’un seul fichier jar
Z JUnit 5 est composé de trois projets : Platform, Jupiter, et Vintage
➥ JUnit 5 est extensible
➥ Les classes de tests JUnit 5 sont similaires à celles de JUnit 4 : basiquement, il suffit
d’écrire une classe contenant des méthodes annotées avec @Test.

Présentation Chiheb Ameur ABID 35/ 63 Présentation Chiheb Ameur ABID 36/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

JUnit5 vs JUnit4 : les annotations

Méthodes de test : vérification de levée d’une exception


➥ L’attribut expected de l’annotation @Test n’est plus valide avec JUnit 5
➥ L’annotation @Rule est aussi enlevée de JUnit 5
@Test
public void whenExceptionThrown_thenAssertionSucceeds() {
Exception exception = assertThrows(NumberFormatException.class, () -> {
Integer.parseInt("1a");
});

String expectedMessage = "For input string";


String actualMessage = exception.getMessage();

assertTrue(actualMessage.contains(expectedMessage));
}

JUnit5 vs JUnit4 : les assertions


Z Toute exception de type classe fille de l’exception attendue est acceptée
Présentation Chiheb Ameur ABID 37/ 63 Présentation Chiheb Ameur ABID 38/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

Exemple de TDD avec JUnit 5


➥ Commençons par écrire un premier test
Z Créer un nouveau projet Java
Z Choisir File->New->JUnit Test Case pour créer une classe de test. Vérifier
bien l’utilisation de JUnit 5

Exemple de TDD avec JUnit 5


On se propose d’organiser des livres dans une étagère. En suivant une démarche TDD, on se
propose d’implémenter la fonctionnalité d’ajouter un livre. Pour simplifier, on commence par
identifier un livre par une chaine de caractères, i.e. le type String.

➥ Nous écrivons un premier test permettant de vérifier que l’étagère est initialement vide
@Test
public void emptyBookShelfWhenNoBookAdded() {
BookShelf shelf = new BookShelf();
List<String> books = shelf.books();
assertTrue(books.isEmpty(), () -> "BookShelf should be empty.");
}

Présentation Chiheb Ameur ABID 39/ 63 Présentation Chiheb Ameur ABID 40/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

Exemple de TDD avec JUnit 5


Exemple de TDD avec JUnit 5
➥ On désire maintenant ajouter la fonctionnalité d’ajouter un livre dans une étagère.
➥ Pour passer au vert dans le cycle de TDD, on écrit une première version du code applicatif
Z Il s’agit de la classe qui représente une étagère ➥ On propose d’écrire un test permettant de vérifier que si on effectue deux opérations
d’ajout, alors on aurait bien deux livres dans l’étagère
import java.util.Collections;
import java.util.List; @Test
void bookshelfContainsTwoBooksWhenTwoBooksAdded() {
public class BookShelf { BookShelf shelf = new BookShelf();
public List<String> books() { shelf.add("Programmer en Java");
return Collections.emptyList(); shelf.add("Tester avant");
} List<String> books = shelf.books();
} assertEquals(2, books.size(), () -> "BookShelf should have two books.");
}
Présentation Chiheb Ameur ABID 41/ 63 Présentation Chiheb Ameur ABID 42/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

Exemple de TDD avec JUnit 5

Exemple de TDD avec JUnit 5 ➥ Est-il possible de modifier la liste retournée par la méthode books() ?
Z Violer le principe d’encapsulation ! ?
➥ Modifier le code applicatif pour passer au vert
➥ Écrire un test pour vérifier cette contrainte
import java.util.ArrayList;
import java.util.List; @Test
public class BookShelf { void booksReturnedFromBookShelfIsImmutableForClient() {
private final List<String> books = new ArrayList<>(); BookShelf shelf = new BookShelf();
public List<String> books() { shelf.add("Effective Java");
return books; shelf.add("Code Complete");
} List<String> books = shelf.books();
public void add(String bookToAdd) { try {
books.add(bookToAdd); books.add("The Mythical Man-Month");
} fail(() -> "Should not be able to add book to books");
} } catch (Exception e) {
assertTrue(e instanceof UnsupportedOperationException, () -> "Should throw
UnsupportedOperationException.");
}
}

Présentation Chiheb Ameur ABID 43/ 63 Présentation Chiheb Ameur ABID 44/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

Exemple de TDD avec JUnit 5


➥ Modifier le code applicatif pour passer au vert pour le dernier test
Exemple de TDD avec JUnit 5
Z Il suffit de modifier le code de la méthode books() pour renvoyer une liste non
modifiable ➥ Peut-on améliorer la lisibilité du code de tests ? (Refactoring)
Z Utiliser l’annotation @BeforeEach pour effectuer l’initialisation une seule fois
public List<String> books() {
return Collections.unmodifiableList(books);
pour tous les tests
}

➥ Toujours, refaire les tests pour vérifier qu’ils sont au vert


Présentation Chiheb Ameur ABID 45/ 63 Présentation Chiheb Ameur ABID 46/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

Exemple de TDD avec JUnit 5

private BookShelf shelf;

@BeforeEach
Exercice de TDD avec JUnit 5
void init() throws Exception {
shelf = new BookShelf(); ❶ En continuant l’exemple précédent, et en suivant une démarche de TDD, ajouter la
} fonctionnalité permettant de trier la liste des livres selon l’ordre lexicographique
@Test ❷ On veut retourner une nouvelle liste triée en gardant la liste originale dans le même ordre
public void emptyBookShelfWhenNoBookAdded() {
List<String> books = shelf.books();
assertTrue(books.isEmpty(), () -> "BookShelf should be empty.");
}

[...]

Présentation Chiheb Ameur ABID 47/ 63 Présentation Chiheb Ameur ABID 48/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

Exemple du TDD avec JUnit 5


➥ On commence par écrire la classe de test
package testing;
import org.testng.Assert;
import org.testng.annotations.Test;
public class RemoveAFirstTest {
Exemple illustratif du TDD avec JUnit 5 @Test
public void removeATest() {
RemoveAfirst a=new RemoveAfirst();
➥ En appliquant les principes de TDD, créer un projet avec JUnit 5 qui permet de Assert.assertEquals("", a.removeLetterA("A"));
supprimer les lettres ‘A’ s’ils existent dans la première ou la deuxième position au début }
}
d’une chaine de caractères.
➥ Conditions à vérifier ➥ On propose un première solution pour le code applicatif
‘A’—”, ‘AB’—’B’, ‘AABC’—’BC’, ‘BACD’—’BCD’, ‘BBAA’—’BBAA’,
package testing;
‘AABAA’—’BAA’ public class RemoveAFirst {
public String removeLetterA(String chaine) {
String nvChaine="";
if (chaine.length()>2) {
if (chaine.charAt(0)==’A’ && chaine.charAt(1)==’A’)
nvChaine=""+chaine.substring(2);
}
else if (chaine.length()==2) {
if (chaine.charAt(0)==’A’)
nvChaine=""+chaine.substring(1);
}
return nvChaine;
}
}
Présentation Chiheb Ameur ABID 49/ 63 Présentation Chiheb Ameur ABID 50/ 63
Tests automatisés avec le framework JUnit Tests automatisés avec le framework JUnit
Le framework JUnit 5 Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Tests automatisés avec le framework JUnit 5

Exemple du TDD avec JUnit 5


➥ Continuer le cycle de développement TDD pour les autres conditions
➥ Le test de la 4ème condition échoue Exemple du TDD avec JUnit 5
➥ En continuant les tests, cette fois c’est la 5ème condition qui provoque une erreur
➥ Modifier le code applicatif pour corriger l’erreur et passer au vert
public String removeLetterA(String chaine) {
String nvChaine="";
int pos1=-1,pos2=-1;
if (chaine.length()>2) {
➥ Modifier le code applicatif pour passer au vert : on introduit les variables pos1 et pos2 pos1=chaine.indexOf(’A’);
pos2=chaine.lastIndexOf(’A’);
pour localiser les deux premières occurrences de ’A’ if (pos1==0 && pos2==1) nvChaine=""+chaine.substring(2);
else if (pos1==1) nvChaine=chaine.charAt(0)+chaine.substring(2);
public String removeLetterA(String chaine) { else nvChaine=chaine;
String nvChaine=""; }
int pos1=-1,pos2=-1; else if (chaine.length()==2) {
if (chaine.length()>2) { pos1=chaine.indexOf(’A’);
pos1=chaine.indexOf(’A’); if (pos1==0) nvChaine=""+chaine.substring(1);
pos2=chaine.lastIndexOf(’A’); else if (pos1==1) nvChaine=""+chaine.charAt(0);
if (pos1==0 && pos2==1) nvChaine=""+chaine.substring(2); }
else if (pos1==1) nvChaine=chaine.charAt(0)+chaine.substring(2); return nvChaine;
} }
else if (chaine.length()==2) {
pos1=chaine.indexOf(’A’);
if (pos1==0) nvChaine=""+chaine.substring(1);
else if (pos1==1) nvChaine=""+chaine.charAt(0);
}
return nvChaine;
}

Présentation Chiheb Ameur ABID 51/ 63 Présentation Chiheb Ameur ABID 52/ 63
Tests automatisés avec le framework JUnit Tests paramétrisés
Le framework JUnit 5

Tests automatisés avec le framework JUnit 5 Plan

Exemple du TDD avec JUnit 5


➥ Le test de la 6ème condition provoque une erreur ! ! !
1 Définitions et concepts de base
➥ Modifions le code applicatif pour corriger l’erreur
public String removeLetterA(String chaine) { 2 Tests automatisés avec le framework JUnit
String nvChaine="";
int pos=-1;
if (chaine.length()>2) {
pos=chaine.indexOf(’A’);
3 Tests paramétrisés
if (pos==0 && chaine.charAt(1)==’A’)
nvChaine=""+chaine.substring(2);
else if (pos==1) nvChaine=chaine.charAt(0)+chaine.substring(2); 4 Bonnes pratiques
else nvChaine=chaine;
}
else if (chaine.length()==2) {
pos=chaine.indexOf(’A’);
if (pos==0) nvChaine=""+chaine.substring(1);
else if (pos==1) nvChaine=""+chaine.charAt(0);
}
return nvChaine;
}
Présentation Chiheb Ameur ABID 53/ 63 Présentation Chiheb Ameur ABID 54/ 63
Tests paramétrisés Tests paramétrisés

Tests paramétrisés Tests paramétrisés

Tests paramétrisés
Exemple : un seul argument
➥ Junit 5 permet les tests paramétrisés en utilisant des différentes valeurs pour la même
méthode de test ➥ Soit à tester la méthode suivante
➥ Un test paramétrisé est exécuté autant de fois que les valeurs spécifiées sur ses entrées public static boolean isOdd(int number) {
return number % 2 != 0;
➥ L’annotation @ParameterizedTest, du package org.junit.jupiter.params, }

est utilisée pour indiquer qu’un test est paramétrisé


➥ Code de la méthode de test
➥ L’annotation @ValueSource, du package
@ParameterizedTest
org.junit.jupiter.params.provider, permet de spécifier les valeurs sur les @ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE})
entrées void testOddShouldReturnTrueForOddNumbers(int number) {
assertTrue(Operations.isOdd(number));
➥ Les types acceptés }

short , byte ,int , long , float , double ,char ,


java.lang.String

Présentation Chiheb Ameur ABID 55/ 63 Présentation Chiheb Ameur ABID 56/ 63
Tests paramétrisés Tests paramétrisés

Tests paramétrisés Tests paramétrisés

Données à partir d’un fichier


Plusieurs arguments
➥ L’annotation @CsvFileSource permet de spécifier des données au format CSV à partir
➥ L’annotation @CsvSource permet de spécifier des données au format CSV d’un fichier
➥ La conversion est effectué systématiquement à partir de type String ➥ La première ligne du fichier csv doit contenir le nom des arguments

Exemple : plusieurs arguments Exemple : données à partir d’un fichier


➥ La méthode à tester ➥ Code de la méthode de test
public static int somme(int a, int b, int c) {
@ParameterizedTest
return a+b+c;
@CsvFileSource(resources = "./test.csv", numLinesToSkip = 1)
}
void testSommeShouldReturnSumofNumbersfromFile(int a,int b,int c) {
assertEquals(a+b+c,Operations.somme(a,b,c));
}
➥ Code de la méthode de test
@ParameterizedTest
@CsvSource({"1,2,3"," 3, 5, -3", "15, 10,0"})
➥ Exemple de contenu du fichier test.csv
void testSommeShouldReturnSumofNumbers(int a,int b,int c) { a,b,c
assertEquals(a+b+c,Operations.somme(a,b,c));
} 1,2,3
4,5,6
7,8,9
Présentation Chiheb Ameur ABID 57/ 63 Présentation Chiheb Ameur ABID 58/ 63
Tests paramétrisés Bonnes pratiques

Tests paramétrisés Plan

1 Définitions et concepts de base

2 Tests automatisés avec le framework JUnit


Exercice : données à partir d’un fichier
➥ Ré-écrire la classe de test de l’exemple 3 (test de la méthode RemoveAFirst) pour
3 Tests paramétrisés
utiliser une seule méthode de test paramétrisée, dont les entrées sont spécifiées à partir
d’un fichier csv.
4 Bonnes pratiques

Présentation Chiheb Ameur ABID 59/ 63 Présentation Chiheb Ameur ABID 60/ 63
Bonnes pratiques Bonnes pratiques

Bonnes pratiques Bonnes pratiques

Qualité d’un bon test


Nommer les tests
➥ Précis
➥ Pour les classes
Z Teste un comportement en particulier
Z Suffixer avec “Test”
Z Un test = une assertion
➥ Pour les méthodes
➥ Répétable et déterministe
Z Décrire le contexte et le résultat attendu
Z S’attend toujours au même comportement
Z Approche Sujet_Scénario_Résultat
➥ Isolé et indépendant
ProductPurchaseAction_IfStockIsZero_RendersOutOfStockView()
Z Ne dépend de rien d’autre
Présentation Chiheb Ameur ABID 61/ 63 Présentation Chiheb Ameur ABID 62/ 63
Bonnes pratiques Bonnes pratiques

Bonnes pratiques
Exercice : jeu de Tic-Tac-Toe (suite)
➥ En continuant l’exercice, on souhaite maintenant alterner le jeu entre les deux joueurs
symbolisés par les types de leurs pions (les caractères ’X’ et ’O’). On suppose toujours que
le joueur X commence le jeu. En suivant une démarche de TDD, implémenter une fonction
permettant de retourner le joueur qui va joueur à un moment donné
Tester les exceptions
Z D’abord, écrire un test pour vérifier que le joueur X commence le jeu
➥ Lister les exceptions qui doivent être levées Z Puis, écrire un deuxième test pour vérifier l’alternance entre les deux joueurs
➥ Écrire un test pour chaque exception ➥ Développer la fonctionnalité pour déterminer le vainqueur
➥ Vérifier que l’exception est bien levée et que le message est clair, compréhensible Z Définir un test qui vérifie que le jeu est en cours. La méthode play retourne l’état du
jeu à travers une chaine de caractères
Z Définir les tests pour la vérification qu’un joueur gagne. On procède en écrivant un
Ne jamais faire confiance au client de vos services test pour chaque type de condition pour annoncer le vainqueur :
➥ Le client utilise mal vos services ❶ Tous les pions sont placés sur la même ligne horizontale. Après avoir proposé une
Z Mauvais inputs, valeurs limites, arguments nuls, valeurs inattendues solution simple, ne pas oublier de réusiner le code
Z Comportements limites, pop() sur une collection vide ❷ Tous les pions sont placés sur la même ligne verticale
❸ Tous les pions sont placés sur la première diagonale
❹ Tous les pions sont placés sur la deuxième diagonale
➥ Développer la fonctionnalité qui annonce que le jeu se termine sans vainqueur. La grille
doit être initialisée.

Présentation Chiheb Ameur ABID 63/ 63


Bonnes pratiques

M ERCI POUR VOTRE ATTENTION

Questions ?

Vous aimerez peut-être aussi