<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body text="#000000" bgcolor="#ffffff">
Salut,<br>
<br>
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).<br>
<br>
<br>
C'est comme ça que j'ai découvert Cucumber, un toutil pour faciliter
les tests<br>
<a href="http://cukes.info/">http://cukes.info/</a><br>
<br>
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.<br>
<br>
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.<br>
<br>
Des exemples de fonctionnalités cucumber:<br>
<a
href="http://git.debian.org/?p=lisaac/compiler.git;a=tree;f=features;hb=HEAD">http://git.debian.org/?p=lisaac/compiler.git;a=tree;f=features;hb=HEAD</a><br>
<br>
<b>Les fonctionnalités cucumber, comment ça marche</b><br>
<br>
(regardez quelques fonctionnalités cucumber avant de continuer<br>
<ul>
<li>Tout d'abord, la première partie est entièrement descriptive
(après "Feature:")</li>
<li>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.</li>
<li>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.</li>
<li>"Given" met en place le contexte du scénario<br>
</li>
<li>"When" exécute des actions<br>
</li>
<li>"Then" teste le résultat de ces actions<br>
</li>
</ul>
<br>
Chacune des lignes sont associées à du code ruby à travers des
expressions régulières. Ce code se trouve dans
features/step_definitions/.<br>
<br>
<b>Exécuter des fonctionnalités avec cucumber</b><br>
<br>
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.<br>
<br>
Ensuite, c'est très simple:<br>
<br>
gem install cucumber<br>
gem install rake<br>
<br>
Et on peut commencer à jouer. Dans le dossier du compilateur,
exécutez:<br>
<br>
cucumber features/*.feature<br>
<br>
Et toutes les fonctionnalités vont être exécutées. Et il y a un joli
rapport en couleurs.<br>
<br>
<b>Couverture de code</b><br>
<br>
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.<br>
<br>
Mais aucun pour Lisaac.<br>
<br>
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:<br>
<br>
<ol>
<li>On compile du code en ajoutant une instrumentation pour la
couverture de code<br>
</li>
<li>On exécute le code instrudmenté<br>
</li>
<li>L'exécution du code produit des fichiers permettant de constater<br>
</li>
<ul>
<li>Quelles lignes sont exécutées<br>
</li>
<li>Quelles lignes ne sont pas exécutées<br>
</li>
<li>Quelles lignes ne sont pas exécutables (commentaires, ...)<br>
</li>
</ul>
<li>On lance un outil pour convertir ces infos brutes en joli
rapport HTML</li>
</ol>
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()`.<br>
<br>
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.<br>
<br>
<br>
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.<br>
<br>
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é.<br>
<br>
Cette fonction va, soit à la fin du programme, soit directement pour
chaque bloc, écrire l'information que le bloc a bien été exécuté.<br>
<br>
Et ensuite, on écrit un outil pour faire la correspondance entre les
deux fichiers, et c'est fini !<br>
<br>
<b>Conclusion</b><br>
<br>
Et comme ça, on aura un compilateur robuste.<br>
<br>
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.<br>
<br>
<br>
Mildred<br>
<br>
<pre class="moz-signature" cols="72">--
Mildred Ki'Lya
╭───────── mildred593@online.fr ──────────
│ Jabber, GoogleTalk: <a class="moz-txt-link-rfc2396E"
href="mailto:mildred@jabber.fr"><mildred@jabber.fr></a>
│ Website: <a class="moz-txt-link-rfc2396E"
href="http://ki.lya.online.fr"><http://ki.lya.online.fr></a> GPG ID: 9A7D 2E2B
│ Fingerprint: 197C A7E6 645B 4299 6D37 684B 6F9D A8D6 9A7D 2E2B
</pre>
</body>
</html>