Skip to topic | Skip to bottom
Home
Linfo
Linfo.GLEnvtProg0708TP5r1.3 - 15 Mar 2008 - 20:36 - NicolasNobelistopic end

Start of topic | Skip to actions

TP 5 - Tests, programmation extrême, infrastructure Check

Licence 3 Informatique - 2007-2008

PhilippeCollet, NicolasNobelis

URL de cette page : http://deptinfo.unice.fr/twiki/bin/view/Linfo/GLEnvtProg0708TP5
URL de l'enseignement : http://deptinfo.unice.fr/twiki/bin/view/Linfo/GLEnvtProg0708

Avant propos

  • Créez votre répertoire de séance pour le TP et placez-vous dedans.
  • Récupérez et décompressez l'archive Fourniture5.tar.bz2. Vous obtenez alors :
    • le fichier file0.h,
    • quatre répertoires pour les différentes expériences demandées dans ce sujet : 0.testsManuels, 1.testsManuels, 2.testsCheck0 et 3.testsCheck1.

1. Programmation "extrême"

La programmation "extrême" (Extreme Programming) préconise un cycle de développement qui combine les trois activités principales de spécification, de programmation et de test. Après la phase de conception et de décomposition de l'application à construire en unités¹ de complexité maîtrisable par un développeur, l'idée générale est de :

  • spécifier une unité,
  • écrire le programme de test de cette unité avant de l'implémenter,
  • finalement implémenter l'unité puis lancer les tests unitaires.
Au cours de l'écriture du programme de tests, on peut découvrir des anomalies dans les spécifications : absence de fonctionnalités, difficultés d'utilisation de l'unité... On peut donc corriger les spécifications avant d'implémenter. Bien entendu, ce type de développement en "spirale" se fait de manière incrémentale : on écrit d'abord un cas de test, puis on implémente ce qu'il faut pour tester. On peut aussi au début implémenter les primitives de manière "extrême", avec des corps vides ou signalant une erreur.

1.1. Étude de la spécification file0.h

Étudiez la spécification suivante file0.h qui définit le comportement d'un type abstrait File bornée fonctionnant en ordre FIFO.

file0.h :

 /* 
  * Type Abstrait File <Element> en ordre FIFO, 
  * bornée par un nombre maximum d'éléments 'nbPlaces'. 
  * Les deux primitives de base sont : 
  *    entrer : dépôt d'un nouvel élément dans la file 
  *    sortir : extraire un élément de la file, selon l'ordre en cours dans la file .
  * Dans cette version, un seul ordre FIFO est possible (pas de priorité) : 
  * le prochain élément à sortir est le plus ancien
  * Toutes les primitives retournent un compte-rendu pour indiquer le succès ou l'échec.
  */

typedef void* File; /* Type Abstrait */

typedef struct {
  void *info; /* espace mémoire quelconque pour stocker l'information de l'élément par exemple une chaîne de caractères */
              /* Autres champs éventuels : priorité, ticket d'arrivée ... */
}Element;

/* Constructeurs ***************************************************************/

File creer(int nbPlaces);
/* rend une File vide, NULL si erreur */

/* Modifieurs ******************************************************************/

int entrer (File f, Element e);
/* enregistre e dans la file .
 * compte-rendu:
 * 0: succès
 * -2: f pleine
 */

int sortir (File f, Element *e);
/* fait sortir un élément de la file f, selon l'ordre en cours
 * et le recopie dans e.
 * compte-rendu:
 * 0: succès
 * -2: f vide
 */

/* Accesseurs ******************************************************************/

int nbElements(File f);
/* rend le nombre d'éléments dans f */

1.2. Correction et robustesse

Les tests peuvent vérifier plusieurs sortes de propriétés du logiciel testé :

  • la correction, mettant en évidence le respect des spécifications fonctionnelles, donc l'absence d'erreurs de programmation lors de l'implémentation.
  • la robustesse, évaluée comme la capacité à détecter des anomalies de l'environnement du programme testé, notamment les erreurs d'utilisation, et à agir au mieux selon ces anomalies.
  • d'autres propriétés extra-fonctionnelles, comme la performance, etc.
A votre avis, quels sont les cas de robustesse à vérifier pour la File ? L'adresse de File manipulée par les différentes primitives est-elle nécessairement correcte en langage C ? En Java ? Quelle technique faudrait-il utiliser pour vérifier en C que les adresses sont correctes ? Quel en serait le coût à l'exécution ?

1.3. Plan de test pour file0.h

Définissez l'ordre dans lequel vous allez tester les différentes primitives pour permettre une approche extrême et incrémentale du développement du type abstrait File.
Que devez-vous vérifier après la création d'une file ? Comment le faire ? S'il manque des primitives, corrigez file0.h et appelez-le file1.h.
Ensuite, définissez pour chaque primitive, les cas intéressants à tester (en "boîte noire") et à vérifier.

2. Série de tests avec trace et une implémentation vide

Pour tester "à la main", une unité, il faut écrire un programme de test. Celui-ci doit appeler les différentes primitives de l'unité à tester, afin de réaliser des expériences d'exécution et offrir des moyens pour vérifier que le comportement est normal. Avec des outils d'aide, comme check vu en cours, la vérification se fait en testant des conditions logiques (des assertions) qui doivent être vraies ou fausses. Un moyen plus simple à écrire, mais nécessitant des vérifications manuelles des résultats de l'expérience, consiste à afficher des traces.

  • Placez-vous dans le répertoire 0.testsManuels et exécutez le Makefile. Vous voyez apparaître des traces d'une série de tests.
  • Examinez le code de file0.c : vous remarquerez que rien n'est encore implémenté. On a obtenu cette version simplement en recopiant la spécification file1.h et en donnant des corps aux primitives qui indiquent une erreur.
  • Examinez maintenant le code du programme de test. Celui-ci correspond au concept de "série de tests", tel que vous l'avez vu en cours avec l'infrastructure check.
    La série est directement pilotée par la routine main, qui enchaîne deux "cas de test" (test cases) tc1 et tc2. Chaque cas de test fait appel à une ou plusieurs "unités de tests" (test units) tu_nomX, qui réalisent les expériences et affichent des traces pertinentes.
  • En vous inspirant du code fourni, complétez le code de l'unité de test tu_sortir et relancez la série de tests avec make. Le fichier tfile0.res contient la trace que vous devez obtenir.

3. Écriture incrémentale des tests avec trace et une implémentation quasi-complète

Placez-vous dans le répertoire 1.testsManuels. Ce répertoire contient un état de développement intermédiaire, où l'implémentation n'est pas encore achevée, mais où les tests sont déjà bien avancés.

3.1. Analyse manuelle de traces

Exécutez le Makefile et observez les traces affichées.
Étudiez ensuite le programme de test. Est-il facile de vérifier la correspondance entre les traces affichées et ce qui est attendu ?

3.2. Tests en boîte noire, blanche et grise.

On appelle tests en boîte noire des tests externes d'un composants logiciel sans qu'on connaisse l'implémentation interne. C'est le cas des tests précédents.
Les tests en boîte blanche, au contraire, sont des tests réalisés par l'implémenteur d'un composant et ont accès à l'implémentation interne. Typiquement, ces tests sont réalisés en mode "DEBUG", et utilisent des traces qui font appel à des variables internes invisibles de l'extérieur du composant. C'est le cas des traces conditionnelles #ifdef DEBUG ... placées dans file1.c.
Les tests en boîte grise sont des tests externes qui n'ont pas accès aux variables d'implémentation, mais supputent la technique d'implémentation choisie. Par exemple ici, sachant que la file est implémentée par un tableau circulaire, proposez des cas de tests externes supplémentaires pour vérifier le bon fonctionnement de la circularité. Ajoutez-les dans un nouveau cas de test tc3.

4. Série de tests avec l'infrastructure check et une implémentation vide

Placez-vous dans le répertoire 2.testsCheck0 et lancez le Makefile. Cette expérience utilise la même implémentation "vide" file0.c qu'à la question 2., mais en utilisant cette fois l'infrastructure check.
L'organisation de la série de tests est identique aux tests manuels précédents, mais cette fois les traces sont remplacées par des assertions à vérifier. Le travail d'écriture de la série est plus long que précédemment, mais la détection des échecs ou des succès est automatique.
Examinez le code du programme de test checkFile0.c pour comprendre l'exécution obtenue. Remarquez que l'exécution s'arrête au premier cas de test (tc) qui échoue, mais pas à la première unité de test qui échoue (tu).

5. Série de tests avec l'infrastructure check et une implémentation complète

Placez-vous dans le répertoire 3.testsCheck1 et lancez le Makefile.

  • Étudiez la suite de tests checkFile1.c pour comprendre le résultat affiché.
  • Complétez cette suite de tests, en écrivant le code approprié dans l'unité de test tu_entrer1, en vous inspirant de 1.testsManuels/tfile1.c pour tester l'arrivée d'élements e1, e2, e3 et tester les cas de saturation.
  • Faites de même pour tu_sortir1 pour tester la sortie d'un élément dans une file vide, et vérifiez que les éléments entrés précédemment ressortent bien dans l'ordre FIFO.
  • S'il vous reste du temps, programmez un cas de test en boîte grise tu_entrer_sortir1 qui teste la circularité supputée.


¹: Selon l'environnement utilisé, ces unités sont appelées classifieur, module, classe, composant...

-- NicolasNobelis - 15 Mar 2008
to top

I Attachment sort Action Size Date Who Comment
Fourniture5.tar.bz2 manage 5.2 K 28 Feb 2008 - 16:24 NicolasNobelis Fourniture pour le TP5
corrige05.pdf manage 120.3 K 15 Mar 2008 - 20:35 NicolasNobelis Corrigé du TP5

You are here: Linfo > GLEnvtProg0708 > GLEnvtProg0708TP5

to top

Copyright © 1999-2020 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding WIKIDeptinfo? Send feedback