Test unitaire
• Les tests sont une partie intégrante des cycles de vie en génie logiciel. En effet,
dans la plupart des méthodologies de développement logiciel, les tests sont
effectués à différentes étapes du cycle de vie du logiciel. Ainsi, on peut avoir des
tests unitaires, d'intégration, de système et de validation, chacun ayant un
objectif spécifique dans le processus de test global.
• Dans les méthodologies de développement Agile, les tests sont effectués tout au
long du cycle de vie, souvent dès le début du développement. Les tests sont
réalisés à chaque itération du processus de développement, ce qui permet une
détection précoce des erreurs et une correction rapide.
Test unitaire
• Les tests unitaires sont des tests permettant de tester de toutes petites unités
d’un logiciel. Ils sont notamment dédiés à des tests de méthodes.
• Les tests unitaires doivent être lancés aussi souvent que possibles, notamment à
chaque modification du code source ; ils faut donc qu’ils soient exécutables
automatiquement. Ils sont donc écrits dans le même langage de programmation
que le logiciel.
• Comme les tests unitaires doivent être exécutés fréquemment, ils doivent être
rapides, et notamment sans interaction avec un humain.
Test unitaire
• Un test de non-régression est une méthode de test logiciel qui vise à s'assurer
que des modifications apportées à une application n'ont pas affecté son
fonctionnement ou ses fonctionnalités existantes. L'objectif est de garantir que
le logiciel continue à fonctionner correctement après des modifications ou des
mises à jour, sans régressions.
• Les tests de non-régression sont particulièrement importants dans les projets
de développement logiciel, car ils permettent de s'assurer que les changements
apportés à une application ne perturbent pas son fonctionnement existant.
Cela permet d'éviter des régressions qui pourraient causer des problèmes pour
les utilisateurs finaux et des coûts supplémentaires pour l'entreprise en cas de
corrections nécessaires.
Test de non-régression
Le Test Driven Development (TDD) est une méthode de développement logiciel dans
laquelle les tests unitaires sont écrits avant le code de l'application. Le processus se
déroule généralement en trois étapes :
• Écrire un test unitaire qui décrit une fonctionnalité ou un comportement que l'on
souhaite implémenter dans l'application.
• Exécuter le test, qui doit échouer, car le code n'a pas encore été écrit.
• Écrire le code nécessaire pour que le test passe.
• Exécuter le test pour que le test passe.
• On peut procéder à des code refractoring
Test Driven Development (TDD)
Référence : https://junit.org
Javadoc : https://junit.org/junit5/docs/current/api/index.html
Structure de base : 3 blocs :
Junit Platform : le cœur du système ; cadre général permettant d’exécuter des tests
Junit Jupiter : la bibliothèque nécessaire à l’exécution de tests
Junit 5
Junit Vintage : pour exécuter des tests Junit 3 et Junit 4 depuis Junit 5.
Intégration dans les outils de développement
Junit 5 est maintenant pris en charge par les divers IDE
(Eclipse, Netbeans, IntelliJ Idea)
Junit 5 est pris en charge par les outils de build (Maven, Gradle)
JUnit 5 est une réécriture intégrale du framework ayant plusieurs
objectifs :
le support et l'utilisation des nouvelles fonctionnalités de Java 8 : par
exemple, les lambdas peuvent être utilisés dans les assertions
une nouvelle architecture reposant sur plusieurs modules
le support de différents types de tests
un mécanisme d'extension qui permet l'ouverture vers des outils tiers
ou des API
• Structure d’une classe de test
• 1 classe de test = un ensemble de méthodes de test
• 1 classe de test par classe à tester
• 1 méthode de test = 1 cas de test
• 1 cas de test = (description, données d’entrée, résultat attendu)
• Structure d’une méthode de test de base
• méthode d’instance publique
• annotée avec @Test
• ne prend aucun paramètre
• ne renvoie rien
• lève une AssertionError en cas de test échoué
• Conventions
• nom d’une classe de test : NomClasseTestéeTest
• nom d’une méthode de test : testNomMethodeTestee
Structure et conventions
public class Calcul {
public int Add(…){ … }
public int Multiply(…) { … }
public double devide() {…}
}
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
public class CalculTest {
private Calcul calcul;
@BeforeEach
public void setUp() { calcul = new Calcul(); }
@Test
@DisplayName("Test de l'addition")
public void testAdd() {
int result = calcul.Add(2, 3);
assertEquals(5, result, "La méthode Add ne fonctionne pas comme prévu");
}
@Test
@DisplayName("Test de la multiplication")
public void testMultiply() {
int result = calcul.Multiply(2, 3);
assertEquals(6, result, "La méthode Multiply ne fonctionne pas comme prévu"); }
}
Ensemble de méthodes statiques aidant à écrire des tests. Ces méthodes lèvent des
AssertionFailedError (sous-type de AssertionError) en cas d’échec.
Classe Assertions
Structure des différentes méthodes
La plupart de ces méthodes existent sous 3 formats :
• avec les paramètres de base
• avec les paramètres de base et une chaîne de caractères correspondant au
message à afficher en cas d’échec
• avec les paramètres de base et un Supplier<String>, méthode construisant la
chaîne de caractères à afficher en cas d’échec
Egalité Nullité Exceptions
assertEquals() assertNull() assertThrows()
assertNotEquals() assertNotNull()
assertTrue()
assertFalse()
assertSame()
assertNotSame()
Le cycle de vie des tests
JUnit 5 créé une nouvelle instance pour exécuter chaque méthode de tests.
Une classe de test JUnit peut avoir des méthodes annotées pour définir des actions exécutées
durant le cycle de vie des tests. Le cycle de vie d'un test peut être enrichi grâce à quatre
annotations utilisées sur des méthodes pour réaliser des initialisations ou du ménage :
• @BeforeAll : exécutée une seule fois avant l'exécution du premier test de la classe
• @BeforeEach : exécutée avant chaque méthode de tests
• @AfterEach : exécutée après chaque méthode de tests
• @AfterAll : exécutée une seule fois après l'exécution de tous les tests de la classe
Par défaut, une nouvelle instance est créée pour exécuter chaque méthode de tests : il n'y a alors
pas d'instance à utiliser pour invoquer les méthodes @BeforeAll et @AfterAll. Celles-ci doivent
donc être statique.
Dans le cycle de vie des instances de tests, les méthodes de tests sont des méthodes
annotées avec @Test, @ParameterizedTest, @RepeatedTest, @TestFactory ou
@TestTemplate.
Par défaut, JUnit créé une nouvelle instance pour chaque test avant d'exécuter la méthode
concernée. Le but de ce comportement est d'exécuter le test de manière isolée et ainsi
d'éviter les effets de bord liés à l'exécution des autres tests.
Il est possible de modifier ce comportement par défaut en utilisant l'annotation
@org.junit.jupiter.api.TestInstance.
Elle ne possède qu'un seul attribut de type TestInstance.Lifecycle qui est une énumération
possédant deux valeurs :
Le cycle de vie des tests
Valeur Rôle
PER_CLASS
Une seule instance est créée pour tous les tests
d'une même classe
PER_METHOD
Une nouvelle instance est créée pour exécuter
chaque méthode de test. C'est la valeur par
défaut de l'attribut de l'annotation
@TestInstance
public double devide(double x, double y) throws IllegalArgumentException {
if (y == 0) {
throw new IllegalArgumentException("Cannot divide by zero.");
}
return x / y;
}
Tester une exception
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class CalculTest {
private static Calcul calcul;
@BeforeAll
public static void init() {
calcul = new Calcul();
}
@Test
public void testDevide() {
double result = calcul.devide(10, 5);
assertEquals(2, result, 0.001);
}
@Test
public void testDevideByZero() {
assertThrows(IllegalArgumentException.class, () -> {calcul.devide(10, 0);
});
}
}
L'assertion assertAll
L'assertion assertAll permet de regrouper plusieurs assertions qui seront toutes
exécutés. L'assertion assertAll échoue si au moins une des assertions qu'elle
regroupe échoue. Même si une assertion du groupe échoue, toutes les
assertions du groupe seront évaluées.
@Test
void test() {
String s1 = "Hello";
String s2 = "World";
String s3 = "JUnit";
assertAll("Test multiple assertions",
() -> assertEquals("Hello", s1),
() -> assertEquals("World", s2),
() -> assertEquals("JUnit", s3)
);
}
@RepeatedTest permet d'exécuter une même méthode de test plusieurs fois avec les mêmes
arguments ou sans arguments. Cela peut être utile pour différents scénarios de test, par exemple :
• Vérifier que la méthode de test est bien stable et reproductible sur plusieurs exécutions.
• Tester la performance d'une méthode de test en mesurant le temps d'exécution ou le nombre
d'itérations qu'elle peut traiter avant de rencontrer une erreur ou une exception.
• Tester la résilience d'une méthode de test en l'exécutant plusieurs fois avec les mêmes arguments
et en vérifiant qu'elle ne provoque pas d'erreurs ou d'exceptions.
Exécuter plusieurs fois une méthode de test
@RepeatedTest(5)
@DisplayName("Repeated Test Example")
void repeatedTest(TestReporter testReporter) {
int actualResult = 5 + 10;
int expectedResult = 15;
assertEquals(expectedResult, actualResult, "The addition of 5 and 10 should equal 15");
testReporter.publishEntry("The addition of 5 and 10 equals " + actualResult);
}
@RepeatedTest(value = 5, name = "Repeated Test Example {currentRepetition}/{totalRepetitions}")
@DisplayName("Repeated Test Example")
@Tag("tag1")
void repeatedTest(TestInfo testInfo) {
double actualResult = 1 + 2;
double expectedResult = 3;
assertEquals(expectedResult, actualResult, "The addition of 0.1 and 0.2 should equal 0.3");
System.out.println("Test " + testInfo.getDisplayName() + " executed with tags " +
testInfo.getTags());
}
Exécuter plusieurs fois une méthode de test
L'annotation @Tag est utilisée pour marquer une classe ou une méthode de test avec
des tags, qui sont des étiquettes permettant de regrouper les tests en fonction de
leur objectif, de leur portée, de leur niveau de priorité, ou de tout autre critère que
vous pouvez définir.
Les tags peuvent être utilisés pour exécuter une sélection de tests spécifiques ou
pour exclure certains tests lors de l'exécution.
L'annotation @Tag
Par exemple, pour exécuter tous les tests marqués avec le tag integration, vous
pouvez utiliser la commande suivante :
mvn test -Dgroups=tag1
Si vous avez plusieurs tags, vous pouvez les séparer par une virgule :
mvn test -Dgroups=tag1,tag2
Cela exécutera tous les tests associés aux tags integration et smoke.
Notez que pour utiliser l'option -Dgroups, vous devez inclure le plugin Surefire
dans votre projet Maven et définir la propriété groups dans le fichier pom.xml :
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<groups>tag1,tag2</groups>
</configuration>
</plugin>
</plugins>
Les Tests paramétrés @ParameterizedTes
Les tests paramétrés permettent d'exécuter un même test plusieurs fois avec
différentes valeurs qui lui sont passés en paramètres.
La méthode de test doit être annotée @ParameterizedTest. Il est aussi nécessaire de
déclarer une source de données permettant d'obtenir les différentes valeurs à
l'exécution des tests.
Annotation Rôle
@ValueSource
Une source de données simple sous la forme
d'un tableau de chaînes de caractères ou de
primitifs (int, long ou double)
@EnumSource
Une source de données simple sous la forme
d'une énumération
@MethodSource
Une source de données dont les valeurs sont
fournies par une méthode
@CsvSource
Une source de données dont les valeurs sont
fournies sous la forme de chaînes de caractères
dans laquelle chaque argument est séparé par
une virgule
@CsvSourceFile
Une source de données dont les valeurs sont
fournies sous la forme d'un ou plusieurs fichiers
CSV
@ArgumentsSource
Une source de données qui est une méthode
d'une instance de type ArgumentProvider
@ParameterizedTest
@ValueSource(ints = { 1, 2, 3 })
void testParametreAvecValueSource(int valeur) {
assertEquals(valeur + valeur, valeur * 2);
}
@ParameterizedTest
@EnumSource(Month.class)
void testParametreAvecEnumSource(Month mois) {
System.out.println(mois);
Assertions.assertNotNull(mois);
}
@ParameterizedTest
@MethodSource("fournirDonnees")
void testTraiter(int index, String element) {
assertTrue(index > 0);
assertTrue(element.startsWith("elem"));
}
static List<Object[]> fournirDonnees() {
return Arrays.asList(new Object[][] { { 1, "elem1" }, { 2, "elem2" } });
}
@DisplayName("Addition")
@ParameterizedTest()
@CsvSource({ "1, 1", "1, 2", "2, 3" })
void testAdditioner(int a, int b) {
int attendu = a + b;
assertEquals(attendu, a + b);
}
@DisplayName("Addition")
@ParameterizedTest()
@CsvFileSource(resources = "additionner_source.csv")
void testAdditionner(int a, int b) {
int attendu = a + b;
assertEquals(attendu, a + b);
}
Les tests imbriqués
Les tests imbriqués permettent de grouper des cas de test pour renforcer le lien qui
existent entre-eux.
JUnit 5 permet de créer des tests imbriquées (nested tests) en utilisant une
annotation @Nested sur une classe interne. Seules les classes internes non statiques
peuvent être annotées avec @Nested.
public class MyClassTest {
private int valeur = 0;
@BeforeAll
static void initAll() {
System.out.println("BeforeAll");
}
@BeforeEach
void init() {
System.out.println("BeforeEach1");
valeur = 1;
}
@AfterEach
void tearDown() {
System.out.println("AfterEach1");
valeur = 0;
}
@AfterAll
static void tearDownAll() {
System.out.println("AfterAll1");
}
@Test
void simpleTest() {
System.out.println("SimpleTest valeur=" + valeur);
Assertions.assertEquals(1, valeur);
}
@Nested
class MonTestImbrique {
@BeforeEach
void init() {
System.out.println("BeforeEach imbrique");
valeur = 2;
}
@Test
void simpleTestImbrique() {
System.out.println("SimpleTest imbrique valeur=" + valeur);
Assertions.assertEquals(2, valeur);
}
}
}
BeforeAll
BeforeEach1
SimpleTest valeur=1
AfterEach1
BeforeEach1
BeforeEach imbrique
SimpleTest imbrique valeur=2
AfterEach1
AfterAll1
Si un test échoue dans la classe mère qui contient des classes de tests imbriquées,
JUnit ne teste pas automatiquement les classes de tests imbriquées. Les tests
imbriqués ne sont pas exécutés indépendamment des tests de la classe mère.
mvn test -Dtest= MyClassTest#MonTestImbrique

testUnitaire (1).pptx

  • 1.
  • 2.
    • Les testssont une partie intégrante des cycles de vie en génie logiciel. En effet, dans la plupart des méthodologies de développement logiciel, les tests sont effectués à différentes étapes du cycle de vie du logiciel. Ainsi, on peut avoir des tests unitaires, d'intégration, de système et de validation, chacun ayant un objectif spécifique dans le processus de test global. • Dans les méthodologies de développement Agile, les tests sont effectués tout au long du cycle de vie, souvent dès le début du développement. Les tests sont réalisés à chaque itération du processus de développement, ce qui permet une détection précoce des erreurs et une correction rapide. Test unitaire
  • 3.
    • Les testsunitaires sont des tests permettant de tester de toutes petites unités d’un logiciel. Ils sont notamment dédiés à des tests de méthodes. • Les tests unitaires doivent être lancés aussi souvent que possibles, notamment à chaque modification du code source ; ils faut donc qu’ils soient exécutables automatiquement. Ils sont donc écrits dans le même langage de programmation que le logiciel. • Comme les tests unitaires doivent être exécutés fréquemment, ils doivent être rapides, et notamment sans interaction avec un humain. Test unitaire
  • 4.
    • Un testde non-régression est une méthode de test logiciel qui vise à s'assurer que des modifications apportées à une application n'ont pas affecté son fonctionnement ou ses fonctionnalités existantes. L'objectif est de garantir que le logiciel continue à fonctionner correctement après des modifications ou des mises à jour, sans régressions. • Les tests de non-régression sont particulièrement importants dans les projets de développement logiciel, car ils permettent de s'assurer que les changements apportés à une application ne perturbent pas son fonctionnement existant. Cela permet d'éviter des régressions qui pourraient causer des problèmes pour les utilisateurs finaux et des coûts supplémentaires pour l'entreprise en cas de corrections nécessaires. Test de non-régression
  • 5.
    Le Test DrivenDevelopment (TDD) est une méthode de développement logiciel dans laquelle les tests unitaires sont écrits avant le code de l'application. Le processus se déroule généralement en trois étapes : • Écrire un test unitaire qui décrit une fonctionnalité ou un comportement que l'on souhaite implémenter dans l'application. • Exécuter le test, qui doit échouer, car le code n'a pas encore été écrit. • Écrire le code nécessaire pour que le test passe. • Exécuter le test pour que le test passe. • On peut procéder à des code refractoring Test Driven Development (TDD)
  • 7.
    Référence : https://junit.org Javadoc: https://junit.org/junit5/docs/current/api/index.html Structure de base : 3 blocs : Junit Platform : le cœur du système ; cadre général permettant d’exécuter des tests Junit Jupiter : la bibliothèque nécessaire à l’exécution de tests Junit 5 Junit Vintage : pour exécuter des tests Junit 3 et Junit 4 depuis Junit 5. Intégration dans les outils de développement Junit 5 est maintenant pris en charge par les divers IDE (Eclipse, Netbeans, IntelliJ Idea) Junit 5 est pris en charge par les outils de build (Maven, Gradle)
  • 8.
    JUnit 5 estune réécriture intégrale du framework ayant plusieurs objectifs : le support et l'utilisation des nouvelles fonctionnalités de Java 8 : par exemple, les lambdas peuvent être utilisés dans les assertions une nouvelle architecture reposant sur plusieurs modules le support de différents types de tests un mécanisme d'extension qui permet l'ouverture vers des outils tiers ou des API
  • 9.
    • Structure d’uneclasse de test • 1 classe de test = un ensemble de méthodes de test • 1 classe de test par classe à tester • 1 méthode de test = 1 cas de test • 1 cas de test = (description, données d’entrée, résultat attendu) • Structure d’une méthode de test de base • méthode d’instance publique • annotée avec @Test • ne prend aucun paramètre • ne renvoie rien • lève une AssertionError en cas de test échoué • Conventions • nom d’une classe de test : NomClasseTestéeTest • nom d’une méthode de test : testNomMethodeTestee Structure et conventions
  • 10.
    public class Calcul{ public int Add(…){ … } public int Multiply(…) { … } public double devide() {…} }
  • 11.
    import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; importorg.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; public class CalculTest { private Calcul calcul; @BeforeEach public void setUp() { calcul = new Calcul(); } @Test @DisplayName("Test de l'addition") public void testAdd() { int result = calcul.Add(2, 3); assertEquals(5, result, "La méthode Add ne fonctionne pas comme prévu"); } @Test @DisplayName("Test de la multiplication") public void testMultiply() { int result = calcul.Multiply(2, 3); assertEquals(6, result, "La méthode Multiply ne fonctionne pas comme prévu"); } }
  • 12.
    Ensemble de méthodesstatiques aidant à écrire des tests. Ces méthodes lèvent des AssertionFailedError (sous-type de AssertionError) en cas d’échec. Classe Assertions Structure des différentes méthodes La plupart de ces méthodes existent sous 3 formats : • avec les paramètres de base • avec les paramètres de base et une chaîne de caractères correspondant au message à afficher en cas d’échec • avec les paramètres de base et un Supplier<String>, méthode construisant la chaîne de caractères à afficher en cas d’échec
  • 13.
    Egalité Nullité Exceptions assertEquals()assertNull() assertThrows() assertNotEquals() assertNotNull() assertTrue() assertFalse() assertSame() assertNotSame()
  • 14.
    Le cycle devie des tests JUnit 5 créé une nouvelle instance pour exécuter chaque méthode de tests. Une classe de test JUnit peut avoir des méthodes annotées pour définir des actions exécutées durant le cycle de vie des tests. Le cycle de vie d'un test peut être enrichi grâce à quatre annotations utilisées sur des méthodes pour réaliser des initialisations ou du ménage : • @BeforeAll : exécutée une seule fois avant l'exécution du premier test de la classe • @BeforeEach : exécutée avant chaque méthode de tests • @AfterEach : exécutée après chaque méthode de tests • @AfterAll : exécutée une seule fois après l'exécution de tous les tests de la classe Par défaut, une nouvelle instance est créée pour exécuter chaque méthode de tests : il n'y a alors pas d'instance à utiliser pour invoquer les méthodes @BeforeAll et @AfterAll. Celles-ci doivent donc être statique.
  • 15.
    Dans le cyclede vie des instances de tests, les méthodes de tests sont des méthodes annotées avec @Test, @ParameterizedTest, @RepeatedTest, @TestFactory ou @TestTemplate. Par défaut, JUnit créé une nouvelle instance pour chaque test avant d'exécuter la méthode concernée. Le but de ce comportement est d'exécuter le test de manière isolée et ainsi d'éviter les effets de bord liés à l'exécution des autres tests. Il est possible de modifier ce comportement par défaut en utilisant l'annotation @org.junit.jupiter.api.TestInstance. Elle ne possède qu'un seul attribut de type TestInstance.Lifecycle qui est une énumération possédant deux valeurs : Le cycle de vie des tests Valeur Rôle PER_CLASS Une seule instance est créée pour tous les tests d'une même classe PER_METHOD Une nouvelle instance est créée pour exécuter chaque méthode de test. C'est la valeur par défaut de l'attribut de l'annotation @TestInstance
  • 16.
    public double devide(doublex, double y) throws IllegalArgumentException { if (y == 0) { throw new IllegalArgumentException("Cannot divide by zero."); } return x / y; } Tester une exception
  • 17.
    import static org.junit.jupiter.api.Assertions.*; importorg.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; public class CalculTest { private static Calcul calcul; @BeforeAll public static void init() { calcul = new Calcul(); } @Test public void testDevide() { double result = calcul.devide(10, 5); assertEquals(2, result, 0.001); } @Test public void testDevideByZero() { assertThrows(IllegalArgumentException.class, () -> {calcul.devide(10, 0); }); } }
  • 18.
    L'assertion assertAll L'assertion assertAllpermet de regrouper plusieurs assertions qui seront toutes exécutés. L'assertion assertAll échoue si au moins une des assertions qu'elle regroupe échoue. Même si une assertion du groupe échoue, toutes les assertions du groupe seront évaluées. @Test void test() { String s1 = "Hello"; String s2 = "World"; String s3 = "JUnit"; assertAll("Test multiple assertions", () -> assertEquals("Hello", s1), () -> assertEquals("World", s2), () -> assertEquals("JUnit", s3) ); }
  • 19.
    @RepeatedTest permet d'exécuterune même méthode de test plusieurs fois avec les mêmes arguments ou sans arguments. Cela peut être utile pour différents scénarios de test, par exemple : • Vérifier que la méthode de test est bien stable et reproductible sur plusieurs exécutions. • Tester la performance d'une méthode de test en mesurant le temps d'exécution ou le nombre d'itérations qu'elle peut traiter avant de rencontrer une erreur ou une exception. • Tester la résilience d'une méthode de test en l'exécutant plusieurs fois avec les mêmes arguments et en vérifiant qu'elle ne provoque pas d'erreurs ou d'exceptions. Exécuter plusieurs fois une méthode de test @RepeatedTest(5) @DisplayName("Repeated Test Example") void repeatedTest(TestReporter testReporter) { int actualResult = 5 + 10; int expectedResult = 15; assertEquals(expectedResult, actualResult, "The addition of 5 and 10 should equal 15"); testReporter.publishEntry("The addition of 5 and 10 equals " + actualResult); }
  • 20.
    @RepeatedTest(value = 5,name = "Repeated Test Example {currentRepetition}/{totalRepetitions}") @DisplayName("Repeated Test Example") @Tag("tag1") void repeatedTest(TestInfo testInfo) { double actualResult = 1 + 2; double expectedResult = 3; assertEquals(expectedResult, actualResult, "The addition of 0.1 and 0.2 should equal 0.3"); System.out.println("Test " + testInfo.getDisplayName() + " executed with tags " + testInfo.getTags()); } Exécuter plusieurs fois une méthode de test
  • 21.
    L'annotation @Tag estutilisée pour marquer une classe ou une méthode de test avec des tags, qui sont des étiquettes permettant de regrouper les tests en fonction de leur objectif, de leur portée, de leur niveau de priorité, ou de tout autre critère que vous pouvez définir. Les tags peuvent être utilisés pour exécuter une sélection de tests spécifiques ou pour exclure certains tests lors de l'exécution. L'annotation @Tag Par exemple, pour exécuter tous les tests marqués avec le tag integration, vous pouvez utiliser la commande suivante : mvn test -Dgroups=tag1 Si vous avez plusieurs tags, vous pouvez les séparer par une virgule : mvn test -Dgroups=tag1,tag2 Cela exécutera tous les tests associés aux tags integration et smoke.
  • 22.
    Notez que pourutiliser l'option -Dgroups, vous devez inclure le plugin Surefire dans votre projet Maven et définir la propriété groups dans le fichier pom.xml : <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M5</version> <configuration> <groups>tag1,tag2</groups> </configuration> </plugin> </plugins>
  • 23.
    Les Tests paramétrés@ParameterizedTes Les tests paramétrés permettent d'exécuter un même test plusieurs fois avec différentes valeurs qui lui sont passés en paramètres. La méthode de test doit être annotée @ParameterizedTest. Il est aussi nécessaire de déclarer une source de données permettant d'obtenir les différentes valeurs à l'exécution des tests.
  • 24.
    Annotation Rôle @ValueSource Une sourcede données simple sous la forme d'un tableau de chaînes de caractères ou de primitifs (int, long ou double) @EnumSource Une source de données simple sous la forme d'une énumération @MethodSource Une source de données dont les valeurs sont fournies par une méthode @CsvSource Une source de données dont les valeurs sont fournies sous la forme de chaînes de caractères dans laquelle chaque argument est séparé par une virgule @CsvSourceFile Une source de données dont les valeurs sont fournies sous la forme d'un ou plusieurs fichiers CSV @ArgumentsSource Une source de données qui est une méthode d'une instance de type ArgumentProvider
  • 25.
    @ParameterizedTest @ValueSource(ints = {1, 2, 3 }) void testParametreAvecValueSource(int valeur) { assertEquals(valeur + valeur, valeur * 2); } @ParameterizedTest @EnumSource(Month.class) void testParametreAvecEnumSource(Month mois) { System.out.println(mois); Assertions.assertNotNull(mois); } @ParameterizedTest @MethodSource("fournirDonnees") void testTraiter(int index, String element) { assertTrue(index > 0); assertTrue(element.startsWith("elem")); } static List<Object[]> fournirDonnees() { return Arrays.asList(new Object[][] { { 1, "elem1" }, { 2, "elem2" } }); }
  • 26.
    @DisplayName("Addition") @ParameterizedTest() @CsvSource({ "1, 1","1, 2", "2, 3" }) void testAdditioner(int a, int b) { int attendu = a + b; assertEquals(attendu, a + b); } @DisplayName("Addition") @ParameterizedTest() @CsvFileSource(resources = "additionner_source.csv") void testAdditionner(int a, int b) { int attendu = a + b; assertEquals(attendu, a + b); }
  • 27.
    Les tests imbriqués Lestests imbriqués permettent de grouper des cas de test pour renforcer le lien qui existent entre-eux. JUnit 5 permet de créer des tests imbriquées (nested tests) en utilisant une annotation @Nested sur une classe interne. Seules les classes internes non statiques peuvent être annotées avec @Nested.
  • 28.
    public class MyClassTest{ private int valeur = 0; @BeforeAll static void initAll() { System.out.println("BeforeAll"); } @BeforeEach void init() { System.out.println("BeforeEach1"); valeur = 1; } @AfterEach void tearDown() { System.out.println("AfterEach1"); valeur = 0; } @AfterAll static void tearDownAll() { System.out.println("AfterAll1"); } @Test void simpleTest() { System.out.println("SimpleTest valeur=" + valeur); Assertions.assertEquals(1, valeur); } @Nested class MonTestImbrique { @BeforeEach void init() { System.out.println("BeforeEach imbrique"); valeur = 2; } @Test void simpleTestImbrique() { System.out.println("SimpleTest imbrique valeur=" + valeur); Assertions.assertEquals(2, valeur); } } } BeforeAll BeforeEach1 SimpleTest valeur=1 AfterEach1 BeforeEach1 BeforeEach imbrique SimpleTest imbrique valeur=2 AfterEach1 AfterAll1
  • 29.
    Si un testéchoue dans la classe mère qui contient des classes de tests imbriquées, JUnit ne teste pas automatiquement les classes de tests imbriquées. Les tests imbriqués ne sont pas exécutés indépendamment des tests de la classe mère. mvn test -Dtest= MyClassTest#MonTestImbrique