Question

Je rédige des tests unitaires lors de la rédaction 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, ressources, cadres, meilleures pratiques?

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

Était-ce utile?

La solution

Un bon point de départ est la lecture de blogs. Ensuite, achetez les livres des personnes qui bloguent. Certains je recommande fortement:

& "Oncle Bob &" Martin et les gars d'Object Mentor: http://blog.objectmentor.com/

P.S. Obtenir le code de nettoyage du livre Bobs:

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

Mon ami Tim Ottinger (ancien mec d'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 d’élargir ce point, car tout le monde semble vouloir simplement vous donner son opinion sur le TDD et non 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 à ce sujet:

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

il blogue également sur:

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

autre " célèbre " Les partisans de TDD incluent:

Ce sont tous des gens formidables à suivre. Vous devriez également envisager d'assister à des conférences comme Agile 2010, ou Software Craftsmanship (cette année, elles se sont tenues simultanément à Chicago).

Autres conseils

Je n'aime pas que les gens disent & "La pratique de X n’est jamais mauvaise; si cela ne fonctionne 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'objectif devrait être la meilleure solution à votre temps et à votre argent.

Quiconque s'oppose au TDD ne doit pas automatiquement être accusé de ne pas tenir compte de la qualité. (" Alors quand avez-vous cessé de battre votre femme? ") Le fait est que le logiciel contient des bugs et que le coût de leur élimination doit être évalué en fonction des avantages.

Il en va de même pour la fabrication. Les tolérances sur les dimensions et les finitions sur les surfaces ne sont pas toutes identiques, car une tolérance étroite et une finition miroir ne sont parfois pas garanties.

Oui, j’écris des tests unitaires, même si ce n’est pas souvent le cas avant d’écrire. J'ai vu l'effet des tests sur la conception. Je mesure et regarde la couverture de 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, car j'ai expérimenté les avantages de première main. Je comprends.

Mais je regarderais de côté n'importe quel coéquipier qui aurait commencé à me déranger au sujet de & "Test des unités mangeant, dormant et respirant et du TDD. &";

  

Mon responsable dit que le seul moyen d'obtenir une promotion est de pouvoir amener l'équipe à TDD / BDD.

Avez-vous déjà pensé que cela vous faisait peut-être sonner comme une merde? Avez-vous constaté que votre harcèlement avait aliéné le reste de votre équipe?

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

Je pense qu'une meilleure approche serait de le pratiquer vous-même et de laisser les autres voir les avantages. Mener par l'exemple. Ce sera beaucoup plus persuasif que de courir la bouche.

Décidément, Grails a une génération de test intégrée. Si vous travaillez dans une équipe qui utilise Grails, combien de ventes faut-il encore?

Meilleure pratique IMHO: Faites ce qui est pratique et pas seulement parce que c'est un processus. N'oubliez pas quel est l'objectif 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'objectif.

Trouvez une personne qui a fait TDD / BDD et programmez-la avec elle.

Les métriques sont, à mon humble avis, le meilleur moyen d’aller de l’ici à l’autre. Gardez une trace de la manière dont votre code est couvert, gardez les deltas de complexité du code pour chaque commit, utilisez des coureurs de tests qui surveillent votre code pour les modifications et réexécutez constamment les tests correspondants. Ne laissez jamais les longueurs de test dépasser les quelques lignes afin que tous vos outils fonctionnent correctement. Et je recommanderais une fois par mois de prendre un jour de congé pour exécuter votre code avec un testeur de mutation. Cette journée devrait être consacrée uniquement à la rédaction de tests. Tout cela vous fera souffrir si vous ne faites pas déjà un bon TDD. Apprenez de la douleur et en un rien de temps, vous le ferez bien.

Et ne perdez jamais de vue le but des tests: Décrire le comportement souhaité. Ce sont vos spécifications exécutables. (C’est aussi pourquoi j’aime bien Concombre ; vous pouvez maintenant demander à votre PHB de passer vos tests à votre place! c'est aussi bon que ça, mais c'est proche!)

" PS: Mon responsable dit que le seul moyen d'obtenir une promotion est si je peux obtenir l'équipe en mode TDD / BDD. "

Le seul moyen réaliste d’amener une équipe à 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 du 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, car vous étiez préparé avec vos tests en place. Le bar était vert, bidouille bidouille bidon, RED BAR !!!!, bidouille bidouille bidon, barre verte, rentre chez toi.

Lisez le livre de Kent Becks sur la conception pilotée par les tests. Commencez avec 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 agace seulement les indigènes:)

Je fais du TDD depuis quelques années, mais récemment, j'ai commencé à mieux me familiariser avec la manière dont BDD pilotait ma conception et mon développement. Les ressources qui m'ont aidé à démarrer sur BDD étaient d'abord et avant tout le blog de Dan North (le «fondateur» de BDD). Consultez Présentation de BDD . Un wiki "officiel" sur BDD est également disponible sur behavior-driven.org avec quelques bons articles qui méritent d'être lus.

La seule 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 rendre compatibles avec BDD. Scott Bellware est un homme expérimenté en BDD (ou Context-Spesification comme il aime le jouer) et son article Le développement axé sur les comportements 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 le screencast TekPub Une conception axée sur le comportement avec Specflow de Rob Conery. Une excellente introduction à BDD et à un outil (SpecFlow) très bien adapté à 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;

Commencez par effectuer des tests unitaires, puis découvrez comment le faire correctement. En dernier lieu, apprenez à votre équipe à 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é: utiliser un serveur de construction pour construire votre code et exécuter votre test. Je vous recommande d'utiliser TeamCity (gratuit, avec restrictions).

Apprendre à corriger de bons tests unitaires est la partie la plus difficile. Vous en apprendrez une partie par vous-même (à condition de garder les tests unitaires) et le reste en apprenant en cherchant sur Internet.

Vous saurez que vous avez atteint votre objectif lorsque vous NE ferez PAS l'erreur d'écrire des tests unitaires dans le cadre du développement.

N'oubliez pas que l'agilité signifie que vous n'êtes pas complètement vendu pour une méthode en particulier. Si vous travaillez sur quelque chose pour lequel les avantages de TDD ne valent pas la peine (comme des modifications d’essai et d’erreur sur une interface Swing), n’utilisez pas TDD.

Je ne vois pas qui que ce soit qui a vraiment dit que TDD n'était pas sur les tests. TDD-ing consiste à exprimer le comportement attendu avant de procéder à la modification minuscule qui modifie le comportement. Cela améliore considérablement la conception et permet de se concentrer comme jamais auparavant. Vous obtenez des tests qui protègent gratuitement vos refactorisations futures et une couverture à 90%.

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

  1. visitez les blogs et lisez les livres mentionnés ci-dessus
  2. faire équipe avec une personne compétente en TDD
  3. pratique

J'ai pratiqué le kata (exercice) seul environ 20 fois (environ 30 minutes chacun) avant de commencer à voir la lumière. Commencez par analyser la description de la description donnée par Uncle Bob, ici . Il y a une foule de katas sur le site codingdojo.org, y compris des solutions et des discussions. Essayez-les!

Pour citer une citation de Nike: JUST DO IT.

Deuxième conseil: ne vous fiez jamais à l'interface de quelqu'un d'autre. Ecrivez toujours, au niveau de chaque classe, sur l'interface que vous souhaitiez exister - écrivez un adaptateur pour l'implémentation réelle si nécessaire.

Je trouve également utile d'éviter de renvoyer des valeurs sur des méthodes et de penser le code en termes de transmission de messages plutôt que d'appels de fonctions.

YMMV.

Il y a un an, je ne savais pas vraiment comment faire du TDD (mais le voulais vraiment (quelle frustration)) et je n'avais jamais entendu parler de BDD ... maintenant, je pratique 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 & Quot; F5 - Exécuter & Quot; bouton avec une macro pour exécuter Cucumber (BDD) ou MBUnit (TDD) selon qu’il s’agit d’une fonction / scénario ou d’une spécification. Pas de débogueur si possible. 1 $ dans le pot si vous utilisez le débogueur (JOKING (en quelque sorte)).

Le processus est vraiment génial. Le framework que nous utilisons en outre est celui de l’Oracle que j’ai la chance de découvrir, et qui absorbe des informations, et ce framework qu’il / nous utilisons est MavenThought.

Tout commence par BDD. Notre BDD est composé de fer et de rubis.

Caractéristique:

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

Scénario: ...

Et ce n’est pas un test unitaire en soi, mais c’est la fonctionnalité, scénario par scénario, puis les spécifications de l’unité (test). Vous commencez donc sur un scénario et vous devez le compléter à chaque étape. entraîne votre TDD.

Et le TDD que nous utilisons est en quelque sorte un BDD, car nous examinons les comportements requis par le système sous test et un comportement est spécifié par spécification (classe " test " fichier).

Exemple:

Voici la spécification pour un comportement: lors de la création du système à tester.

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 il est séparé dans un fichier séparé.

using MavenThought.Commons.Testing;
using SharpTestsEx;

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

Il s’agit probablement du comportement le plus simple pour un système sous test, car dans ce cas, lorsqu’il est créé, la propriété Diffuser doit être identique à celle du diffuseur injecté. J'ai dû utiliser un diffuseur concret au lieu d'un simulacre car, dans ce cas, le diffuseur est un objet 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 le vrai.

Nous avons souvent plusieurs [It] Should_do_xyz (), et parfois un peu de configuration, comme peut-être jusqu'à 10 lignes de stubbing. Ceci est juste un exemple très simple, sans GivenThat () ou AndGivenThatAfterCreated () dans cette spécification.

Pour configurer chaque spécification, nous n’avons généralement besoin de redéfinir que quelques méthodes de la spécification:

GivenThat () == > cela se produit avant la création du SUT.

CreatSut () == > Nous modifions automatiquement la création du sut avec StructureMap et 90% du temps n’avions jamais besoin de le remplacer, mais si vous êtes un constructeur qui injecte un béton, vous devez le remplacer.

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

WhenIRun () = > sauf s'il s'agit d'une [ConstructorSpecification], nous l'utilisons pour exécuter UNE ligne de code qui correspond au comportement que nous spécifions pour le SUT

En outre, s'il existe un comportement commun de deux spécifications ou plus du même système SUT, nous le déplaçons dans la spécifcation de base.

Tout ce que je dois faire pour exécuter la spécification est de mettre en surbrillance son nom, exemple & "When_diffuser_observer_is_created &"; et appuyez sur F5, car rappelez-vous, F5 exécute une tâche de ratissage test: feature: balise si Cucumber, ou test: class [SUT]. Cela me semble logique car à chaque fois que vous exécutez le débogueur, vous ne créez aucun code (oh, cela coûte 1 $ (blague)).

C’est une manière très, très propre de spécifier le comportement avec TDD et d’avoir des SUT et des spécifications très simples. Si vous essayez d’être un codeur cow-boy et d’écrire le SUT avec des dépendances difficiles, vous ressentirez la douleur d’essayer de faire du TDD et d’en avoir marre / d’abandonner OU de mordre la balle et de le faire correctement.

Et voici le SUT réel. Nous avons eu un peu de fantaisie et utilisons PostSharp pour ajouter un avis de propriété modifié sur le Diffuser, d’où le Post.Cast < > ;. Et encore une fois, c’est pourquoi j’ai injecté un béton plutôt que de faux. Quoi qu'il en soit, comme vous pouvez le constater, le comportement manquant défini dans une autre spécification concerne tout changement 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
{
    /// <summary>
    /// Implementation of current observer for the selected product
    /// </summary>
    public class DiffuserObserver : AbstractNotifyPropertyChanged, IDiffuserObserver
    {
        /// <summary>
        /// gets the diffuser
        /// </summary>
        public IDiffuser Diffuser { get; private set; }

        /// <summary>
        /// Initialize with a diffuser
        /// </summary>
        /// <param name="diffuser">The diffuser to observe</param>
        public void Initialize(IDiffuser diffuser)
        {
            this.Diffuser = diffuser;
            this.NotifyInterface().PropertyChanged += (x, e) => this.OnPropertyChanged(e.PropertyName);
        }

        /// <summary>
        /// Gets the notify interface to use
        /// </summary>
        /// <returns>The instance of notify property changed interface</returns>
        protected INotifyPropertyChanged NotifyInterface()
        {
            return Post.Cast<Diffuser, INotifyPropertyChanged>((Diffuser)Diffuser);
        }
    }
}

En conclusion, ce style de développement BDD / TDD est un succès. Cela a pris un an mais je suis un converti total comme mode de vie. Je n'aurais pas appris cela par moi-même. J'ai tout repris dans Oracle, http://orthocoders.com/ .

Pilule rouge ou bleue, à vous de choisir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top