26th
MAR

Alt.Net Paris #11 : TDD, compte rendu par Clément Bouillier

Posted by clement under Comptes Rendus Paris

Cette session Alt.Net regroupait de nouveau une trentaine de participants autour de Djamel et Frédéric qui nous présentaient le développement piloté par les tests (TDD, Test Driven Development). Les participants avaient majoritairement une coloration TDD, mais nous avions nos « avocats du diable » forts utiles pour alimenter la discussion comme d’habitude (Alt.NET serait bien triste sans cela).

La discussion a commencé par une question classique mais logique : pourquoi des tests ou pourquoi pas ? Au premier abord, la réponse amène beaucoup de « stéréotypes » (cher, long, utilité…), des points qui peuvent au demeurant être légitimes dans certains cas particuliers (ce sujet n’a pas été traité plus avant). Mais la réponse apporte surtout une bonne introduction à la pratique.

La suite consista à faire les premiers pas en répondant aux questions : quand tester et comment s’y prendre ? Pour aboutir à des points fondamentaux pas forcément évidents au premier abord : le TDD ce n’est pas qu’écrire des tests unitaires, mais c’est une pratique par laquelle, pour bien faire, il sera nécessaire de faire usage d’un ensemble de bonnes pratiques.

Pourquoi ne pas faire des tests ?

En faisant un rapide sondage de l’audience, nous avons mis en évidence que de nombreuses objections sont couramment mises en avant : « c’est trop cher », « ça prend trop de temps », « je les ferais plus tard » (= jamais comme souligné dans la presentation), « comment m’assurer que mes tests vérifient ce qui est spécifié et pas une fausse interprétation » (intention du développeur VS besoin du client), « ce n’est pas faisable dans mon cas », « qu’est-ce que je teste », « mon code va changer, je le testerai quand il sera stable »…

L’idée de la session était de contredire certains de ces points, de démontrer les forces de la pratique, mais pas forcément de batailler contre des avis tranchés sur la question. Pour cela, un exemple simple a été utilisé : implémenter un MasterMind.

Quand tester ?

Comme cela a été dit plusieurs fois, l’objectif des tests n’est pas d’avoir des indicateurs de couverture maximaux mais d’avoir un code correspondant le plus à ce que le développeur s’attend à avoir, i.e. son intention donc et non malheureusement le besoin client, l’interprétation de celui-ci ne pouvant être cadré par le TDD…il n’y a pas de magie.

La question qui en découle est : qu’est-ce qui doit être testé ? Il n’est pas nécessaire de tester du code sans intérêt particulier du point de vue de sa complexité (il sera toujours temps d’ajouter des tests s’il se complexifie). De même qu’elle est granularité des tests, est-ce que je parle de tests unitaires, de tests d’intégration, de tests fonctionnels…mais ce point est un sujet un peu plus avancé qui fut traité rapidement.

Les tests se révèlent également un outil puissant dans le cas des changements inéluctables d’une application (liés au changement du besoin ou à des remaniements du code), en fournissant une « base de connaissance » pour la non-régression.

La question du temps passé aujourd’hui en debugging répétitif et autres applications consoles satellites peu réutilisables a aussi été soulevée. Pourquoi ne pas considérer que ce temps est un temps qu’il vaut mieux consacrer à des tests réutilisables i.e. automatisables et rapides. Cela n’exclue pas le debugging mais en réduit notablement les excès et même apporte une base permettant un debugging plus aisé (en debuggant les tests).
Ce sujet a été un point de controverse assez discuté pendant la session : est-ce que je sais ce que je veux a priori (ce qui me permet de démarrer mes premiers tests) ou est-ce le fait de coder qui révèle l’intention ? Je dirais après réflexion que la réponse est les deux. Mais le point soulevé est que la seconde sans la première revient à tomber dans le travers de s’attaquer au cas le plus complexe, à « se perdre » dans la conception du design miracle et des algorithmes traitant tous les cas, et cela rejoins un second point : lorsqu’on agit ainsi, on risque inévitablement d’introduire des bugs au fur et à mesure de la complexification du code née de notre cerveau de codeur/concepteur tout puissant (un peu mégalo… ;) ). Tant qu’on n’en a pas tout va bien, le jour où cela arrive c’est la chute libre : aucun filet pour se rattraper…

Comment s’y prendre ?

L’approche TDD demande donc un peu d’humilité en commençant par des tests simples (au développeur de bien évaluer la simplicité minimale, dans l’exemple donné, on était forcément un peu caricatural, mais l’idée était là). On part donc d’une intention simple a priori fondée. Par la suite, on complexifie de manière incrémentale en écrivant le test qui révèle l’intention à chaque étape (analogie avec l’alpiniste qui à pose un mousqueton régulièrement, nécessite également de réaliser un check in à chaque état stable de nos développement). On développe donc l’intention en développant, mais en développant les tests d’abord.
L’avantage est également de mettre à jour l’approche utilisée et de documenter le code produit explicitement (notion de spécifications exécutables).
Ceci a été démontré par Frédéric via leur exemple relativement simple, et c’est un point assez crucial du TDD à mon sens.

Un autre point a été soulevé : il n’est pas contradictoire d’esquisser quelques diagrammes UML afin de cadrer notre intention globale, mais il serait contradictoire d’être dans une démarche « pure MDA », structurant et contraignant le design en premier lieu sans passer par les tests.

Ce dernier point démontre l’intérêt de commencer par les tests, ils doivent nous forcer à ne pas aller trop vite et à découper notre travail. Je pense sincèrement que c’est également un argument par rapport au temps et au coût lié au TDD, nous perdons régulièrement du temps à vouloir concevoir/développer trop compliqué.

Dans l’exemple du MasterMind, plusieurs points essentiels liés à l’application du TDD sont ressortis de la discussion (formulation assez proche de la présentation) :

  • La démarche est un cercle vertueux : intention > code du test (ne compile pas) > code qui ne fonctionne pas (test rouge) > code qui fonctionne (test vert) > remaniement (refactoring) pour répondre à une intention plus complexe
  • En découle qu’il faut commencer par des cas simples Vs penser aux cas les plus complexes, le cercle vertueux nous amenant aux plus complexes
  • Un test doit être bien écrit = AAA : Acteur + Action + Assertions (attention aux tests sans assertions !!)
  • Ne pas faire un modèle trop complexe, laisser l’évolution des intentions guider le remaniement du code pour aboutir au modèle le plus juste (et pas forcément le plus générique, le plus beau…ce qui rappelle le principe YAGNI).
  • Le remaniement à une étape donnée doit se faire soit sur les tests, soit sur le code de production, l’un servant de filet de sécurité à l’autre.
  • Un bug doit systématiquement amener à écrire un test vérifiant la correction (approche la mieux adaptée au legacy code).
  • Jouer l’ensemble des tests (automatiques et rapides afin de ne pas perdre de temps)

Quelques remarques connexes ont vu le jour également. Notamment est-ce que TDD est contradictoire avec la programmation par contrats? Ou plutôt complémentaire? C’est plutôt la seconde proposition qui retenait l’attention.

TDD est une pratique englobant beaucoup de pratiques

Le principal point est que le TDD nécessite rapidement de s’intéresser à des pratiques de design courantes et considérées comme bonnes qu’il n’est pas toujours facile de mettre en place sans cette approche.
Le débat fut animé sur la question pendant la session. Mon avis étant qu’il y a beaucoup de développeurs expérimentés, « experts » et autres personnes aux titres élogieux – surtout dans la communauté .NET – et qui n’ont pas la moindre idée de toutes ces bonnes pratiques. Elles les balayent systématiquement et orgueilleusement en les sacrifiant sur l’autel de la performance ou de la productivité (NDJ : enfin… c’est ce qu’elles pensent!), et ce évidemment au détriment de la maintenabilité…

Ainsi, Frédéric et Djamel nous ont parlé de couplage faible à l’aide d’injection de dépendance (voir Fowler) permettant de faciliter les tests unitaires, de différents patterns notamment pour WPF : M-V-VM et les Converter, ou encore des plus classiques (GoF) comme l’Abstract Factory (fabrique abstraite en français/québécois)… Tout cela permet de faciliter grandement l’approche des tests et devrait être utilisé afin de bénéficier pleinement des bénéfices de la pratique.

Via les exemples WPF, on a pu voir un peu les limites du TDD au niveau du test de l’interface, bien que l’intérêt du pattern M-V-VM permette de s’en accommoder tout en structurant avantageusement son code. Des solutions existent tout de même, j’ai rapidement vu White…à creuser.

On peut parler du bouchonnage ou Mock/Stub (voir Fowler pour la différence Mocks/Stubs). L’idée étant d’utiliser de faux objets dans les graphes de dépendances de l’objet testé afin de limiter les effets de bord liés à ces dépendances par rapport à l’intention testée.

Enfin, deux sujets dont on aurait pu parler plus profondément (mais le sujet était déjà assez touffu) : l’intégration continue qui pouvait être entraperçu dans les mots souvent répétés comme « outillage » ou « automatisation », et la couverture de code qui a été abordée rapidement. Je rajouterais sur ce dernier sujet qu’il est très important de garder en tête que ces métriques (comme toutes les autres) sont à prendre avec des pincettes, ne surtout pas croire que 100% de couverture = code parfait. Il est important de toujours garder en tête les problématiques liées à la combinatoire des données d’entrée à nos tests qui restreint ce point de vue.

Conclusion

Pour résumer, je reprendrais celle de la présentation de Djamel et Frédéric (que l’audience a remerciée sincèrement de cette présentation de qualité et du dialogue établi).

Le TDD est :

  • pas forcément plus cher ou plus long à mettre en oeuvre,
  • applicable (presque) dans tous les cas

Le TDD apporte :

  • Un code mieux documenté
  • La possibilité de modifier sans risque (non-régression)
  • Un code au design le plus juste et flexible (dans un contexte de changement permanent inhérent aux sujets traités dans les projets informatiques)

A noter que TDD est une pratique qui se marie très bien au DDD présenté à Alt.NET France en décembre (cf. Eric Evans et/ou Jimmy Nilson, je n’ai lu que le 2nd).

Références

Un document de 70 pages fort intéressant reprenant beaucoup d’éléments discutés lors de la rencontre : Foundation of programming

Greg Young sur Design by Contracts et TDD à l’USI2009 (à voir pour les chanceux ;) )

Livres sur DDD intégrant l’approche TDD : Domain-Driven Design, Eric Evans et Applying Domain Driven Design and Patterns, Jimmy Nilson

Enfin un grand merci à Octo pour nous avoir accueilli et pour cette présentation…tout le monde trouvera le site d’Octo, faisons un peu de pub pour l’USI2009 où on pourra retrouver Greg et Frédéric notamment.

Rq : Frédéric, pourrais-tu nous donner le lien vers la présentation de Greg Young sur TDD que tu as vivement recommandée…(recherche rapide sans succès…), ainsi qu’un lien vers les slides éventuellement ?

Tags:

20th
FéV

ALT.Net Paris #11 : Test Driven Development

Posted by Julien under Rencontres Paris

La 11eme édition d’ALT.Net Paris sera organisée chez Octo Technology, société de conseil particulièrement active dans le domaine de l’agilité et de l’open source. Leur blog est d’ailleurs une source d’information passionnante.

A cette occasion, Djamel Zouaoui nous parlera de Test Driven Development ou TDD.

Octo est situé à l’adresse suivante : 50 avenue des champs Elysées, 75008 Paris. L’horaire exacte est à confirmer d’ici là, mais la présentation devrait commencer aux alentours de 19h30 – 20h. Plus d’infos dans les jours qui viennent !


Agrandir le plan

En espérant vous voir nombreux pour un sujet qui s’annonce très intéressant !

Edit : La rencontre est repoussé au 25 mars en raison de la journée de grève prévue le 19. Le rendez-vous est fixé à 19h, et la présentation débutera à 19h30. Djamel sera également épaulé par Frédéric Schäfer.

Merci d’annoncer votre présence sur la liste de discussion !

Edit : Vous pouvez maintenant indiquer votre présence grâce au lien suivant :

Tags:
Entrepreneur Press Wordpress Theme