Développer des tests unitaires en Java
Le Test Unitaire (TU) est un programme dédié spécifiquement à la validation du bon fonctionnement de ton application/librairie/API. Comme son nom l'indique, il a vocation à valider des unités simples et bien définies du logiciel qui correspondent, très souvent, en programmation orientée objet, à des méthodes. Pour les parties plus complexes du logiciel, mettant en jeu plusieurs classes ou nécessitant, par exemple, l'interaction avec des programmes externes (ex: BD, API JSON, etc ...), on écrira plutôt des tests d'intégration.
N'oublie pas également que le "bon fonctionnement" est une notion qui peut être relative voire subjective, mais qui doit avant tout couvrir le fonctionnement décrit par la demande client (spécifications, cahier des charges, etc ...), sans oublier les cas d'erreurs éventuels. En effet, les TU permettent également de valider le comportement du programme pour les scénarios à la marge, les cas d'erreurs . Par exemple, que se passe-t-il si un paramètre est null?

Ressources
Objectifs
-
Savoir définir les dépendances nécessaires au développement de tests unitaires sous Java
-
Prendre en main l'API JUnit 5 pour l'écriture de tests unitaires
Librairie JUnit
Pour pouvoir écrire des tests unitaires, on utilise généralement une librairie dédiée, qui fournit tous les éléments de base nécessaires pour lancer et valider des TU. En java, la librairie JUnit est la librairie utilisée la plupart du temps même s'il en existe d'autre comme TestNG.
La librairie JUnit suit le standard xUnit.
Pour avoir un projet Maven prêt à l'emploi utilisant JUnit 5, il te faudra cloner le repository suivant : https://github.com/WildCodeSchool/maven-junit5-project
On remarque la présence du dossier maven standard src/main/java qui contient un package fr.wildcodeschool. Nous pourrons y placer le code métier.
De même, il existe un dossier également standard src/test/java où iront nos tests unitaires.
Version de JUnit
Un changement majeur a eu lieu entre la version JUnit 4 et JUnit 5 (nom de code Jupiter) Le repository est déjà bien configuré pour la dernière version, mais il est important de garder ça à l'esprit. Les packages ont même changé d'une version à l'autre.
Find the bug!
Tu es maintenant face au code suivant sur lequel un bug a été détecté en production 💥. Ton objectif est non seulement de trouver ce bug mais également d'assurer la non-régression de ta correction. Assure-toi que ta modification ne casse pas le contrat de base de cette méthode mais également que ta correction sera toujours validée par un test dans le futur.
package fr.wildcodeschool.unittesting;
public class StringUtils {
private static final String ALL_VOWELS = "aeiouyAEIOUY";
/**
* Renvoie la chaine formée par les voyelles d'une chaine de caractères
* @return Chaine avec uniquement des voyelles
*/
public static String vowels(String candidate) {
String vowels = "";
char[] letters = candidate.toCharArray();
for (int i = 1; i < candidate.length(); i++) {
if (ALL_VOWELS.indexOf(letters[i]) >= 0) {
vowels += letters[i];
}
}
return vowels;
}
}
-
Ajoute la classe précédente dans le package
fr.wildcodeschool.unittestingde ton projet -
Crée une classe de test avec deux méthodes de test permettant de relever deux problèmes dans ce code :
-
Un cas non passant : la méthode vowels ne remplit son contrat dans tous les cas. Essaie différents jeux de tests pour trouver le souci.
-
Un cas d'exception : la méthode vowels lève une exception dans le cas où le paramètre en entrée n'est pas défini.
-
Assure toi que ces deux tests échouent.
-
-
Corrige la méthode pour faire passer ces deux tests
-
Crée le cas de test qui s'assure que le contrat de base de cette méthode est toujours respecté suite à ta correction (retour de la chaine de voyelles)
TDD
La méthodologie TDD ou Test Driven Development est une technique de développement qui consiste à développer en écrivant les tests unitaires avant d'écrire le code source que ceux-ci testent.
En plus de produire des tests qui permettront de valider la conformité des développements avec les spécifications, le cahier des charges ou tout autre forme de définition des besoins, cette technique permet également de s'assurer que le design de ton api est réutilisable dans un contexte différent de celui de ton logiciel.
En effet, le fait même d'écrire un test va permettre de définir un nouveau contexte d'utilisation de ton code, et va donc te forcer à t'assurer qu'il n'est pas trop fortement couplé avec l'environnement de ton application/librairie. Autrement dit, qu'il ne dépend pas de trop nombreuses classes/modules liés à ton contexte applicatif (par exemple une requête http dans le cas d'une application web) pour être réutilisable dans d'autres. Le test exerce donc en quelque sorte une nouvelle contrainte d'utilisation pour ton code, qui peut te permettre de mieux le penser, mieux le concevoir. C'est donc aussi un outil d'aide à la conception.

Challenge
Définir des tests pertinents
Ajoute à présent la méthode uniqueVowels, qui comme la méthode vowels, va renvoyer les voyelles d'une chaine, mais cette fois-ci sans doublon.
Définis au moins trois cas de tests qui te semblent essentiels pour valider cette méthode. Ces tests couvrent des scénarios différents et s'assurent du bon fonctionnement de cette méthode.
Écris les tests un à un, en commençant par les faire échouer puis en écrivant le code qui permettra de les faire passer.
Critères de validation
-
Le code est accessible sur GitHub
-
Un test valide le cas avec de multiples occurrences d'une même voyelle
-
Un test valide le cas sans voyelle