Introduction au tests logiciels : unitaires, d'intégration ou fonctionnels

 

Tests unitaires

 

Introduction au test logiciel

Suivant les cycles de vie, la phase de test est placée à différents niveaux. Dans ce cours, on utilise la phase de tests de Maven

D’après Maven, elle se passe avant le pakaging, avant l’installation

La phase de test est souvent découpée en plusieurs sous phases.

 

-le test unitaire (issu du diagramme de classes)

A partir du diagramme de classes UML, on teste les classes une à une. Jamais 2 classes !

-le test d’intégration (issu du diagramme de séquences)

 

A partir du diagramme de séquences UML, on teste un ensemble de classes qui ont du sens utile au développeur.

-le test fonctionnel (issu du diagramme d’activités)

On teste un ensemble de classes utiles au client MOA, besoin client. Or les MOA ne font que des diagrammes d’activités.

 

Une question? Posez-la ici

 

Le test unitaire

Le test unitaire s’intéresse à une classe dont la technicité nécessite une validation.

Avec des tests, on valide des classes d’un programme avec des preuves de propriétés, on vérifie un programme.

Ne pas dire « on vérifie », dire « on valide ».

On considère avec de nombreuses classses, ces classes sont divisées en 2 catégories

Des classes de données

Get, set

Des classes de traitement

Des méthodes qui effectuent des traitements utiles à l’application.

Pour chaque classe de traitement, il est utile de faire une classe jumelle (twin en anglais)

SI j’ai une classe DAO, je m’attends qu’il y ait une classe qui porte le même nom.

Combien de méthodes ? Tout dépend de la classe de traitement ? SI j’ai 5 méthodes dans ma classe de traitement, j’aurais 5 méthodes de tests.

Si CUT, classe under tests a 5 méthodes

CT, classe test a aussi 5 méthodes.

Dans une organisation de projet, il y a plusieurs sources folders :

Ce qui sera livré au client 

src/main/java = CUT

src /main/resources= données

Il faudra mettre aussi les tests à garder 

src /test/java = CT

src /test/resources = CT

Les 2 répertoires « main » et « test » possèdent la même arborescence de package

Frameorks de tests : Junit (v>4.8 au jourd’hui j’utilise la 4.12) , TestNG

En java, il y a y mot clé: assert condition: Objet

En Java natif, il y a un mot « assert » . Quand ça rencontre un assert, ça vérifie la condition : si condition bonne, tout va bien, sinon une exception est levée.

Comme les gens ne connaissent pas « assert », ils utilisent Junit qui lui utilise « assert »

La JVM recherche une méthode main dans la classe

Pour executer un test, on utilise une classe TestRunner à qui on donne en paramètre notre classe de test, qui invoquera notre classe undertest.

 

Une question? Posez-la ici

 

Comment fabriquer une classe de test ?

 

Quand on fait du Junit, il faut connaitre 2 designs patterns :

Visitor (comportement)

Utile pour un test (TestCase) annotation@Test>

Composite (tructure)

Utile pour faire une suite de tests (TestSuite) annotation @TestSuite

Rappel : une annotation en java est qualifiée par 3 propriétés :

1 rétention 

source (doc), bytecode (monitoring) , runtime (execution).

1 portée parmi 8 

Avant un package, classe, attribut, paramètre, constructeur, variable locale, annotation

1 mode d’héritage

True ou false

La classe TestRunner peut être composée avec une éval d’automate.

Un cas de test doit être programmé comme une succession de phases, d’étapes évaluées par TestRunner.

Pour qualifier chaque étape il y a une annotation

Exemple : il est demandé de faire une classe triangle qui permet le calcul de sa surface.

Rappel métier :

3 cotés a,b,c tels que a !=b !=c a différent de b, différent de c

Théorème de Héron (qui permet de calculer la surface de n’importe quel quadrilatère)

J’ai besoin de calculer le demi périmètre

Demi-périmètre = Dp= ½(a+b+c)

Aire = racine carrée de( (a-dp)(b-dp)(c-dp)dp )

A=3

B=4

C=5

Dp=6

Aire=racine carrée de (3x2x1x6) =6

Je crée donc ma classe :

Triangle

Arguments :

A

B

C

Méthodes

-triangle

-surface

PB : cette classe est un mix de données et de traitements. Il serait préférable de la transformer afin qu’elle soit mieu ou plus testable.

Classe de données :

Triangle

Arguments :

Cote1

Cote2

Cote3

Méhodes :

Triangle (a,b,c)

Classe de traitements  (qui utilise la classe de données):

CalculSurface

+surface (Triangle)

Ce découpage va me permettre de faire des Mocks

Src/main/java contient :

Geometry/

               Triangle.Java

               CalculSurface.Java

               HeronSurface.Java

Test/main/java contient :

               Geometry/

                              HeronSurfaceTest.Java

Un ensemble d’états

Un test est un automate :

 

Une question? Posez-la ici

 

Les étapes des tests

 

 

Avec les annotations de rétention runtime, de portée méthodes, et elles s’héritent

@BeforeClass Travail à faire AVANT les tests

@Before Travail à faire AVANT un test

@Test On effectue un test

@After Travail à faire APRES un test

(existe-t-il d’autres tests ? Si oui, aller à Travail à faire AVANT un test)

@AfterClass Travail à faire APRES tous les tests

Fin

Créer une méthode de test signifie, effectuer une comparaison entre un résultat escompté (expected) et un résultat calculé (computed).

Pour pouvoir faire des tests, il faut que les méthodes retournent quelquechose, pas void.

Grace au classloader , @beforeclasse et @afterclasse annotent des methods statiques

Public geometry ;

Public class HeronSurfaceTest{

@beforeclass

Public static void setupBeforeClass(){

}

Private Triangle triangle;

@before

Public void setup(){

Triangle= new Triagle(3,4,5);

}

@test

Public void surface(){

CalculSurface cs=newtherundsurface()

Assert.assertequel(6,triangle.surface());

// on a bien le asserted et le computed

}

@After

Public void teardown(){

Triangle=null

Counter++;

}

Public static void teardownClass(){

System.out.println(“Nombre de test:” +counter);

}

A la fin de l’execution de TestRunner, il y a l’édition d’un rapport de test unitaire, pour voir par les résultats.

« 14 test ont été faites, 5 ont réussis, 8 sont en erreur. »

Un test peut avoir 3 résultats

-succès 

le CUT est validé par le test

-echec 

le CUT n’est pas validé par le test -> modification de CUT (travail à planifier)

-erreur

le test est faux

Rappel : pour toute annotation, il faut faire un import, avec CTRL+O

Une annotation est un code java

 

Une question? Posez-la ici

 

Rapport de test

Il faut une raison pour faire les tests, on ne les fait pas pour rien, pour rigoler, ou pour passer le temps. Cette raison c’est le critère.

Pour conclure un rapport de test, il est essentiel de fournir le degré de couverture des tests afin de répondre à la question :

« est-ce que mon critère de couverture est satisfait ? »

Un critère de couverture est à annoncer avant le début de la phase de tests. C’est lui qui pilote l’écriture des tests. Il y aura d’autant plus de tests que le critère est fort.

Exemple :

critère 1, il faut passer par toutes les méthodes de la CUT

critère2, il faut effectuer au moins 2 itérations par boucle

S’il n’y en n’a pas de critères, on vous le reprochera.

 

 

Une question? Posez-la ici

 

 

Des questions?