Tests logiciels : unitaires, d'intégration ou fonctionnels
Tests unitaires
Introduction au test logiciel
il est difficile de dispenser un cours de développement Java sans parler des différents tests.
Suivant les cycles de vie des développements d'applications informatiques, 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 !
Ensuite on peut faire un beau rapport de test unitaire avec une belle présentation.comme j'aime les voir
-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. c'est le test d'intégration
-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
Aide au développement d'applications
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
Exemple, un getter, un setter: Get, set
Des classes de traitements
Elles sont composées de 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
Aide au développement d'applications
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
Aide au développement d'applications
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
Aide au développement d'applications
Le 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
Aide au développement d'applications
Des questions?