Test du compilateur, couverture de code
Mildred Ki'Lya
ml.mildred593 at gmail.com
Sat Mar 6 08:39:48 UTC 2010
Salut,
Où je travaille ne ce moment, on insiste beaucoup sur les tests, et que
les tests couvrent l'entièreté du code source. C'est juste avec le
langage Ada, et pas Lisaac (même si Lisaac les intéresse).
C'est comme ça que j'ai découvert Cucumber, un toutil pour faciliter les
tests
http://cukes.info/
Mon idée est de créer des tests qui pourrait servir de spécification au
langage Lisaac, un comportement de référence en quelque sorte.
Cucumber est particulier dans le fait que les tests sont écrits en
langue naturelle (Anglais, Français ...). Ces tests sont appelés des
fonctionnalités (feature) et sont lisibles par des non informaticiens.
Ils sont donc en particulier très pratique dans mon entreprise pour se
mettre d'accord avec un client sur un fonctionnement attendu.
Des exemples de fonctionnalités cucumber:
http://git.debian.org/?p=lisaac/compiler.git;a=tree;f=features;hb=HEAD
*Les fonctionnalités cucumber, comment ça marche*
(regardez quelques fonctionnalités cucumber avant de continuer
* Tout d'abord, la première partie est entièrement descriptive
(après "Feature:")
* Ensuite, la fonctionnalité est décomposée en scénarios, contenant
différentes étapes de test. Les scénarios sont exécutés
séquentiellement, précédés à chaque fois par le contexte
(background) qui sert à mettre en place l'environnement.
* Les actions dans un scénarios (et dans le xontexte) sont préfixées
par un des mots clefs "Given" "When" ou "Then". Le mot clef "And"
permet de répéter le mot clef qu'il y avait à la ligne d'avant.
* "Given" met en place le contexte du scénario
* "When" exécute des actions
* "Then" teste le résultat de ces actions
Chacune des lignes sont associées à du code ruby à travers des
expressions régulières. Ce code se trouve dans features/step_definitions/.
*Exécuter des fonctionnalités avec cucumber*
Pour installer cucumber (et rake qui est nécessaire dans les
step_definitions) vous avez besoin du rubygems. On m'a dit que ça ne
marchait pas bien sous debian/ubuntu à cause de patches debian (encore
et toujours). Donc vous aurez peut être à faire comme ma collègue et
installer rubygems à la main.
Ensuite, c'est très simple:
gem install cucumber
gem install rake
Et on peut commencer à jouer. Dans le dossier du compilateur, exécutez:
cucumber features/*.feature
Et toutes les fonctionnalités vont être exécutées. Et il y a un joli
rapport en couleurs.
*Couverture de code*
Les tests, c'est très pratique, mais c'est encore plus pratique quand on
est sûr qu'il testent bien tout le code, et qu'il n'y a pas certains bug
qui sont restés cachés dans des parties reculées du code non testées.
C'est pourquoi il y a plein d'outils pour vérifier la couverture de code.
Mais aucun pour Lisaac.
En y réfléchissant, je ne pense pas que créer un outil de couverture de
code pour Lisaac soit bien difficile, voyons comment ça fonctionne:
1. On compile du code en ajoutant une instrumentation pour la
couverture de code
2. On exécute le code instrudmenté
3. L'exécution du code produit des fichiers permettant de constater
* Quelles lignes sont exécutées
* Quelles lignes ne sont pas exécutées
* Quelles lignes ne sont pas exécutables (commentaires, ...)
4. On lance un outil pour convertir ces infos brutes en joli rapport HTML
Donc, comment faire en Lisaac pour générer ces infos de couverture ? En
Lisaac, c'est très simple parce que le langage interdit formellement les
branchements dans les {BLOCK} ou les (listes). Si une instruction est
exécutée dans un bloc (ou une liste) on sait que toutes les instructions
sont exécutées (sauf external C particulier comme `exit()` ou `longjmp()`.
Maintenant, plus difficile. Comment différencier le code non exécuté des
parties du fichier qui ne sont pas du code source ? Cela implique le
parseur. A chaque fois que le parseur trouve un bloc, il doit stocker
l'information quelque part pour avoir un ensemble de tous les blocs du
programme.
Maintenant, je vois l'implémentation comme suit: Quand le parseur trouve
un bloc, il le stocke quelque part avec sa position de début, sa
position de fin, et un identifiant. A la fin, le compilateur va créer un
fichier avec ces infos.
Pour chaque bloc, le parseur ajoutera une instruction au début du bloc.
Cette instruction sera un appel de fonction (soit une fonction C —
simple et rapide, soit Lisaac — flexible mais un peu plus difficile à
mettre en place). Cette fonction aura comme paramètre l'identifiant du
bloc exécuté.
Cette fonction va, soit à la fin du programme, soit directement pour
chaque bloc, écrire l'information que le bloc a bien été exécuté.
Et ensuite, on écrit un outil pour faire la correspondance entre les
deux fichiers, et c'est fini !
*Conclusion*
Et comme ça, on aura un compilateur robuste.
Et ça peut aussi être pratique pour détecter le code mort depuis
longtemps qui n'a plus qu'à être nettoyé, Benoît va aimer ça je pense.
Mildred
--
Mildred Ki'Lya
╭───────── mildred593@online.fr ──────────
│ Jabber, GoogleTalk: <mildred at jabber.fr>
│ Website: <http://ki.lya.online.fr> GPG ID: 9A7D 2E2B
│ Fingerprint: 197C A7E6 645B 4299 6D37 684B 6F9D A8D6 9A7D 2E2B
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/lisaac-devel/attachments/20100306/29c749c4/attachment.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.alioth.debian.org/pipermail/lisaac-devel/attachments/20100306/29c749c4/attachment.pgp>
More information about the Lisaac-devel
mailing list