décembre
2009
Dans un billet précédent j’avais expliqué les bases de NBehave, outil qui permet de faire du BDD (Behavior Driven Development) en .NET. Je vais maintenant montrer un exemple plus complet, développé à l’occasion des Coding Dojos du Club Agile Rhône-Alpes juste avant la pause estivale. Durant les dojos, Emmanuel Etasse nous avait proposé de développer un jeu du pendu, et avait joué le rôle de Product Owner. Nous avions identifié 3 users stories (gérer une lettre, gérer deux lettres successives, gérer la fin de jeu), chacune avec plusieurs scénarios. Dans ce billet je vais montrer le code correspondant, et expliquer pourquoi, après cette expérimentation, l’approche NBehave ne me convient pas trop, et pourquoi je suis beaucoup plus intéressé par une approche de type Cucumber sur IronRuby.
Voici tout d’abord la première user story, qui permet de démarrer le travail en décrivant le traitement d’une première lettre proposée par l’utilisateur dans le jeu du pendu. La démarche que nous avons suivie était : description des scenarios avec un format libre basé sur des Given When Then, programmation dans NBehave, exécution de NBehave et obtention de la sortie texte. Ce que je montre ci-dessous est le résultat final, la sortie texte de NBehave :
Story: Handle a first letter Narrative: As a user I want to enter a letter So that I will know if the letter is in the word Scenario 1: user has entered a wrong letter Given the secret word: SANGLIER And the remaining count: 6 When the user enters: Z Then the displayed word should be: ******** And the remaining count should be: 5 Scenario 2: user has entered a good letter Given the secret word: SANGLIER And the remaining count: 6 When the user enters: A Then the displayed word should be: *A****** And the remaining count should be: 6
Je trouve cette description assez claire, cela montre bien le comportement attendu, c’est compréhensible par d’autres personnes que des développeurs, donc c’est assez satisfaisant.
Voici maintenant le code nécessaire pour faire passer cette story. Si besoin, vous pouvez revoir le billet précédent qui explique plus précisément la syntaxe NBehave.
[Story] public void handle_a_first_letter() { var story = new Story("Handle a first letter"); story .AsA("user") .IWant("to enter a letter") .SoThat("I will know if the letter is in the word"); Game game = null; story .WithScenario("user has entered a wrong letter") .Given("the secret word", SECRET_WORD, secret => game = new Game(secret)) .And("the remaining count", REMAINING_COUNT, remaining => game.Remaining = remaining) .When("the user enters", 'Z', letter => game.ProposedLetter = letter) .Then("the displayed word should be", "********", expectedValue => Assert.AreEqual(expectedValue, game.DisplayedWord)) .And("the remaining count should be", 5, expectedValue => Assert.AreEqual(expectedValue, game.Remaining)) .WithScenario("user has entered a good letter") .Given("the secret word", SECRET_WORD, secret => game = new Game(secret)) .And("the remaining count", REMAINING_COUNT, remaining => game.Remaining = remaining) .When("the user enters", 'A', letter => game.ProposedLetter = letter) .Then("the displayed word should be", "*A******", expectedValue => Assert.AreEqual(expectedValue, game.DisplayedWord)) .And("the remaining count should be", REMAINING_COUNT, expectedValue => Assert.AreEqual(expectedValue, game.Remaining)) ; }
L’écriture du code ci-dessus a conduit à identifier une classe Game, ainsi que son interface. Mais je ne suis pas forcément très satisfait de cette interface. J’aurais préféré que la classe Game comporte un constructeur qui oblige à fournir le mot secret et le nombre de coups restant en une seule opération, et que la propriété Remaining soit en lecture seule. Toutefois je n’ai pas réussi à trouver comment faire avec NBehave pour écrire quelque chose comme
.Given("the secret word", SECRET_WORD, " and the remaining count", REMAINING_COUNT, (secret,remaining) => game = new Game(secret,remaining))
Je rate peut-être quelque chose d’évident, merci de commenter ce billet si vous savez comment faire.
D’autre part le code ci-dessus illustre mon premier grief vis-à-vis de l’approche NBehave : le manque de lisibilité du code dû au mélange des éléments textuels de la sortie avec des éléments de code. J’ai mis le « code pur » à chaque fois sur une ligne, afin de le séparer des éléments plus textuels de NBehave, pour essayer d’améliorer la lisibilité.
Un autre grief est que le code ci-dessus n’est compréhensible et modifiable que par un développeur, l’utilisateur ou le testeur n’étant concerné que par la sortie textuelle. Je trouve que c’est une grosse limitation. Si le testeur veut apporter une modification (modifier ou ajouter un scénario par exemple) il devra absolument passer par un développeur s’il n’a pas des connaissances de base en programmation. C’est irréaliste dans notre situation, les testeurs sont des spécialistes métiers sans expérience en programmation.
Je suis donc très sensible à l’argument développé par Joseph Wilk dans sa présentation Cucumbered : la plupart des utilisateurs ne veulent pas entendre parler de la technologie que nous utilisons pour réaliser les tests. En fait nous devons arriver à un stade où nous pouvons envoyer un cas de test à un utilisateur par mail, il doit le comprendre aisément sans voir un quelconque jargon informatique, il doit pouvoir le compléter et le renvoyer par mail. Le contenu de ce mail sera intégré tel quel dans nos tests existants. Voilà un critère de succès pour une bonne relation avec les utilisateurs.
Pour ce que j’ai vu pour l’instant de NBehave, cet outil ne passe pas ce critère. Il est toutefois possible que je n’ai pas tout bien compris (il n’y a pas beaucoup de documentation et d’exemples sur NBehave), n’hésitez pas à corriger mon propos si besoin.
Par contre les démonstrations de Cucumber durant les dojos (merci Grégory notamment) laissent à penser que Cucumber peut passer ce critère, c’est ce que je vais explorer dans de prochains billets. Comme nous avons une grosse base de code en .NET, je vais également explorer l’utilisation de Cucumber sur du code .NET.
2 Commentaires + Ajouter un commentaire
Commentaires récents
- Des tableaux pour l’intégration d’un équipier dans une équipe Scrum dans
- Rétrospectives, la directive première dans
- Des tableaux pour l’intégration d’un équipier dans une équipe Scrum dans
- Des tableaux pour l’intégration d’un équipier dans une équipe Scrum dans
- Des tableaux pour l’intégration d’un équipier dans une équipe Scrum dans
Effectivement mon essai date d’avant l’été, et d’après ce que je viens de lire sur nbehave.org, le fonctionnement à maintenant l’air d’être proche de Cucumber. Je vais donc essayer d’adapter mon exemple.
Merci pour l’info.
Bruno
NBehave vient de passer en version 4.5, et l’interface fluent est devenu « obsolète »
http://nbehave.org/
Il existe aussi un autre projet .net se basant sur Cucumber
http://gasparnagy.blogspot.com/search/label/SpecFlow
Pour l’instant je ne les ai pas encore testé, je ne peux donc pas te faire de retour.