TUTORIEL ALGO/METHODES 
Développer avec les tests unitaires
Le Test-Driven Development cherche à inverser le cycle de développement habituel pour aider le développeur à concevoir des programmes plus clairs et plus simples. (18/11/2004)

Il y a presque autant de méthodes et paradigmes de développement que de langages de programmation, mais certains méritent que l'on s'y intéresse plus qu'à d'autres, tant leur apport au quotidien du développeur est démontré. Le Test-Driven Development (développement guidé par le test), ou TDD, est de ceux-ci. Nous l'avions d'ailleurs déjà rapidement abordé lors de notre article sur le test logiciel, mais nous prenons ici le temps de l'étudier plus avant.

Description
Une explication en quelques mots du TDD ? Cela pourrait être : "on écrit les tests avant d'écrire le code qui est testé". Bien qu'existant depuis de nombreuses années, les récents ouvrages sur l'eXtreme Progamming (XP), dont les tests unitaires sont une pierre angulaire, ont largement contribué à sa nouvelle popularité.

Le cycle habituel de développement, depuis une éternité, est le suivant : "concevoir, programmer, tester, débuguer, re-tester, re-débuguer, etc", trop souvent ad vitam eternam. Le TDD propose d'inverser cette tendance, afin si possible d'éliminer, ou au moins de réduire grandement, le cycle de test et de débogage.

Pour ce faire, il place le test avant toute écriture de code : après avoir conçu sur papier son application, le développeur écrit un test pour, par exemple, une classe de son application, est seulement après avoir terminé ce test, écrit la classe qu'il teste. Le but n'est plus d'écrire du code, mais d'écrire le code le plus simple possible capable de passer le test. Plus globalement, cette méthode doit amener le développeur à faire ressortir les fonctionnalités réellement nécessaires à la classe, plutôt que celles qui semble utiles selon lui.

Le principe de cette méthode consiste à écrire chaque test un a un, avec la classe qui l'accompagne. Une fois que la classe passe correctement le test, on la teste avec les éléments qui s'y rapportent (et leurs propres tests), puis on passe au test suivant (et à la classe qu'il teste).
Il faut faire attention d'avancer pas à pas (ou plutôt, test/classe à test/classe), et tester à chaque étape : ainsi, si un test ne passe pas (provoque un échec), c'est que le code que l'on vient d'écrire pose problème - on le modifie alors immédiatement pour que la classe passe le test.
Si le test provoque une erreur plutôt qu'un échec, il faut d'abord s'assurer que le test renvoie bien un échec dans un cas choisi comme faux, puis re-tester - et modifier la classe si l'erreur se produit toujours.

Et si un test est mal écrit ? La solution la plus rapide consiste, après avoir écrit le test, à écrire un bout de code qui fera forcément rater le test. Si le test passe malgré tout, il faut le revoir.
Ce cycle porte l'appellation "red/green/refactor ". Les développeurs qui utilisent des outils de test logiciels, comme JUnit, reçoivent en réponse au lancement de leurs tests une réponse claire : soit rouge (le teste ne passe pas), soit vert (le test passe). Si c'est rouge, il faut remanier le code (refactor).

Quelques avantages du TDD
Cette méthode de programmation, loin d'être révolutionnaire ni même nouvelle mais se révélant souvent extrêmement utile, offre plusieurs avantages aux développeurs souhaitant être rigoureux :

1) Les bugs sont trouvés plus vite : cela semble une évidence, mais écrire une classe par rapport à un test permet de s'assurer que la classe fait bien ce que l'on attend d'elle. Par ailleurs, enchaîner développement du test/développement de la classe/test permet de repérer aussi le code fautif, plutôt que d'attendre la complétion de nombreuses classes reliées entre elles et pouvant par leurs complexités additionnées cacher un bogue pourtant simple.
Au fur et à mesure du développement, chaque classe dispose de son propre test, et chaque test correspond à une classe donnée. Un test qui échoue ne peut donc signifier une erreur que dans une classe…

2) Il oblige le développeur à prendre en compte le plus de possibilités dans ses tests. Il est plus facile d'écrire un test qui prenne en compte un grand nombre de possibilités, que de concevoir du premier coup un code qui les prenne d'entrée de jeu en compte. Le temps de développement se réduit ainsi.

3) Etant donné que le code est écrit pour être testé, le développeur est incidemment obligé de mieux concevoir ses classes. Le code en devient quasi-automatiquement plus propre, plus lisible, plus facile à isoler et à modifier.

4) Les tests viennent habituellement à la fin de la phase de développement, prennent du temps et n'apporte le plus souvent que des mauvaises nouvelles. Commencer par écrire les tests permet de les automatiser, donc de gagner du temps… sur la phase de tests.

Notez bien que cela ne permet pas de repérer tous les bugs, mais bien ceux issus de fautes d'inattention… et donc qui font généralement perdre un temps mieux utilisé à résoudre des bugs plus sérieux. Le TDD n'est évidemment pas une formule magique qui élimine automatiquement tous les bugs.

Comment s'y prendre
La méthode est donc d'inverser les principes acquis : on commence par écrire, en quelque sorte, l'utilisateur de la classe. Cela permet de définir ses besoins (plutôt que les besoins de la classe), donc d'y répondre en adaptant la classe aux besoins du test, ce de la manière la plus simple possible, et en commençant par un code imparfait afin de s'assurer que le test remarque les possibles erreurs (échec, et non erreur).

  Forum

Réagissez dans les forums de JDN Développeurs

Les grands projets comptent un grand nombre de classes, souvent plus que ce qu'un développeur peut retenir. Il devient alors nécessaire de tester le code de manière automatique, et c'est là qu'interviennent des outils comme Ant et JUnit.
Ant est un outil de compilation automatique, tandis que JUnit est un framework de test automatique. Les deux combinés permettent de lancer l'ensemble des tests créés, et si ceux-ci passent avec succès, de compiler l'application automatiquement. Le projet peut ainsi obtenir des "nightly-builds", compilation réalisée pendant la nuit pour ne pas gêner le développement, que l'on peut en théorie lancer, voire utiliser, afin de découvrir des bugs moins automatiquement discernables.

Nous aborderons le coté pratique du test unitaire dans un prochain tutoriel.

 
Xavier Borderie, JDN Développeurs
 
Accueil | Haut de page
 
 





Quand achetez-vous le plus en ligne ?
Du lundi au vendredi
Le samedi
Le dimanche

Tous les sondages