Manger, dormir et respirer les tests unitaires / TDD / BDD

J’écris des tests unitaires tout en écrivant des API et des fonctionnalités de base. Mais je veux être le fanboy cool qui mange, dort et respire TDD et BDD. Quel est le meilleur moyen de démarrer correctement avec TDD / BDD? Des livres, des ressources, des frameworks, des meilleures pratiques?

Mon environnement est Java backend avec l’interface Grails, intégré à plusieurs services Web et bases de données externes.

    Un bon endroit pour commencer est la lecture de blogs. Ensuite, achetez les livres des personnes qui bloguent. Certains que je recommanderais fortement:

    “Oncle Bob” Martin et les gars d’Object Mentor: http://blog.objectmentor.com/

    PS obtenir Bobs book Clean Code:

    http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882

    Mon ami Tim Ottinger (ancien mec de Object Mentor) http://agileinaflash.blogspot.com/ http://agileotter.blogspot.com/

    Les gars de Jetbrains: http://www.jbrains.ca/permalink/285

    J’ai ressenti le besoin de développer cela, car tout le monde semble vouloir vous donner son opinion sur TDD et ne pas vous aider dans votre quête pour devenir un Jedi-Ninja. Le Michael Jordan de TDD est Kent Beck. Il a vraiment écrit le livre là-dessus:

    http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530

    il blogue aussi à:

    http://www.threeriversinstitute.org/blog/?p=29

    Parmi les autres “célèbres” partisans de TDD figurent:

    • Tim Bray
    • Martin Fowler
    • Ward Cunningham

    Tous sont des gens formidables à suivre. Vous devriez également envisager d’assister à des conférences comme Agile 2010, ou Software Craftsmanship (cette année, elles ont eu lieu en même temps à Chicago).

    Je n’aime pas quand les gens disent: “La pratique X n’est jamais mauvaise; si ça ne marche pas, vous ne le faites pas correctement”. Désolé, il a la même sensation que tout autre dogme religieux trop zélé. Je ne l’achète pas

    Je suis d’accord avec ces gens qui disent que l’objective devrait être la meilleure solution que votre temps et votre argent peuvent offrir.

    Toute personne qui s’oppose à TDD ne devrait pas être automatiquement accusée de ne pas tenir compte de la qualité. (“Alors, quand as-tu arrêté de battre ta femme?”) Le fait est que le logiciel contient des bogues et que le coût de leur élimination doit être mis en balance avec les avantages.

    La même chose vaut pour la fabrication. Les tolérances sur les dimensions et les finitions sur les surfaces ne sont pas toutes les mêmes, car parfois une tolérance étroite et une finition miroir ne sont pas garanties.

    Oui, j’écris des tests unitaires, même si ce n’est pas souvent avant d’écrire le cours. J’ai vu l’effet des tests sur le design. Je mesure et regarde la couverture du code. Si je trouve que ma couverture n’est pas acceptable, j’écris plus de tests. Je comprends les avantages d’un filet de sécurité constitué de tests unitaires pour la refactorisation. Je suis ces pratiques même lorsque je travaille seul, parce que j’ai expérimenté les avantages de première main. J’ai compris.

    Mais je regarderais de travers tous les coéquipiers qui ont commencé à me surprendre à propos de “manger, dormir et tester des appareils respiratoires et du TDD”.

    Mon manager dit que la seule façon de me faire une promotion est de pouvoir faire équipe avec TDD / BDD.

    Avez-vous déjà pensé que peut-être cela vous fait-il sonner comme une sucette? Avez-vous trouvé que votre harcèlement a aliéné le rest de votre équipe?

    Cette réponse pourrait me faire perdre quelques points de réputation, mais il fallait le dire.

    Je pense qu’une meilleure approche serait de la pratiquer vous-même et de laisser les autres voir les bénéfices. Mener par l’exemple. Ce sera beaucoup plus convaincant que de courir la bouche.

    Bon sang, Grails a intégré la génération de tests. Si vous travaillez dans une équipe qui utilise Grails, combien de ventes supplémentaires sont nécessaires?

    Meilleure pratique IMHO: Faites ce qui est pratique et pas seulement parce que c’est un processus. N’oubliez pas quel est l’objective de l’écriture d’applications et, dans le monde des affaires, il ne s’agit pas d’écrire des tests. Ne vous méprenez pas, ils ont leur place, mais ce ne devrait pas être l’objective.

    Trouvez quelqu’un qui fait du TDD / BDD et combinez le programme avec eux.

    Les mésortingques sont, à mon humble avis, le meilleur moyen d’obtenir d’ici à là. Gardez une trace de la qualité de votre code, conservez des deltas de complexité de code pour chaque validation, utilisez des programmes de test qui surveillent votre code et réexécutez constamment les tests correspondants. Ne laissez jamais des longueurs de test supérieures à quelques lignes, afin que tous vos outils fonctionnent correctement. Et je recommande une fois par mois, prenez une journée de congé pour exécuter votre code via un testeur de mutation. Ce jour devrait être consacré uniquement à la rédaction de tests. Toutes ces choses vous apporteront des ennuis si vous ne faites pas déjà du bon TDD. Apprenez de la douleur et en un rien de temps, vous le ferez bien.

    Et ne jamais perdre de vue les tests: Décrire le comportement souhaité. Ils sont votre spécification exécutable. (C’est aussi pour ça que j’aime Cucumber ; maintenant, vous pouvez demander à votre PHB d’écrire vos tests pour vous! Eh bien, peut-être pas si bon, mais c’est proche!)

    “PS: Mon manager dit que la seule façon de me faire une promotion est de pouvoir envoyer l’équipe à TDD / BDD.”

    Le seul moyen réaliste de convaincre une équipe de faire quelque chose (sans vous tuer en même temps) est de leur démontrer clairement que cela leur sera bénéfique de changer leurs habitudes. En d’autres termes, écrivez le code. Beaucoup de code. Des tonnes de code. Et puis, lorsque le courrier électronique crucial modifiant radicalement la spécification arrive, montrez-leur que vous pouvez modifier facilement votre code avec le refactoring et, pire encore, parce que vous y êtes préparé avec vos tests. Le bar était vert, hack hack hack, RED BAR !!!!, hack hack hack, green bar, rentre chez toi.

    Lisez le livre de Kent Becks sur la conception pilotée par les tests. Commencez par des tests, puis faites le code. Obtenez un serveur de construction en cours d’exécution qui exécute les tests! Vous n’avez pas besoin de l’avoir pour toute l’équipe – faites-le pour vous-même et montrez-leur que cela aide.

    La prédication n’agace que les indigènes 🙂

    Je fais du TDD depuis quelques années, mais dernièrement, j’ai commencé à mieux comprendre la manière dont BDD pilotait ma conception et mon développement. Les ressources qui m’ont aidé à démarrer sur BDD ont été les premiers et le premier blog de Dan North (le «fondateur» de BDD). Jetez un coup d’œil à la présentation de BDD . Il y a aussi un wiki BDD «officiel» sur behavioriour-driven.org avec quelques bons messages qui méritent d’être lus.

    La première chose que j’ai trouvée très difficile lorsque j’ai commencé avec BDD (et que j’ai toujours trouvé un peu difficile) est de savoir comment formuler ces scénarios pour les adapter à BDD. Scott Bellware est un homme très compétent en BDD (ou Context-Spesification comme il aime le jouer) et son article intitulé Behavior-Driven Development dans Code Magazine m’a beaucoup aidé à comprendre la façon de penser de BDD et à formuler des récits d’utilisateurs.

    Je recommanderais également la conception de TekPub screencast axée sur le comportement avec Specflow de Rob Conery. Une excellente introduction à BDD et à un outil (SpecFlow) très bien adapté à la réalisation de BDD en C #.

    En ce qui concerne les ressources TDD, il y a déjà beaucoup de bonnes recommandations ici. Mais je veux juste souligner quelques livres que je peux vraiment recommander;

    • Travailler efficacement avec Legacy Code par Michael Feathers; Une lecture indispensable si vous travaillez sur un code hérité (n’est-ce pas?) Et que vous voulez le tester
    • L’art des tests unitaires: avec des exemples dans .Net par Roy Osherove; Si vous êtes nouveau aux tests unitaires, voici le livre pour vous aider à démarrer
    • Développement piloté par les tests: par exemple par Kent Beck; Si vous apprenez TDD, pourquoi ne pas l’obtenir de la source elle-même? Un bon livre – facile à lire, bonne humeur et bonnes pensées.
    • Code propre: un manuel de savoir-faire logiciel agile par Robert C. Martin; Si Kent Beck décrit les voeux de TDD, oncle Bob décrit les pourquoi .

    Pour commencer, effectuez des tests unitaires, puis renseignez-vous sur la procédure à suivre. En dernier lieu, apprenez à votre équipe comment procéder au TDD et à les intégrer – car, selon mon expérience, rien n’est plus important que de faire des tests unitaires avec l’ensemble de votre équipe.

    Vous aurez également besoin d’un processus de construction approprié – en utilisant un serveur de construction qui construirait votre code et exécuterait votre test Je recommande d’utiliser TeamCity (gratuit avec limitations).

    Apprendre à corriger les bons tests unitaires est la partie la plus difficile – en partie, vous apprendrez vous-même (tant que vous garderez les tests unitaires) et vous apprendrez tout le rest en cherchant sur Internet.

    Vous saurez que vous avez atteint votre objective lorsque vous n’écrivez PAS les tests unitaires dans le cadre du développement.

    Rappelez-vous, agile signifie que vous n’êtes pas complètement épuisé sur une méthode particulière. Si vous travaillez sur quelque chose dont les avantages de TDD ne valent pas la peine (comme faire des vérifications d’évaluation d’erreurs sur une interface Swing), n’utilisez pas TDD.

    Je ne vois pas que quiconque ait réellement exprimé que TDD ne concerne pas les tests. TDD-ing consiste à exprimer le comportement attendu avant de procéder à la modification minuscule du comportement. Cela améliore grandement la conception et permet de se concentrer de manière inédite. Vous obtenez des tests qui protègent vos futures refactorisations et une couverture de 90% gratuite.

    Pour l’apprendre, je suggérerais (en résumant ce que les autres ont dit et en ajoutant un des miens):

    1. visitez les blogs et lisez les livres mentionnés ci-dessus
    2. jumelez-vous avec quelqu’un qui maîsortingse le TDD
    3. entraine toi

    J’ai pratiqué le kata (exercice) de bowling seul environ 20 fois (environ 30 minutes chacun) avant de commencer à voir la lumière. Nous avons commencé par parsingr la description de mon oncle Bob ici . Il y a une foule de katas sur le site codingdojo.org, y compris des solutions et des discussions. Essayez les!

    Pour prendre une citation de Nike: JUST DO IT.

    Deuxième conseil: ne comptez jamais sur l’interface de quelqu’un d’autre. Toujours écrire, au niveau de chaque classe, sur l’interface que vous souhaitiez exister – écrivez un adaptateur sur l’implémentation réelle si nécessaire.

    En outre, je trouve utile d’éviter les valeurs de retour sur les méthodes et de penser au code en termes de transmission de messages plutôt qu’aux appels de fonctions.

    YMMV.

    Il y a un an, je ne savais pas trop comment faire TDD (mais je voulais vraiment (c’est frustrant)) et je n’avais jamais entendu parler de BDD … maintenant je fais les deux de manière compulsive. J’ai été dans un environnement de développement .Net, pas Java, mais j’ai même remplacé le bouton “F5 – Exécuter” par une macro pour exécuter Cucumber (BDD) ou MBUnit (TDD), selon qu’il s’agisse d’une fonctionnalité / scénario ou d’une spécification. Pas de débogueur si possible. $ 1 dans le pot si vous utilisez le débogueur (JOKING (sorte de)).

    Le processus est vraiment génial. Le cadre que nous utilisons en plus est celui de The Oracle dont j’ai eu la chance de trouver, et d’absorber des informations, et ce cadre que nous utilisons est MavenThought.

    Tout commence par BDD. Notre BDD est un concombre en pointe de rbuy de fer.

    Fonctionnalité:

    Scénario: …. Étant donné que je fais du bla …
    Quand je fais autre chose … Alors il se passe des choses merveilleuses …

    Scénario: …

    Et ce ne sont pas les tests unitaires proprement dits, mais ils pilotent la fonctionnalité, le scénario par scénario et, à son tour, les spécifications de l’unité (de test). .

    Et le TDD que nous avons utilisé est en quelque sorte un BDD, car nous examinons les comportements requirejs par le SUT (System Under Test) et un comportement est spécifié par spécification (fichier de classe “test”).

    Exemple:

    Voici la spécification pour un comportement: lorsque le système sous test est créé.

    Il existe une autre spécification (fichier de classe C # When_blah_happens) pour un autre comportement lorsqu’une propriété est modifiée, mais elle est séparée dans un fichier séparé.

    using MavenThought.Commons.Testing; using SharpTestsEx; namespace Price.Displacement.Module.Designer.Tests.Model.Observers { ///  /// Specification when diffuser observer is created ///  [ConstructorSpecification] public class When_diffuser_observer_is_created : DiffuserObserverSpecification { ///  /// Checks the diffuser injection ///  [It] public void Should_return_the_injected_diffuser() { Sut.Diffuser.Should().Be.SameInstanceAs(this.ConcreteDiffuser); } } } 

    C’est probablement le comportement le plus simple pour un SUT, car dans ce cas, lorsqu’il est créé, la propriété Diffuseur doit être identique au diffuseur injecté. J’ai dû utiliser un diffuseur concret au lieu d’un simulacre, car dans ce cas, le diffuseur est un object Core / Domain et n’a pas de notification de propriété pour l’interface. 95% du temps, nous nous référons à toutes nos dépendances comme Dep (), au lieu d’injecter la chose réelle.

    Souvent, nous avons plusieurs [It] Should_do_xyz (), et parfois un peu de configuration, par exemple jusqu’à 10 lignes de stubbing. Ceci est juste un exemple très simple avec GivenThat () ou AndGivenThatAfterCreated () dans cette spécification.

    Pour la configuration de chaque spécification, nous n’avons généralement besoin de remplacer que deux méthodes de la spécification:

    Étant donné que () ==> cela se produit avant que le SUT soit créé.

    CreatSut () ==> Nous simulons automatiquement la création du sut avec StructureMap et 90% du temps n’a pas besoin de le remplacer, mais si vous construisez un Concrete, vous devez le remplacer.

    AndGivenThatAfterCreated () => cela se produit après la création du SUT.

    LorsqueIRun () => sauf s’il s’agit d’un [ConstructorSpecification], nous l’utilisons pour exécuter UNE ligne de code correspondant au comportement que nous spécifions pour le SUT

    De plus, si le comportement de deux ou plusieurs spécifications du même SUT est commun, nous le déplaçons dans la spécification de base.

    Tout ce que je dois faire pour exécuter la spécification, c’est mettre en évidence son nom, exemple “When_diffuser_observer_is_created” et appuyer sur F5, car rappelez-vous que F5 exécute une tâche Rake soit test: feature [tag] Cela a du sens pour moi parce que chaque fois que vous lancez le débogueur, c’est à jeter, aucun code n’est créé (oh et cela coûte un dollar (blague)).

    C’est un moyen très, très propre de spécifier le comportement avec TDD et d’avoir des TUS vraiment simples et des spécifications simples. Si vous essayez de coder les cow-boys et que vous écrivez la merde du SUT avec des dépendances dures, etc., vous ressentirez la douleur d’essayer de faire du TDD et d’en avoir marre / abandonner OU mordre la balle et le faire correctement.

    Et voici le véritable SUT. Nous avons eu un peu de fantaisie et nous avons utilisé PostSharp pour append la propriété notify modifiée sur le diffuseur, d’où le nom Post.Cast <>. Et encore une fois, c’est pourquoi j’ai injecté un béton plutôt que de la maquette. Quoi qu’il en soit, comme vous pouvez voir le comportement manquant défini dans une autre spécification, c’est quand quelque chose change sur le diffuseur.

     using System.ComponentModel; using MavenThought.Commons.Events; using PostSharp; using Price.Displacement.Core.Products; using Price.Displacement.Domain; namespace Price.Displacement.Desktop.Module.Designer.Model.Observers { ///  /// Implementation of current observer for the selected product ///  public class DiffuserObserver : AbstractNotifyPropertyChanged, IDiffuserObserver { ///  /// gets the diffuser ///  public IDiffuser Diffuser { get; private set; } ///  /// Initialize with a diffuser ///  /// The diffuser to observe public void Initialize(IDiffuser diffuser) { this.Diffuser = diffuser; this.NotifyInterface().PropertyChanged += (x, e) => this.OnPropertyChanged(e.PropertyName); } ///  /// Gets the notify interface to use ///  /// The instance of notify property changed interface protected INotifyPropertyChanged NotifyInterface() { return Post.Cast((Diffuser)Diffuser); } } } 

    En conclusion, ce style de développement BDD / TDD est important. Cela a pris un an mais je suis un converti total en tant que mode de vie. Je ne l’aurais pas appris par moi-même. J’ai ramassé tout de The Oracle http://orthocoders.com/ .

    Pilule rouge ou bleue, à vous de choisir.