Tests unitaires automatisés avec JUnit4

JUnit

Cet article a pour objectif de présenter ce qu'apporte JUnit4 pour les tests automatisés (annotations, nouvelles assertions, suppositions, tests paramétrés).

Article lu   fois.

L'auteur

HomeViadeoLinkedIn

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. INTRODUCTION

Pour une compréhension aisée de cet article, il est conseillé d'avoir quelques connaissances en Java, JUnit (de version précédente) et Eclipse.

JUnit est un framework de tests unitaires pour Java. Ce framework appartient à l'ensemble des frameworks de tests xUnit. Ce framework a été écrit par Kent Beck (en autre créateur de l'Extreme Programming et du framework de tests SUnit pour Smalltalk, qui a inspiré tous les autres xUnit) et Erich Gamma (entre autre un des quatre auteurs de Design Patterns: Elements of Reusable Object-Oriented Software et concepteur de Java Development Tools, la partie d'Eclipse supportant Java).

Depuis Java 5, d'importantes évolutions ont été apportées à JUnit. Les dernières versions de JUnit ont donc changé de numéro majeur de version pour passer de JUnit 3.x à JUnit 4.x.

Cet article va présenter les particularités que JUnit4 (et plus particulièrement la version 4.5) apporte par rapport à JUnit3 :

  • les annotations pour les tests
  • les nouvelles assertions
  • les suppositions
  • les tests paramétrés
  • les annotations pour les suites de tests

Lors de mes recherches, j'ai remarqué que parfois les imports statiques étaient considérés comme une évolution de JUnit4. Il s'agit cependant d'une évolution entièrement liée à Java5. J'ai tendance à ne pas les utiliser dans l'article, non par conviction anti-"imports statiques" ;-), mais parce que j'ai pensé que ça serait plus lisible dans l'article. Il y a cependant quelques exemples avec des imports statiques.

Pour la réalisation de cet article les versions des outils sont :

II. AUTRES RESSOURCES SUR DEVELOPPEZ.COM

III. LES ANNOTATIONS POUR LES TESTS

Les annotations sont en Java une nouveauté de Java 5. Les annotations de JUnit apportent des fonctionnalités en plus (initialisation globale à l'ensemble des méthodes de tests d'un cas de test) et de la souplesse. Il n'est plus nécessaire que le cas de tests soit une classe héritant de TestCase. Les annotations indiquent le comportement du cas de tests. Toutes les annotations, ci-après, sont apparues à partir de la version 4.0 de JUnit.

III-A. Test simple

La javadoc de cette annotation est disponible ici.

Pour déterminer les méthodes de tests, JUnit3 recherche toutes celles commençant par "test" dans les classes héritant de TestCase. JUnit4, quant à lui, recherche les méthodes avec l'annotation @Test dans n'importe quelle classe.

Operations.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

public class Operations {

    public static long additionner(final long...pNombres) {
        long lRetour = 0;
        for(final long lNombre : pNombres) {
            lRetour += lNombre;
        }
        return lRetour;
    }
    
    // Cette méthode ne fonctionne pas correctement
    // Les tests vont le vérifier 
    public static long multiplier(final long...pNombres) {
        long lRetour = 0;
        for(final long lNombre : pNombres) {
            lRetour *= lNombre;
        }
        return lRetour;
    }
    
}
TestSimple.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.Assert;
import org.junit.Test;

public class TestSimple {

    @Test
    public void additionAvecDeuxNombres() {
        final long lAddition = Operations.additionner(10, 20);
        Assert.assertEquals(30, lAddition);
    }

    @Test
    public void additionAvecCinqNombres() {
        final long lAddition = Operations.additionner(256, 512, 1024, 2048, 4096);
        Assert.assertEquals(7936, lAddition);
    }

    @Test
    public void mutiplicationAvecDeuxNombres() {
        final long lMultiplication = Operations.multiplier(10, 20);
        Assert.assertEquals(300, lMultiplication);
    }
    
    public void testMutiplicationAvecCinqNombres() {
        final long lMultiplication = Operations.additionner(256, 512, 1024, 2048, 4096);
        Assert.assertEquals(1125899906842624L, lMultiplication);
    }
}

Comme le montre la capture d'écran ci-dessous, seules les méthodes de tests avec l'annotation ont été exécutées.

Image non disponible

III-B. Test devant déclencher un Throwable

La javadoc de cette annotation est disponible ici.

Cette annotation permet de vérifier qu'un Throwable a bien été déclenché. L'annotation reçoit la classe du Throwable attendu en paramètre.

Operations.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

public class Operations {

    public static long diviser(final long...pNombres) {
        if(pNombres.length < 2) {
            throw new IllegalArgumentException(
                    "Il faut au moins deux nombres en entrée");
        }
        long lRetour = pNombres[0];
        for(int i=1;i<pNombres.length;i++) {
            lRetour /= pNombres[i];
        }
        return lRetour;
    }
    
}
TestThrowable.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.Test;

public class TestThrowable {

    @Test(expected=IllegalArgumentException.class)
    public void divisionAvecUnNombre() {
        Operations.diviser(1);
    }

    @Test(expected=ArithmeticException.class)
    public void divisionAvecDeuxNombresDontUnZero() {
        Operations.diviser(10, 0);
    }

    @Test(expected=ArithmeticException.class)
    public void divisionAvecDeuxNombres() {
        Operations.diviser(10, 5);
    }
}

Comme le montre la capture d'écran ci-dessous, les deux premières méthodes de test provoquent des Exceptions (la première à cause du contrôle en début de la méthode diviser, la deuxième à cause d'une division par zéro). La dernière ne déclenche pas d'erreur, le test est donc considéré comme échoué.

Image non disponible

III-C. Test d'une durée limitée

La javadoc de cette annotation est disponible ici.

Cette annotation permet de vérifier qu'un test ne dépasse pas une durée. Au delà de cette durée, le test passe en erreur. La durée en millisecondes est passée en paramètre à l'annotation.

TestDureeLimitee.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.Test;

public class TestDureeLimitee {

    @Test(timeout=1000)
    public void dureeRespectee() {
        
    }

    @Test(timeout=1000)
    public void dureeNonRespectee() throws InterruptedException {
        Thread.sleep(10000);
    }
}

Comme le montre la capture d'écran ci-dessous, lorsque la durée d'un test dépasse la durée indiquée, le test passe en erreur.

Image non disponible

III-D. Indisponibilité d'un test

La javadoc de cette annotation est disponible ici.

Cette annotation permet de pas passer un test.

TestIndisponibilite.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;

public class TestIndisponibilite {

    @Test
    public void nonIgnore1() {
        
    }

    @Test
    public void nonIgnore2() {
        Assert.fail("Echec");
    }

    @Ignore
    @Test
    public void ignore() {
        Assert.fail("Echec ignoré");
    }
}

Comme le montre la capture d'écran ci-dessous, le premier test est passé avec succès, le deuxième a échoué et le troisième a été ignoré.

Image non disponible

III-E. Préparation avant et démontage après chaque test d'un cas de test

La javadoc de ces annotations est disponible ici et ici.

Ces annotations permettent d'indiquer une méthode qui sera exécutée avant chaque test et un méthode qui sera exécutée après chaque test.

TestAvantApres.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestAvantApres {

    @Before
    public void avantTest() {
        System.out.println("------------------------");
        System.out.println("Avant Test");
    }
    
    @After
    public void apresTest() {
        System.out.println("Après Test");
        System.out.println("------------------------");
    }
    
    @Test
    public void premierTest() {
        System.out.println("Premier Test");
    }

    @Test
    public void deuxiemeTest() {
        System.out.println("Deuxième Test");
    }

    @Test
    public void troisiemeTest() {
        System.out.println("Troisième Test");
    }
}

Comme le montre la trace ci-dessous, les méthodes avantTest et apresTest sont exécutées avant et après les méthodes de test.

 
Sélectionnez
------------------------
Avant Test
Premier Test
Après Test
------------------------
------------------------
Avant Test
Deuxième Test
Après Test
------------------------
------------------------
Avant Test
Troisième Test
Après Test
------------------------

III-F. Préparation avant et démontage après l'ensemble de tests d'un cas de tests

La javadoc de ces annotations est disponible à l'url : ici et ici.

Ces annotations permettent d'indiquer une méthode qui sera exécutée avant l'ensemble des tests d'un cas de tests et une méthode qui sera exécutée après l'ensemble des tests d'un cas de tests.

TestAvantApresEnsemble.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class TestAvantApresEnsemble {

    @BeforeClass
    public static void avantTests() {
        System.out.println("------------------------");
        System.out.println("Avant Tests");
        System.out.println("------------------------");
    }
    
    @AfterClass
    public static void apresTests() {
        System.out.println("------------------------");
        System.out.println("Après Tests");
        System.out.println("------------------------");
    }
    
    @Test
    public void premierTest() {
        System.out.println("Premier Test");
    }

    @Test
    public void deuxiemeTest() {
        System.out.println("Deuxième Test");
    }

    @Test
    public void troisiemeTest() {
        System.out.println("Troisième Test");
    }
}

Comme le montre la trace ci-dessous, les méthodes avantTests et apresTests sont exécutées avant et après l'ensemble des méthodes de test.

 
Sélectionnez
------------------------
Avant Tests
------------------------
Premier Test
Deuxième Test
Troisième Test
------------------------
Après Tests
------------------------

IV. LES NOUVELLES ASSERTIONS

IV-A. Assertions d'égalité pour les tableaux

Ces assertions comprennent des assertions d'égalité pour les tableaux de :

  • "byte" dont la javadoc est disponible ici et ici.
  • "char" dont la javadoc est disponible ici et ici.
  • "short" dont la javadoc est disponible ici et ici.
  • "int" dont la javadoc est disponible ici et ici.
  • "long" dont la javadoc est disponible ici et ici.
  • "Object" dont la javadoc est disponible ici et ici.

Ces assertions sont présentes dans JUnit depuis la version 4.3.1.

Operations.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import java.util.Arrays;

public class Operations {

    // Cette méthode vérifie que les longueurs passées en paramètre
    // sont celles d'un triangle rectangle
    public static Boolean[] pythagore(final long[]...pLongueurs) {
        final Boolean[] lRetours = new Boolean[pLongueurs.length];

        for(int i=0;i<pLongueurs.length;i++) {
            final long[] lLongeurs = pLongueurs[i];
            if(lLongeurs.length != 3) {
                throw new IllegalArgumentException(
                    "Les blocs de longueurs doivent être de 3 éléments");
            }
            
            final long[] lCopieLongueurs = lLongeurs.clone();
            Arrays.sort(lCopieLongueurs);
            
            final long lLongueur1 = lCopieLongueurs[0] * lCopieLongueurs[0];
            final long lLongueur2 = lCopieLongueurs[1] * lCopieLongueurs[1];
            final long lLongueur3 = lCopieLongueurs[2] * lCopieLongueurs[2];
            
            if(lLongueur1 + lLongueur2 == lLongueur3) {
                lRetours[i] = true;
            }
            else {
                lRetours[i] = false;
            }
        }

        return lRetours;
    }
}
TestTableau.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.Assert;
import org.junit.Test;

public class TestTableau {

    @Test 
    public void tableauAvecMemesValeurs() {
        final Boolean[] lResutat = Operations.pythagore(
                new long[]{3, 4, 5}, 
                new long[]{6, 10, 8}
        );
        Assert.assertArrayEquals(new Boolean[]{true, true}, lResutat);
    }

    @Test 
    public void tableauAvecValeursDifferentes() {
        final Boolean[] lResutat = Operations.pythagore(
                new long[]{3, 4, 6}, 
                new long[]{6, 11, 8}
        );
        Assert.assertArrayEquals(new Boolean[]{true, true}, lResutat);
    }
}

Comme le montre la capture d'écran ci-dessous, l'assertion vérifie que les éléments des tableaux sont égaux.

Image non disponible

IV-B. Assertion d'égalité pour les "double" avec un delta maximal entre les deux valeurs à comparer

La javadoc de cette assertion est disponible ici et ici.

Cette assertion est présente dans JUnit depuis la version 4.4. L'assertion d'égalité pour les doubles sans delta est passé en déprécié à partir de la version 4.5 de JUnit.

Operations.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

public class Operations {
    
    public static double soustraire(final double...pNombres) {
        if(pNombres.length < 2) {
            throw new IllegalArgumentException(
                    "Il faut au moins deux nombres en entrée");
        }
        double lRetour = pNombres[0];
        for(int i=1;i<pNombres.length;i++) {
            lRetour -= pNombres[i];
        }
        return lRetour;
    }
    
}
TestDoubleAvecDelta.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.Assert;
import org.junit.Test;

public class TestDoubleAvecDelta {

    @Test
    public void valeursExactementEgales() {
        final double lResultat = Operations.soustraire(5, 2.5);
        Assert.assertEquals(2.5, lResultat, 0);
    }

    @Test
    public void valeursAvecUneLegereDifference() {
        final double lResultat = Operations.soustraire(71.19, 98);
        Assert.assertEquals(-26.81, lResultat, 0.005);
    }

    @Test
    public void valeursAvecUneDifferenceTropImportante() {
        final double lResultat = Operations.soustraire(71.19, 98);
        Assert.assertEquals(-26.81, lResultat, 0);
    }
}

Comme le montre la capture d'écran ci-dessous, le paramètre delta permet de considérer que l'assertion est juste même s'il y a une différence entre les valeurs, tant que cette différence est inférieure au delta.

Image non disponible

IV-C. Assertion sur une condition définie par contrat

La javadoc de cette assertion est disponible ici et ici.

Cette assertion est présente dans JUnit depuis la version 4.4.

Pour que l'assertion soit juste, il faut que le contrat soit vérifié.

IV-C-1. Contrat "pareil" : IsSame

La javadoc de ce contrat est disponible ici.

Le contrat vérifie que l'instance passée en premier paramètre de l'assertion et celle passée en paramètre du contrat sont les mêmes.

TestContratPareil.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.hamcrest.core.IsSame;
import org.junit.Assert;
import org.junit.Test;

public class TestContratPareil {

    @Test
    public void pareil() {
        // Remarque : c'est la même instance à cause du cache
        Assert.assertThat("texte", IsSame.sameInstance("texte"));
    }

    @Test
    public void pasPareil() {
        // Remarque : ce n'est pas la même instance parce que new String() force une nouvelle instance.
        Assert.assertThat(new String("texte"), IsSame.sameInstance("texte"));
    }
}

Comme le montre la capture d'écran ci-dessous, l'assertion échoue si les instances ne sont pas les mêmes.

Image non disponible

IV-C-2. Contrat "égalité" : IsEqual

La javadoc de ce contrat est disponible ici.

Le contrat vérifie que l'instance passée en premier paramètre de l'assertion et celle passée en paramètre du contrat sont égales.

TestContratEgal.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.hamcrest.core.IsEqual;
import org.junit.Assert;
import org.junit.Test;

public class TestContratEgal {

    @Test
    public void egal1() {
        Assert.assertThat("texte", IsEqual.equalTo("texte"));
    }

    @Test
    public void egal2() {
        Assert.assertThat(new String("texte"), IsEqual.equalTo("texte"));
    }

    @Test
    public void pasEgal1() {
        Assert.assertThat("Texte", IsEqual.equalTo("texte"));
    }

    @Test
    public void pasEgal2() {
        Assert.assertThat(new String("Texte"), IsEqual.equalTo("texte"));
    }
}

Comme le montre la capture d'écran ci-dessous, l'assertion échoue si les instances ne sont pas égales.

Image non disponible

IV-C-3. Contrat "classe de l'instance" : IsInstanceOf

La javadoc de ce contrat est disponible ici.

Le contrat vérifie que l'instance passée en premier paramètre de l'assertion est de la classe passée en paramètre du contrat.

TestContratClasseInstance.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import java.io.Serializable;

import org.hamcrest.core.IsInstanceOf;
import org.junit.Assert;
import org.junit.Test;

public class TestContratClasseInstance {

    @Test
    public void classeDeString() {
        Assert.assertThat("texte", IsInstanceOf.instanceOf(String.class));
    }

    @Test
    public void classeDeSerializable() {
        Assert.assertThat("texte", IsInstanceOf.instanceOf(Serializable.class));
    }

    @Test
    public void classeDeCharSequence() {
        Assert.assertThat("texte", IsInstanceOf.instanceOf(CharSequence.class));
    }

    @Test
    public void classeDeInteger() {
        Assert.assertThat("texte", IsInstanceOf.instanceOf(Integer.class));
    }
}

Comme le montre la capture d'écran ci-dessous, l'assertion échoue si l'instance n'est pas de la bonne classe.

Image non disponible

IV-C-4. Contrat "valeur null" : IsNull

La javadoc de ce contrat est disponible ici.

Le contrat vérifie que la référence passée en premier paramètre de l'assertion est null ou n'est pas null.

TestContratValeurNull.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.hamcrest.core.IsNull;
import org.junit.Assert;
import org.junit.Test;

public class TestContratValeurNull {

    @Test
    public void valeurNull1() {
        final String lTexte = null;
        Assert.assertThat(lTexte, IsNull.nullValue());
    }

    @Test
    public void valeurNull2() {
        final String lTexte = "texte";
        Assert.assertThat(lTexte, IsNull.nullValue());
    }

    @Test
    public void valeurPasNull1() {
        final String lTexte = null;
        Assert.assertThat(lTexte, IsNull.notNullValue());
    }

    @Test
    public void valeurPasNull2() {
        final String lTexte = "texte";
        Assert.assertThat(lTexte, IsNull.notNullValue());
    }
}

Comme le montre la capture d'écran ci-dessous, l'assertion échoue si la référence ne correspond pas au contrat.

Image non disponible

IV-C-5. Contrat "être" : Is

La javadoc de ce contrat est disponible ici.

Le contrat vérifie que l'instance passée en premier paramètre correspond à ce qui est passé (classe, valeur, autre contrat) en paramètre du contrat. Ce contrat n'apporte pas de nouveau type de contrat :

  • si on passe une classe, cela correspond à un contrat "classe de l'instance"
  • si on passe une valeur, cela correspond à un contrat "égalité"
  • si on passe un autre contrat, cela correspond à cet autre contrat
TestContratEtre.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.hamcrest.core.Is;
import org.hamcrest.core.IsSame;
import org.junit.Assert;
import org.junit.Test;

public class TestContratEtre {

    @Test
    public void classeDeString() {
        Assert.assertThat("texte", Is.is(String.class));
    }

    @Test
    public void classeDeInteger() {
        Assert.assertThat("texte", Is.is(Integer.class));
    }

    @Test
    public void egal() {
        Assert.assertThat("texte", Is.is("texte"));
    }

    @Test
    public void pasEgal() {
        Assert.assertThat("Texte", Is.is("texte"));
    }

    @Test
    public void pareil() {
        Assert.assertThat("texte", Is.is(IsSame.sameInstance("texte")));
    }

    @Test
    public void pasPareil() {
        Assert.assertThat(new String("texte"), Is.is(IsSame.sameInstance("texte")));
    }
}

Comme le montre la capture d'écran ci-dessous, l'assertion réussit si l'instance est de la classe passée en paramètre du contrat, si elle est égale à la valeur passée en paramètre du contrat ou si le contrat passé en paramètre du contrat "être" est respecté.

Image non disponible

IV-C-6. Contrat "ne pas être" : IsNot

La javadoc de ce contrat est disponible ici.

Le contrat vérifie que l'instance passée en premier paramètre ne correspond pas à ce qui est passé (valeur ou autre contrat) en paramètre du contrat. Ce contrat n'apporte pas de nouveau type de contrat :

  • si on passe une valeur, cela correspond à un contrat "égalité"
  • si on passe un autre contrat, cela correspond à cet autre contrat
TestContratNePasEtre.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.hamcrest.core.IsNot;
import org.hamcrest.core.IsSame;
import org.junit.Assert;
import org.junit.Test;

public class TestContratNePasEtre {

    @Test
    public void egal() {
        Assert.assertThat("texte", IsNot.not("texte"));
    }

    @Test
    public void pasEgal() {
        Assert.assertThat("Texte", IsNot.not("texte"));
    }

    @Test
    public void pareil() {
        Assert.assertThat("texte", IsNot.not(IsSame.sameInstance("texte")));
    }

    @Test
    public void pasPareil() {
        Assert.assertThat(new String("texte"), IsNot.not(IsSame.sameInstance("texte")));
    }
}

Comme le montre la capture d'écran ci-dessous, l'assertion réussit si l'instance n'est pas égale à la valeur passée en paramètre du contrat ou si le contrat passé en paramètre du contrat "ne pas être" n'est pas respecté.

Image non disponible

IV-C-7. Contrat "tous" : AllOf

La javadoc de ce contrat est disponible ici.

Le contrat vérifie que tous les contrats passés en paramètre du contrat sont respectés.

TestContratTous.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.hamcrest.core.AllOf;
import org.hamcrest.core.IsEqual;
import org.hamcrest.core.IsInstanceOf;
import org.hamcrest.core.IsNot;
import org.junit.Assert;
import org.junit.Test;

public class TestContratTous {

    @Test
    public void classeDeStringEtEgal() {
        Assert.assertThat("texte", AllOf.allOf(
                IsInstanceOf.instanceOf(String.class), IsEqual.equalTo("texte")
        ));
    }

    @Test
    public void classeDeIntegerEtEgal() {
        Assert.assertThat("texte", AllOf.allOf(
                IsInstanceOf.instanceOf(Integer.class), IsEqual.equalTo("texte")
        ));
    }

    @Test
    public void classeDeStringEtPasEgal() {
        Assert.assertThat("texte", AllOf.allOf(
                IsInstanceOf.instanceOf(String.class), IsEqual.equalTo("Texte")
        ));
    }

    @Test
    public void classeDeIntegerEtPasEgal() {
        Assert.assertThat("texte", AllOf.allOf(
                IsInstanceOf.instanceOf(Integer.class), IsEqual.equalTo("Texte")
        ));
    }

    @Test
    public void classeDePasIntegerEtEgal() {
        Assert.assertThat("texte", AllOf.allOf(
                IsNot.not(IsInstanceOf.instanceOf(Integer.class)), IsEqual.equalTo("texte")
        ));
    }

    @Test
    public void classeDeStringEtPasPasEgal() {
        Assert.assertThat("texte", AllOf.allOf(
                IsInstanceOf.instanceOf(String.class), IsNot.not(IsEqual.equalTo("Texte"))
        ));
    }
}

Comme le montre la capture d'écran ci-dessous, les assertions où les deux sous-contrats sont respectés réussissent.

Image non disponible

IV-C-8. Contrat "au moins un" : AnyOf

La javadoc de ce contrat est disponible ici.

Le contrat vérifie qu'au moins un des contrats passés en paramètre du contrat est respecté.

TestContratAuMoinsUn.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.hamcrest.core.AnyOf;
import org.hamcrest.core.IsEqual;
import org.hamcrest.core.IsInstanceOf;
import org.junit.Assert;
import org.junit.Test;

public class TestContratAuMoinsUn {

    @Test
    public void classeDeStringEtEgal() {
        Assert.assertThat("texte", AnyOf.anyOf(
                IsInstanceOf.instanceOf(String.class), IsEqual.equalTo("texte")
        ));
    }

    @Test
    public void classeDeIntegerEtEgal() {
        Assert.assertThat("texte", AnyOf.anyOf(
                IsInstanceOf.instanceOf(Integer.class), IsEqual.equalTo("texte")
        ));
    }

    @Test
    public void classeDeStringEtPasEgal() {
        Assert.assertThat("texte", AnyOf.anyOf(
                IsInstanceOf.instanceOf(String.class), IsEqual.equalTo("Texte")
        ));
    }

    @Test
    public void classeDeIntegerEtPasEgal() {
        Assert.assertThat("texte", AnyOf.anyOf(
                IsInstanceOf.instanceOf(Integer.class), IsEqual.equalTo("Texte")
        ));
    }
}

Comme le montre la capture d'écran ci-dessous, les assertions où au moins un sous-contrat est respecté réussissent.

Image non disponible

IV-C-9. Pour aller plus loin : les contrats hors JUnit

Les assertions par contrat sont désormais intégrées à JUnit, mais sont à l'origine développées par JMock.

La librairie originale comprend des contrats supplémentaires. La javadoc de JMock est disponible ici.

Ces contrats sont séparés en 7 groupes :

  • core (contrats intégrés dans JUnit et déjà vus dans les chapitres précédents) : contrats de base sur les objets et les valeurs, ainsi que les contrats composés.
  • beans : contrats sur les beans Java et leurs valeurs.
  • collection : contrats sur les tableaux et les collections.
  • number : contrats de comparaison numérique.
  • object : contrats de contrôle des objets et des classes.
  • text : contrats de comparaison de textes.
  • xml : contrats sur les documents XML.

Pour pouvoir les utiliser, il faut rajouter les jar : "jmock-2.5.1.jar", "hamcrest-core-1.1.jar" et "hamcrest-library-1.1.jar".

IV-C-9-a. Les contrats beans

Le contrats "HasProperty" vérifie qu'un bean possède bien les getter et setter correspondants à une propriété. La javadoc de ce contrat est disponible ici.

Le contrat "HasPropertyWithValue" vérifie que la valeur d'une propriété d'un bean respecte un contrat passé en paramètre. La javadoc de ce contrat est disponible ici.

BeanSansPropriete.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

public class BeanSansPropriete {

}
BeanAvecPropriete.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

public class BeanAvecPropriete {
    private Integer prop;
    public void setProp(Integer pProp){prop = pProp;}
    public Integer getProp(){return prop;}
}
TestContratBean.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasProperty;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class TestContratBean {
    
    @Test
    public void beanSansPropriete() {
        assertThat(new BeanSansPropriete(), hasProperty("prop"));
    }

    @Test
    public void beanAvecPropriete() {
        assertThat(new BeanAvecPropriete(), hasProperty("prop"));
    }

    @Test
    public void beanAvecBonneValeur() {
        final BeanAvecPropriete lBean = new BeanAvecPropriete();
        lBean.setProp(10);
        assertThat(lBean, hasProperty("prop", equalTo(10)));
    }

    @Test
    public void beanAvecMauvaiseValeur() {
        final BeanAvecPropriete lBean = new BeanAvecPropriete();
        assertThat(lBean, hasProperty("prop", equalTo(10)));
    }
}

Comme le montre la capture d'écran ci-dessous, le contrat valide la présence d'une propriété et le respect d'un contrat par la valeur d'une propriété.

Image non disponible

IV-C-9-b. Les contrats collection

Le contrat "IsArray" vérifie que les éléments d'un tableau respecte un tableau de contrats (un contrat par élément). La javadoc de ce contrat est disponible ici.

Le contrat "IsArrayContaining" vérifie qu'un tableau contient au moins un élément qui respecte un contrat passé en paramètre ou qui est égal à une valeur passée en paramètre. La javadoc de ce contrat est disponible ici.

Le contrat "IsCollectionContaining" vérifie qu'une Collection contient des éléments qui respectent un ou des contrats passés en paramètres ou qui sont égaux à une valeur ou des valeurs passées en paramètres. La javadoc de ce contrat est disponible ici.

Le contrat "IsIn" vérifie qu'un objet est contenu dans une Collection, un tableau ou parmi les paramètres du contrat. La javadoc de ce contrat est disponible ici.

Le contrat "IsMapContaining" vérifie qu'une Map contient une entrée, une clé ou valeur qui respecte un contrat ou qui sont égaux à une valeur passée en paramètre. La javadoc de ce contrat est disponible ici.

TestContratCollectionIsArray.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.junit.Assert.assertThat;
import static org.hamcrest.collection.IsArray.array;
import static org.hamcrest.Matchers.is;

import org.junit.Test;

public class TestContratCollectionIsArray {

    @Test
    public void elementsEgaux() {
        assertThat(new Integer[]{1, 2}, array(is(1), is(2)));
    }

    @Test
    public void elementsDifferents() {
        assertThat(new Integer[]{1, 2}, array(is(1), is(3)));
    }
}

Comme le montre la capture d'écran ci-dessous, le contrat valide le respect par chaque élément du tableau d'un contrat.

Image non disponible
TestContratCollectionIsArrayContaining.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.hasItemInArray;
import static org.hamcrest.Matchers.nullValue;

import org.junit.Test;

public class TestContratCollectionIsArrayContaining {

    @Test
    public void contientElementContrat() {
        assertThat(new Long[]{1L, null}, hasItemInArray(nullValue()));
    }

    @Test
    public void neContientPasElementContrat() {
        assertThat(new Long[]{1L, 2L}, hasItemInArray(nullValue()));
    }

    @Test
    public void contientElement() {
        assertThat(new Long[]{1L, 2L}, hasItemInArray(1L));
    }

    @Test
    public void neContientPasElement() {
        assertThat(new Long[]{1L, 2L}, hasItemInArray(3L));
    }
}

Comme le montre la capture d'écran ci-dessous, le contrat valide que le tableau possède au moins un élément avec la valeur ou respectant le contrat passé en paramètre.

Image non disponible
TestContratCollectionIsCollectionContaining.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;

import java.util.Arrays;

import org.junit.Test;

public class TestContratCollectionIsCollectionContaining {

    @Test
    public void contientElementContrat() {
        assertThat(Arrays.asList(1L, 2L), hasItem(is(1L)));
    }

    @Test
    public void neContientPasElementContrat() {
        assertThat(Arrays.asList(3L, 2L), hasItem(is(1L)));
    }

    @Test
    public void contientElementsContrat() {
        assertThat(Arrays.asList(1L, 2L), hasItems(is(1L), is(2L)));
    }

    @Test
    public void neContientPasElementsContrat() {
        assertThat(Arrays.asList(1L, null), hasItems(is(1L), is(2L)));
    }

    @Test
    public void contientElement() {
        assertThat(Arrays.asList(1L, 2L), hasItem(1L));
    }

    @Test
    public void neContientPasElement() {
        assertThat(Arrays.asList(1L, 2L), hasItem(3L));
    }

    @Test
    public void contientElements() {
        assertThat(Arrays.asList(1L, 2L), hasItems(1L, 2L));
    }

    @Test
    public void neContientPasElements() {
        assertThat(Arrays.asList(1L, 2L), hasItems(1L, 2L, 3L));
    }
}

Comme le montre la capture d'écran ci-dessous, les contrats valident que la collection possède au moins un élément ou des éléments avec la/les valeur(s) ou respectant le(s) contrat(s) passé(s) en paramètre(s).

Image non disponible
TestContratCollectionIsIn.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.isIn;
import static org.hamcrest.Matchers.isOneOf;
import static org.junit.Assert.assertThat;

import java.util.Arrays;

import org.junit.Test;

public class TestContratCollectionIsIn {

    @Test
    public void presentDansCollection() {
        assertThat("a", isIn(Arrays.asList("a", "z", "e", "r", "t", "y")));
    }

    @Test
    public void absentDeCollection() {
        assertThat("A", isIn(Arrays.asList("a", "z", "e", "r", "t", "y")));
    }

    @Test
    public void presentDansTableau() {
        assertThat("a", isIn(new String[]{"a", "z", "e", "r", "t", "y"}));
    }

    @Test
    public void absentDeTableau() {
        assertThat("A", isIn(new String[]{"a", "z", "e", "r", "t", "y"}));
    }

    @Test
    public void present() {
        assertThat("a", isOneOf("a", "z", "e", "r", "t", "y"));
    }

    @Test
    public void absent() {
        assertThat("A", isOneOf("a", "z", "e", "r", "t", "y"));
    }
}

Comme le montre la capture d'écran ci-dessous, les contrats valident que la valeur appartient à un ensemble.

Image non disponible
TestContratCollectionIsMapContaining.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;

import java.util.HashMap;
import java.util.Map;

import org.hamcrest.collection.IsMapContaining;
import org.junit.Before;
import org.junit.Test;

public class TestContratCollectionIsMapContaining {

    private Map<String, Long> hashMap;
    
    @Before
    public void initialise() {
        hashMap = new HashMap<String, Long>();
        hashMap.put("cle1", 1L);
        hashMap.put("cle2", 2L);
    }
    
    @Test
    public void contientEntree() {
        assertThat(hashMap, hasEntry("cle1", 1L));
    }

    @Test
    public void neContientPasEntree() {
        assertThat(hashMap, hasEntry("cle1", 2L));
    }

    @Test
    public void contientEntreeContrat() {
        assertThat(hashMap, hasEntry(is("cle1"), not(2L)));
    }

    @Test
    public void neContientPasEntreeContrat() {
        assertThat(hashMap, hasEntry(is("cle1"), not(1L)));
    }

    @Test
    public void contientCle() {
        assertThat(hashMap, IsMapContaining.<String, Long>hasKey("cle1"));
    }

    @Test
    public void neContientPasCleEntree() {
        assertThat(hashMap, IsMapContaining.<String, Long>hasKey("cle3"));
    }

    @Test
    public void contientCleContrat() {
        assertThat(hashMap, IsMapContaining.<String, Long>hasKey(is("cle1")));
    }

    @Test
    public void neContientPasCleContrat() {
        assertThat(hashMap, IsMapContaining.<String, Long>hasKey(is("cle3")));
    }

    @Test
    public void contientValeur() {
        assertThat(hashMap, IsMapContaining.<String, Long>hasValue(1L));
    }

    @Test
    public void neContientPasValeur() {
        assertThat(hashMap, IsMapContaining.<String, Long>hasValue(3L));
    }

    @Test
    public void contientValeurContrat() {
        assertThat(hashMap, IsMapContaining.<String, Long>hasValue(is(1L)));
    }

    @Test
    public void neContientPasValeurContrat() {
        assertThat(hashMap, IsMapContaining.<String, Long>hasValue(is(3L)));
    }
}

Comme le montre la capture d'écran ci-dessous, les contrats valident qu'un objet Map possède une entrée, une clé ou une valeur ou respectant un contrat passé en paramètre.

Image non disponible

IV-C-9-c. Les contrats number

Le contrat "IsCloseTo" vérifie qu'un nombre passé en paramètre est suffisamment proche d'un autre nombre. La javadoc de ce contrat est disponible ici.

Le contrat "OrderingComparisons" vérifie qu'un nombre passé en paramètre est supérieur, supérieur ou égal, inférieur, inférieur ou égal à une autre valeur. La javadoc de ce contrat est disponible ici.

TestContratNumber.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class TestContratNumber {

    @Test
    public void proche() {
        assertThat(20.5, closeTo(20, 0.5));
    }

    @Test
    public void pasProche() {
        assertThat(20.5, closeTo(20, 0.1));
    }

    @Test
    public void plusGrand() {
        assertThat(21, greaterThan(20));
    }

    @Test
    public void pasPlusGrand() {
        assertThat(20, greaterThan(20));
    }

    @Test
    public void plusGrandOuEgal() {
        assertThat(20, greaterThanOrEqualTo(20));
    }

    @Test
    public void pasPlusGrandOuEgal() {
        assertThat(19, greaterThanOrEqualTo(20));
    }

    @Test
    public void plusPetit() {
        assertThat(19, lessThan(20));
    }

    @Test
    public void pasPlusPetit() {
        assertThat(20, lessThan(20));
    }

    @Test
    public void plusPetitOuEgal() {
        assertThat(20, lessThanOrEqualTo(20));
    }

    @Test
    public void pasPlusPetitOuEgal() {
        assertThat(21, lessThanOrEqualTo(20));
    }
}

Comme le montre la capture d'écran ci-dessous, les contrats valident la comparaison entre les deux nombres.

Image non disponible

IV-C-9-d. Les contrats object

Le contrat "HasToString" vérifie que la valeur retournée par le toString() de l'objet passé en paramètre respecte un contrat. La javadoc de ce contrat est disponible ici.

Le contrat "IsCompatibleType" vérifie que la classe passée en paramètre est compatible avec celle passée en paramètre du contrat. La javadoc de ce contrat est disponible ici.

Le contrat "IsEventFrom" vérifie l'origine (et la classe) d'un évènement. La javadoc de ce contrat est disponible ici.

TestContratObject.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.hasToString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.typeCompatibleWith;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class TestContratObject {

    @Test
    public void toStringOK() {
        assertThat(new Long(30), hasToString(is("30")));
    }

    @Test
    public void toStringNOK() {
        assertThat(new Long(30), hasToString(is(" 30")));
    }

    @Test
    public void compatible() {
        assertThat(Long.class, typeCompatibleWith(Number.class));
    }

    @Test
    public void incompatible() {
        assertThat(Long.class, typeCompatibleWith(String.class));
    }
}

Comme le montre la capture d'écran ci-dessous, les contrats valident la valeur retournée par le toString() d'un objet et la compatibilité entre deux classes.

Image non disponible
TestContratObjectIsEventFrom.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.eventFrom;
import static org.junit.Assert.assertThat;

import java.beans.PropertyChangeEvent;

import javax.swing.event.ChangeEvent;

import org.junit.Before;
import org.junit.Test;

public class TestContratObjectIsEventFrom {

    private Object source;
    private ChangeEvent event;

    @Before
    public void initialise() {
        source = "source";
        event = new ChangeEvent(source);
    }

    @Test
    public void envementOrigine() {
        assertThat(event, eventFrom(source));
    }

    @Test
    public void envenementAutreOrigine() {
        assertThat(event, eventFrom("autreSource"));
    }

    @Test
    public void evenementClasse() {
        assertThat(event, eventFrom(ChangeEvent.class, source));
    }

    @Test
    public void evenementAutreClasse() {
        assertThat(event, eventFrom(PropertyChangeEvent.class, source));
    }

}

Comme le montre la capture d'écran ci-dessous, le contrat valide l'origine d'un évènement et sa classe.

Image non disponible

IV-C-9-e. Les contrats text

Le contrat "IsEqualIgnoringCase" vérifie l'égalité de deux chaines de caractères sans tenir compte de la casse. La javadoc de ce contrat est disponible ici.

Le contrat "IsEqualIgnoringWhiteSpace" vérifie l'égalité de deux chaines de caractères sans tenir compte des espaces. La javadoc de ce contrat est disponible ici.

Le contrat "StringContains" vérifie que la chaine de caractères passée en paramètre contient la chaine de caractère passée en paramètre du contrat. La javadoc de ce contrat est disponible ici.

Le contrat "StringEndsWith" vérifie que la chaine de caractère passée en paramètre finit par la chaine de caractère passée en paramètre du contrat. La javadoc de ce contrat est disponible ici.

Le contrat "StringStartsWith" vérifie que la chaine de caractère passée en paramètre commence par la chaine de caractères passée en paramètre du contrat. La javadoc de ce contrat est disponible ici.

TestContratText.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.hamcrest.Matchers.equalToIgnoringWhiteSpace;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class TestContratText {

    @Test
    public void egalCasse() {
        assertThat("azerty", equalToIgnoringCase("Azerty"));
    }

    @Test
    public void pasEgalCasse() {
        assertThat("azerty", equalToIgnoringCase("Qwerty"));
    }

    @Test
    public void egalEspace() {
        assertThat("a\nz e r t y", equalToIgnoringWhiteSpace("a  z  e  r \n t  y"));
    }

    @Test
    public void pasEgalEspace() {
        assertThat("a z e r t y", equalToIgnoringWhiteSpace("q w e r t y"));
    }

    @Test
    public void contient() {
        assertThat("azerty", containsString("zert"));
    }

    @Test
    public void neContientPas() {
        assertThat("azerty", containsString("wert"));
    }

    @Test
    public void commencePar() {
        assertThat("azerty", startsWith("azer"));
    }

    @Test
    public void neCommencePasPar() {
        assertThat("azerty", startsWith("qwer"));
    }

    @Test
    public void finitPar() {
        assertThat("azerty", endsWith("erty"));
    }

    @Test
    public void neFinitPasPar() {
        assertThat("azerty", endsWith("erti"));
    }
}

Comme le montre la capture d'écran ci-dessous, les contrats valident les relations entre les deux chaines de caractères.

Image non disponible

IV-C-9-f. Les contrats xml

Le contrat "HasXPath" vérifie qu'un chemin existe et/ou respecte un contrat dans un document XML. La javadoc de ce contrat est disponible ici.

TestContratXMLjava
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.hamcrest.Matchers.hasXPath;
import static org.junit.Assert.assertThat;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class TestContratXML {

    private Document document;

    @Before
    public void initialise() throws ParserConfigurationException {
        final DocumentBuilderFactory lDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
        final DocumentBuilder lDocumentBuilder = lDocumentBuilderFactory.newDocumentBuilder();

        document = lDocumentBuilder.newDocument();

        final Element lElement = document.createElement("racine");
        document.appendChild(lElement);

        final Element lElement1 = document.createElement("element1");
        lElement1.appendChild(document.createTextNode("texteElement1"));
        lElement.appendChild(lElement1);
        final Element lElement2 = document.createElement("element2");
        lElement2.appendChild(document.createTextNode("texteElement2"));
        lElement.appendChild(lElement2);
    }
    
    @Test
    public void avecChemin() {
        assertThat(document, hasXPath("/racine/element1"));
    }
    
    @Test
    public void sansChemin() {
        assertThat(document, hasXPath("/racine/element3"));
    }
    
    @Test
    public void avecCheminContrat() {
        assertThat(document, hasXPath("/racine/element1", equalToIgnoringCase("texteelement1")));
    }
    
    @Test
    public void sansCheminContrat() {
        assertThat(document, hasXPath("/racine/element1", equalToIgnoringCase("texteelement2")));
    }
}

Comme le montre la capture d'écran ci-dessous, le contrat valide que le document XML possède un chemin et que ce chemin respecte un contrat.

Image non disponible

V. LES SUPPOSITIONS

La javadoc des suppositions est disponible ici.

Les suppositions sont présentes dans JUnit depuis la version 4.4.

Une supposition vérifie une condition. Si la condition n'est pas vérifiée, le test s'arrête mais ne passe pas en erreur ou en échec.

Les différentes suppositions sont :

TestSupposition.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;

public class TestSupposition {

    @Test
    public void verifierExistenceFichier() {
        final File lFile = new File("fichier.txt");
        Assert.assertTrue("Le fichier doit exister", lFile.exists());
    }
    
    @Test
    public void lireFichier() throws IOException {
        final File lFile = new File("fichier.txt");
        Assume.assumeTrue(lFile.exists());
        
        final FileInputStream lFileInputStream = new FileInputStream(lFile);
        final byte[] lBytes = new byte[16];
        lFileInputStream.read(lBytes);
        Assert.assertArrayEquals("Bonjour le monde".getBytes(), lBytes);
    }
}

Comme le montre la capture d'écran ci-dessous, si le fichier n'existe pas, seul le test vérifiant la présence du fichier passe en échec.

Image non disponible

VI. LES TESTS PARAMETRES

La javadoc des tests paramétrés est disponible ici.

Les tests paramétrés permettent d'exécuter plusieurs fois un cas de tests avec des valeurs différentes. Le cas de test doit être annoté avec @RunWith avec pour valeur Parameterized. Les paramètres sont indiqués par une méthode annotée avec @Parameters retournant une Collection. Le cas de tests paramétrés doit comporter un constructeur correspondant aux paramètres. Les tests paramétrés sont apparus avec la version 4.0 de JUnit.

Operations.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

public class Operations {

	public static long additionner(final long...pNombres) {
		long lRetour = 0;
		for(final long lNombre : pNombres) {
			lRetour += lNombre;
		}
		return lRetour;
	}
	
	// Cette méthode ne fonctionne pas correctement
	// Les tests vont le vérifier 
	public static long multiplier(final long...pNombres) {
		long lRetour = 0;
		for(final long lNombre : pNombres) {
			lRetour *= lNombre;
		}
		return lRetour;
	}
}
TestParametre.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import java.util.Arrays;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class TestParametre {

    @Parameters
    public static List<Object[]> getParametres() {
        return Arrays.asList(new Object[][] {
                { 10L, 0L, new long[] { 10L, 0L } },
                { 30L, 300L, new long[] { 10L, 20L } },
                { 7936L, 1125899906842624L, new long[] { 256L, 512L, 1024L, 2048L, 4096L } }, 
        });
    }

    private long resultatAddition;
    private long resultatMultiplication;
    private long[] nombres;

    public TestParametre(long pResultatAddition, long pResultatMultiplication, long[] pNombres) {
        resultatAddition = pResultatAddition;
        resultatMultiplication = pResultatMultiplication;
        nombres = pNombres;
    }

    @Test
    public void addition() {
        System.out.println("addition :      - attendu : " + resultatAddition + 
                         "\n                - nombres : " + Arrays.toString(nombres));
        final long lAddition = Operations.additionner(nombres);
        Assert.assertEquals(resultatAddition, lAddition);
    }

    @Test
    public void mutiplication() {
        System.out.println("mutiplication : - attendu : " + resultatMultiplication + 
                         "\n                - nombres : " + Arrays.toString(nombres));
        final long lMultiplication = Operations.multiplier(nombres);
        Assert.assertEquals(resultatMultiplication, lMultiplication);
    }
}

Comme le montre la capture d'écran et la trace ci-dessous, le cas de tests est exécuté plusieurs fois avec des paramètres différents.

Image non disponible
 
Sélectionnez
mutiplication : - attendu : 0
                - nombres : [10, 0]
addition :      - attendu : 10
                - nombres : [10, 0]
mutiplication : - attendu : 300
                - nombres : [10, 20]
addition :      - attendu : 30
                - nombres : [10, 20]
mutiplication : - attendu : 1125899906842624
                - nombres : [256, 512, 1024, 2048, 4096]
addition :      - attendu : 7936
                - nombres : [256, 512, 1024, 2048, 4096]

VII. LES ANNOTATIONS POUR LES SUITES DE TESTS

La javadoc de l'annotation des suites de tests est disponible ici.

Les suites des tests permettent d'exécuter plusieurs cas de tests dans la même exécution. La classe de suite doit être annotée avec @RunWith avec pour valeur Suite. Les cas de tests composants la suite sont indiqués par l'annotation @SuiteClasses.

TestSuitePartie1.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.Test;

public class TestSuitePartie1 {

    @Test
    public void test1() {
    }
}
TestSuitePartie2.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import static org.junit.Assert.fail;

import org.junit.Test;

public class TestSuitePartie2 {

    @Test
    public void test2() {
        fail();
    }
}
TestSuite.java
Sélectionnez
package com.developpez.rpouiller.testsjunit4;

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({TestSuitePartie1.class, TestSuitePartie2.class})
public class TestSuite {
}

Comme le montre la capture d'écran, les différents cas de tests sont exécutés dans la même exécution.

Image non disponible

VIII. REMERCIEMENTS

Je remercie sincèrement par ordre plus ou moins chronologique :

  • www.developpez.com me permettant de publier cet article.
  • Nono40 pour ses outils.
  • Mikrob pour ses encouragements.
  • djo.mos pour ses suggestions pertinentes et ses encouragements.
  • romaintaz pour sa relecture orthographique rigoureuse et ses encouragements.

IX. SOURCES

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2009 Régis POUILLER. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts. Droits de diffusion permanents accordés à Developpez LLC.