Cours Junit PDF
Document Details
Uploaded by IrreplaceableFern864
ENIS
Dr. Mariam LAHAMI
Tags
Summary
This document is a presentation on JUnit, a testing framework for Java (based on the information and the title in the sample). The information presented includes the history, use-cases, and specific features like annotations, architectures and use-cases.
Full Transcript
Les tests unitaires avec JUnit Responsable du cours: Dr. Mariam LAHAMI 1 Cours Test et qualité de logiciels 04/10/2024 Les tests unitaires Les tests unitaires sont des tests permettant de tester de toutes petites unités d’un logiciel. Ils sont notamment...
Les tests unitaires avec JUnit Responsable du cours: Dr. Mariam LAHAMI 1 Cours Test et qualité de logiciels 04/10/2024 Les tests unitaires 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 ; il 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. 2 Cours Test et qualité de logiciels 04/10/2024 C’est quoi JUnit ? C’est un environnement de test permettant de décrire et d’exécuter des tests unitaires sur une application Java (https://junit.org/junit5/) En Java, unité = méthode D’autres environnements de test existent selon le langage de programmation CUnit pour le C CppUnit pour le C++ PyUnit pour le Python JsUnit pour le JavaScript, etc. 3 Cours Test et qualité de logiciels 04/10/2024 JUnit framework(1/2) JUnit est utilisé pour tester des programmes et des classes Java: Au niveau des méthodes et des classes Pendant le développement du programme En utilisant des assertions JUnit définit trois notions principales : Un « TestCase » est typiquement une classe de test. Une « TestSuite » est un ensemble de tests Un « TestRunner » permet de lancer l'exécution d'une liste de Tests 4 Cours Test et qualité de logiciels 04/10/2024 JUnit framework(2/2) JUnit est intégré dans l’IDE Eclipse mais il peut être utilisé indépendamment La version courante de JUnit est la version 5.9.1 pour Java 8 et supérieure Appelé JUnit Jupiter apparu en 2017 C’est une évolution de JUnit 4 S’adapte aux styles de codage de Java 8 La version Jupiter Intégré à partir de Eclipse Oxygen4.7 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) 5 Cours Test et qualité de logiciels 04/10/2024 Architecture JUnit 5 (1/2) 6 Cours Test et qualité de logiciels 04/10/2024 Architecture JUnit 5 (2/2) Platform: permettant de démarrer des tests dans la JVM tout en offrant une API permettant le démarage des tests via la console ou bien un IDE Jupiter:c’est la combinaison du nouveau modèle de programmation et le modèle permettant de rédiger des tests Vintage: c’est un engine pour exécuter les anciens tests écrits en JUnit 3 ou JUnit 4 7 Cours Test et qualité de logiciels 04/10/2024 Les annotations JUnit 4 vs JUnit 5 (1/3) Définition JUnit 4 JUnit 5 méthode de test @Test @Test méthode exécutée avant toutes les méthodes @BeforeClass @BeforeAll de test méthode exécutée après toutes les méthode @AfterClass @AfterAll de test méthode exécutée avant chaque test @Before @BeforeEach méthode exécutée après chaque test @After @AfterEach méthode qui ne sera pas lancée comme test @Ignore @Disabled méthode de test qui sera répétée N/A @RepeatedTest méthode de test paramétrée N/A @ParameterizedTest définir un libellé pour la classe ou la méthode N/A @DisplayName de test 8 Cours Test et qualité de logiciels 04/10/2024 Les annotations JUnit 4 vs JUnit 5 (2/3) import static org.junit.Assert.*; import org.junit.After; import org.junit.Before; import org.junit.Test; public class TestCompte { @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void Solde() { fail("Not yet implemented"); } } 9 Cours Test et qualité de logiciels 04/10/2024 Les annotations JUnit 4 vs JUnit 5 (3/3) import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class TestCompte { @BeforeEach void setUp() throws Exception { } @AfterEach void tearDown() throws Exception { } @Test void test() { Maintenant avec JUnit 5, ni les fail("Not yet implemented"); } classes ni les méthodes de tests n'ont l'obligation d'être public } 10 Cours Test et qualité de logiciels 04/10/2024 Les assertions (1/5) JUnit utilise les assertions pour écrire des tests: assertEquals(a,b) et assertNotEquals(a,b): teste si a est égal à b resp. a est différent à b (a et b sont soit des valeurs primitives, soit des objets possédant une méthode equals) assertTrue(a) et assertFalse(a): testent si a est vrai resp. faux, avec a une expression booléenne assertSame(a,b) et assertNotSame(a,b): testent si a et b référent au même objet ou non. assertNull(a) et assertNotNull(a): testent si l’objet a est nul ou non fail (message): provoque l’échec de test (levée d’exception) 11 Cours Test et qualité de logiciels 04/10/2024 Les assertions (2/5) Les assertions qui font des comparaisons attendent au moins deux paramètres qui sont dans l'ordre : la valeur attendue et la valeur actuelle. Avec JUnit 4, ces assertions sont importés du package : org.junit.Assert Avec JUnit 5, ces assertions sont importés du package : org.junit.jupiter.Assertions Des nouvelles assertions existent assertAll() pour regrouper différentes assertions qui seront toutes exécutées pour au final fournir la liste de celles en échec si au moins une échoue assertThrows() pour vérifier la lever d'une exception durant le test 12 Cours Test et qualité de logiciels 04/10/2024 Les assertions (3/5) Exemples d’utilisation des assertions //Test will pass Assertions.assertNotEquals(3, Calculator.add(2, 2)); //Test will pass Assertions.assertArrayEquals(new int[]{1,2,3}, new int[]{1,2,3}, "Array Equal Test"); //Test will fail because element order is different Assertions.assertArrayEquals(new int[]{1,2,3}, new int[]{1,3,2}, "Array Equal Test"); //Test will fail because number of elements are different Assertions.assertArrayEquals(new int[]{1,2,3}, new int[]{1,2,3,4}, "Array Equal Test") 13 Cours Test et qualité de logiciels 04/10/2024 Les assertions (4/5) // In a grouped assertion all assertions are executed, and all // failures will be reported together. assertAll("person", () -> assertEquals("Jane", person.getFirstName()), () -> assertEquals("Doe", person.getLastName()) ); //This will pass Assertions.assertTimeout(Duration.ofMinutes(1), () -> { return "result"; }); //This will fail Assertions.assertTimeout(Duration.ofMillis(100), () -> { Thread.sleep(200); return "result"; }); 14 Cours Test et qualité de logiciels 04/10/2024 Les assertions (5/5) //This will pass assertThrows(NumberFormatException.class, () -> { Integer.parseInt("One"); }); Soit les listes suivantes : Iterable listOne = new ArrayList(Arrays.asList(1,2,3,4)); Iterable listTwo = new ArrayList(Arrays.asList(1,2,3,4)); Iterable listThree = new ArrayList(Arrays.asList(1,2,3)); //Test will pass assertIterableEquals(listOne, listTwo); //Test will fail assertIterableEquals(listOne, listThree); 15 Cours Test et qualité de logiciels 04/10/2024 Cycle de vie des tests (1/2) Pour chaque classe Foo.java, vous devez créer une classe FooTest.java Dans la classe de test FooTest.java, définir les méthodes de test le constructeur qui initialise le nom de la suite de tests Une méthode d’initialisation qui sera appelée avant chaque test setUp() (utilisation de l’annotation @BeforeEach) Une méthode de terminaison qui sera appelée après chaque test tearDown() (utilisation de l’annotation @AfterEach) Une ou plusieurs méthodes qui implémentent les tests unitaires (utilisation de l’annotation @Test) 16 Cours Test et qualité de logiciels 04/10/2024 Cycle de vie des tests (2/2) Ordre d’exécution 1. La méthode annotée @BeforeAll 2. Pour chaque méthode annotée @Test (ordre indéterminé). Les méthodes annotées @BeforeEach La méthode annotée @Test Les méthodes annotées @AfterEach 3. La méthode annotée @AfterAll 17 Cours Test et qualité de logiciels 04/10/2024 Développement des tests (1/7) Créer un projet Java, HelloTest Créer une classe Java, HelloMessage.class dans un package appelé main Créer une classe de test TestHello.java dans un package appelé test 18 Cours Test et qualité de logiciels 04/10/2024 Développement des tests (2/7) Afin de rédiger les tests unitaires avec JUnit Nous utilisons une version de l’IDE ECLIPSE 19 Cours Test et qualité de logiciels 04/10/2024 Développement des tests(3/7) Nous utilisons la version de JUnit Jupiter 20 Cours Test et qualité de logiciels 04/10/2024 Développement des tests(4/7) Il faut ajouter la bibliothèque JUnit (.jar) au classpath du projet 21 Cours Test et qualité de logiciels 04/10/2024 Développement des tests(5/7) Code de la classe de Test généré automatiquement par l’IDE 22 Cours Test et qualité de logiciels 04/10/2024 Développement des tests(6/7) Pour exécuter les tests éléborés, on fait appel au TestRunner du Framework JUnit 23 Cours Test et qualité de logiciels 04/10/2024 Développement des tests(7/7) Succès du Test Echec du Test 24 Cours Test et qualité de logiciels 04/10/2024 Exemple HelloJUnit5 (1/2) Classe Sous Test (Class Under Test) public class HelloMessage { public String getMessage() { return "Hello Junit 5"; } } 25 Cours Test et qualité de logiciels 04/10/2024 Exemple HelloJUnit5 (2/2) Classe de test Hi before tests public class TestHelloMessage { Hi test HelloMessage h; Test running1 @BeforeAll Bye test static void setUpBeforeClass() throws Exception { Hi after tests System.out.println("Hi before tests");} @AfterAll static void tearDownAfterClass() throws Exception { System.out.println("Hi after tests");} @BeforeEach void setUp() throws Exception {System.out.println("Hi test"); h=new HelloMessage();} @AfterEach void tearDown() throws Exception { System.out.println("Bye test"); h=null;} @Test void testGetMessage1() { System.out.println("Test running1"); assertEquals("Hello 26 Junit 4",Cours h.getMessage()); Test et qualité de logiciels 04/10/2024 } Exemple d’initiation 1: La classe sous test class Compte { private int cin; private int s; public Compte( int c, int soldeInit ) { cin = c; s = soldeInit; } public int solde() { return( s ); } public int client() { return( cin ); } public void deposer( int montant ) { s += montant; } public void retirer( int montant ) { s += montant; } } 27 Cours Test et qualité de logiciels 04/10/2024 Exemple d’initiation 1: la classe de test @Test void testdeposer() { ---------------------------------- ---------------------------------- class TestCompte { ---------------------------------- Compte c; } @Test @BeforeEach void testretirer() { void setUp() throws Exception { ---------------------------------- ----------------------------- ---------------------------------- } ---------------------------------- @AfterEach } void tearDown() throws Exception @Test { void testsolde() { ----------------------------- ---------------------------------- } ---------------------------------- ---------------------------------- } } 28 Cours Test et qualité de logiciels 04/10/2024 Exemple d’initiation 2 La classe sous test La classe de test public class Calculator { public int evaluate(String expression) { int sum = 0; for (String summand: expression.split("\\+")) sum += Integer.valueOf(summand); return sum; } } 29 Cours Test et qualité de logiciels 04/10/2024 Nouveautés avec JUnit 5 (1/5) On peut désactiver un test avec l’annotation @Disabled @Test @Disabled("for demonstration purposes") void skippedTest() { // not executed } On peut créer un test paramétrable avec l’annotation @ParameterizedTest @ParameterizedTest @ValueSource(strings = {"100+100" , "10*10+100"}) void testevaluatewithparam(String ch) { int sum = cal.evaluate(ch); assertEquals(200, sum); } 30 Cours Test et qualité de logiciels 04/10/2024 Nouveautés avec JUnit 5(2/5) L’annotation @ValueSource permet d’offrir une source d’arguments qui vont être passés en paramètres L’annotation @ValueSource supporte plusieurs types (short, int, long float, double, char, java.lang.String, java.lang.Class) @ValueSource(ints = { 2016, 2020, 2048 }) On peut utiliser aussi @EnumSource @ParameterizedTest @EnumSource(Job.class) public enum Job { void testjob(Job j) { p.setJob(j); teacher, student, assertEquals(j, p.getJob()); engineer; } } 31 Cours Test et qualité de logiciels 04/10/2024 Nouveautés avec JUnit 5 (3/5) On peut passer plusieurs paramètres en utilisant @CsvSource @ParameterizedTest @CsvSource({"1,1,2","5,-1,4"}) void testadd(int a, int b, int s) { assertEquals(s, cal.add(a, b)); } 32 Cours Test et qualité de logiciels 04/10/2024 Nouveautés avec JUnit 5 (4/5) On peut passer plusieurs paramètres en utilisant @CsvFileSource @DisplayName("Addition") @ParameterizedTest @CsvFileSource(resources = "/addition.csv") void testAdditionner(int a, int b, int s) { assertEquals(s, cal.add(a, b)); } 33 Cours Test et qualité de logiciels 04/10/2024 Nouveautés avec JUnit 5 (5/5) @RepeatedTest @DisplayName ("Testcase for Multiplication") @RepeatedTest (5) void testrepeatedmultiply () { int a, b; a=10; b=20; assertEquals(200, (a*b), "Matched. Test status - Passed"); } } 34 Cours Test et qualité de logiciels 04/10/2024 Application (1/2) Q1: Pour la classe Calculator, ajouter des méthodes int add(int a, int b) int multiply(int a, int b) int substract(int a, int b) int divide (int a, int b) Q2 : Ajouter une méthode de test appelée GroupedTest dans la quelle on utilise l’assertion assertAll Q3 : Ajouter une méthode de test renvoyant un succès lorsque la division par zéro aura lieu 35 Cours Test et qualité de logiciels 04/10/2024 Application(2/2) Q4: Créer un test qui se répète 10 fois testant la méthode add 36 Cours Test et qualité de logiciels 04/10/2024 Tests suites with JUnit (1/3) Rappel : une suite de test est un ensemble de cas de tests définis dans différents classes de test @Suite @SelectPackages("test") class TestSuite { } @SelectPackages : spécifier le(s) package(s) contenant les classes de test Dans le cas de plusieurs packages : @SelectPackages({"test1", "test2"}) 37 Cours Test et qualité de logiciels 04/10/2024 Tests suites with JUnit (2/3) @SelectClasses : spécifier la(s) classe(s) de test à exécuter @Suite @SelectClasses( ClassATest.class ) public class JUnit5TestSuiteExample { } @Suite @SelectClasses( { ClassATest.class, ClassBTest.class} ) public class JUnit5TestSuiteExample { } 38 Cours Test et qualité de logiciels 04/10/2024 Tests suites with JUnit (3/3) Pour pouvoir utiliser l’annotation @Suite, nous devons ajouter au classpath du projet les jars de junit-platform-suite-engine Télécharger les jars de ce lien https://jar-download.com/artifacts/org.junit.platform/junit- platform-suite-engine https://howtodoinjava.com/junit5/junit5-test-suites-examples/ 39 Cours Test et qualité de logiciels 04/10/2024 Timeout avec JUnit 5 class TimeoutDemo { @BeforeEach @Timeout(5) void setUp() { // fails if execution time exceeds 5 seconds } @Test @Timeout(value = 100, unit = TimeUnit.MILLISECONDS) void failsIfExecutionTimeExceeds100Milliseconds() { // fails if execution time exceeds 100 milliseconds } } 40 Cours Test et qualité de logiciels 04/10/2024 Exécution des tests conditionnelle Selon le système d’exploitation : activer/ désactiver l’exécution des test selon le SE @TestOnMac void testOnMac() { //... } @Test @EnabledOnOs({ LINUX, MAC }) void onLinuxOrMac() { //... } @Test @DisabledOnOs(WINDOWS) void notOnWindows() { //... } Selon le type JRE installé @Test @EnabledOnJre({ JAVA_9, JAVA_10 }) void onJava9Or10() { //... } @Test @DisabledOnJre(JAVA_9) void notOnJava9() { //... } 41 Cours Test et qualité de logiciels 04/10/2024 Ordre des tests @TestMethodOrder(value = OrderAnnotation.class) class OrderedTest { @Test @Order(4) void test1() {fail("test 1Not yet implemented");} @Test @Order(3) void test2() {fail(" test 2 Not yet implemented");} @Test @Order(2) void test3() {fail(" test 3 Not yet implemented");} @Test @Order(1) void test4() {fail(" test 4 Not yet implemented"); }} 42 Cours Test et qualité de logiciels 04/10/2024 Lien du guide JUnit 5 https://junit.org/junit5/docs/current/user-guide/#overview 43 Cours Test et qualité de logiciels 04/10/2024 Couverture du code Couverture du code (Eng. code coverage) est une mesure utilisée en génie logiciel pour décrire le taux de code source testé d'un programme. But: mesurer la qualité des tests effectués. Plusieurs outils existent : Pour Java : EclEmma plugin Eclipse, Corbertura Etc. 44 Cours Test et qualité de logiciels 04/10/2024 Couverture du code avec EclEmma (1/2) Installer ce plugin via Eclipse Marketplace 45 Cours Test et qualité de logiciels 04/10/2024 Couverture du code avec EclEmma (2/2) Tester l’exemple 1 avec l’outil de couverture Le code en Vert est couvert Le code en rouge n’est pas couvert Le code en jaune est partiellement couvert 46 Cours Test et qualité de logiciels 04/10/2024 Conclusion JUnit 5 apporte des fonctionnalités intéressantes : une nouvelle architecture plus modulaire pour séparer l’API, le moteur d’exécution et les fonctionnalités d’exécution et d’intégration le support de Java 8 (les expressions Lambdas, les annotations répétées, …) le mécanisme d’extension de nouveaux types de tests : tests imbriqués, tests dynamiques, tests paramétrés (avec différentes sources) comme il permet une compatibilité d’exécution avec JUnit 4, la migration vers la version 5 peut se faire en douceur 47 Cours Test et qualité de logiciels 04/10/2024 Application Soit la classe suivante public class LeapYear { boolean isLeapyear(int year) { if (year%400==0) return true; if(year%100==0) return false; return (year%4==0)?true:false; } } Développer sa classe de test et vérifier sa couverture avec l’outil de couverture 48 Cours Test et qualité de logiciels 04/10/2024