2009-06-01 14 views
14

J'ai donc fait des tests unitaires et j'ai de l'expérience dans l'écriture de tests, mais je n'ai pas complètement adopté TDD comme outil de conception.TDD: Où commencer le premier test?

Mon projet actuel consiste à retravailler un système existant qui génère des numéros de série dans le cadre du processus d'assemblage des entreprises. J'ai une compréhension du processus actuel et du flux de travail dû à l'examen du système existant. J'ai aussi une liste de nouvelles exigences et comment elles vont modifier le flux de travail. Je sens que je suis prêt à écrire le programme et j'ai décidé de me forcer à faire TDD du début à la fin.

Mais maintenant je n'ai aucune idée par où commencer. (Je me demande aussi si je triche le processus TDD en ayant déjà une idée du flux du programme pour l'utilisateur.)

Le flux utilisateur est vraiment en série et n'est qu'une série d'étapes. À titre d'exemple, serait la première étape:

    utilisateur
  • présente un numéro de commande de fabrication et reçoit une liste de références sérialisables de ce projet de loi de commandes de matériel

L'étape suivante est lancée lorsque l'utilisateur sélectionne l'un des numéros de pièce. Je pensais donc pouvoir utiliser cette première étape comme point de départ. Je sais que je veux un morceau de code qui prend un numéro de commande de fabrication et renvoie une liste de numéros de pièces. En lisant le livre d'exemples de Kent Becks, il parle de la sélection de petits tests. Cela semble être une assez grosse boîte noire. Cela va nécessiter un référentiel d'ordres mfg et je dois explorer une arborescence de structure de produit pour trouver tous les numéros de pièces applicables pour cette commande mfg et je n'ai même pas défini mon modèle de domaine dans le code.

Donc, d'une part, cela semble être un début de merde - une fonction très générale de haut niveau. D'un autre côté, j'ai l'impression que si je commence à un niveau inférieur, je ne fais que deviner ce dont j'ai besoin et qui semble anti-TDD.


En remarque ... est-ce que c'est comme ça que vous utiliseriez des histoires?

Comme un assembleur Je veux obtenir une liste des numéros de pièce sur un ordre Mfg Pour que je puisse choisir celui sérialiser

Pour être honnête, un assembleur ne dirait jamais que. Tout un assembleur veut est de terminer l'opération sur commande MFG:

Comme un assembleur Je veux marquer des pièces avec un numéro de série Afin que je puisse terminer l'opération de l'ordre de Mfg

Répondre

15

Voici comment je commencerais. Supposons que vous n'avez absolument aucun code pour cette application.

  1. Définir l'histoire d'utilisateur et la valeur commerciale qu'il apporte: « En tant qu'utilisateur, je veux présenter un numéro de commande de fabrication et une liste de références de ce ordre afin que je puisse envoyer la liste au système d'inventaire "
  2. commencez avec l'interface utilisateur. Créer une page très simple (laisse supposer son une application web) avec trois champs: étiquette, liste et bouton. C'est assez bien, n'est-ce pas? L'utilisateur pourrait copier la liste et l'envoyer au système inv.
  3. Utilisez un motif pour baser votre dessin, comme MVC.
  4. Définissez un test pour votre méthode de contrôleur qui est appelée depuis l'interface utilisateur. Vous testez ici que le contrôleur fonctionne, pas que les données soient correctes: Assert.AreSame(3, controller.RetrieveParts(mfgOrder).Count)
  5. Écrivez une implémentation simple du contrôleur pour vous assurer que quelque chose est retourné: return new List<MfgOrder>{new MfgOrder(), new MfgOrder(), new MfgOrder()}; Vous devrez également implémenter des classes pour MfgOrder, par exemple .
  6. Votre interface utilisateur fonctionne maintenant! Travailler incorrectement, mais en travaillant. Attendons donc que le contrôleur obtienne les données d'un service ou d'un DAO. Créez un objet Mock DAO dans le scénario de test et ajoutez une attente que la méthode "partsDao.GetPartsInMfgOrder()" est appelée.
  7. Créez la classe DAO avec la méthode. Appelez la méthode à partir du contrôleur. Votre contrôleur est maintenant terminé.
  8. Créez un test distinct pour tester le DAO, en vérifiant enfin qu'il renvoie les données correctes de la base de données.
  9. Continuez l'itération jusqu'à ce que tout soit terminé. Après un petit moment, vous vous y habituerez.

Le point principal ici est de séparer l'application en très petites parties, et de tester ces petites pièces individuellement.

1

Je pense que vous avez un bon début mais ne le vois pas comme ça. Le test qui est censé engendrer plus de tests est tout à fait logique pour moi, comme si vous y pensiez, savez-vous ce qu'est un numéro d'ordre de fabrication ou un numéro de pièce est encore? Vous devez construire ceux qui peuvent conduire à d'autres tests, mais vous finirez par obtenir les tests itty bitty je crois.

Voici une histoire qui peut nécessiter un peu de décomposer:

  • En tant qu'utilisateur, je veux présenter un numéro de commande de fabrication et de recevoir une liste de références sérialisables de ce projet de loi de commandes de matériel

Je pense que la clé est de décomposer les choses encore et encore en minuscules morceaux qui font que c'est pour construire le tout. Cette technique de "Diviser pour régner" est pratique à certains moments. ;)

+0

Vous avez oublié la troisième partie de l'histoire, l'avantage. Vous avez également des détails de mise en œuvre là-dedans, qui n'apportent aucun avantage commercial (sérialisable). Je dirais qu'une meilleure histoire serait quelque chose comme "En tant qu'utilisateur, je veux soumettre un numéro de commande de fabrication et une liste de numéros de pièces de ces commandes afin que je puisse envoyer la liste au système d'inventaire". –

+0

Serializable dans ce contexte n'est pas l'implémentation, c'est un terme de domaine qui indique quelles parties peuvent porter un numéro de série, donc c'est important (pour autant que je comprends les exigences). –

+0

Si c'est le cas, vous avez raison. L'expertise du domaine est tout. –

1

Bien bien, vous avez touché le même mur exact que je l'ai fait quand j'ai essayé TDD pour la première fois :)

Depuis lors, je lui ai donné sur le sujet, tout simplement parce qu'il fait refactoring trop cher - et j'ai tendance à refactoriser beaucoup au cours de la phase initiale de développement. Avec ces mots grincheux à l'écart, je trouve que l'un des aspects les plus surveillés et les plus importants de TDD est qu'il vous oblige à définir vos interfaces de classe avant de les implémenter réellement. C'est une très bonne chose quand vous avez besoin d'assembler toutes vos pièces en un seul gros produit (enfin, en sous-produits;)). Ce que vous devez faire avant d'écrire vos premiers tests, c'est d'avoir votre modèle de domaine, votre modèle de déploiement et de préférence une bonne partie de vos diagrammes de classe prêts avant le codage - simplement parce que vous devez identifier vos invariants, valeurs min et max etc. ., avant de pouvoir les tester. Vous devriez être capable de les identifier sur un niveau de test unitaire à partir de votre conception.

Soo, dans mon expérience (pas dans l'expérience de certains auteur qui jouit d'analogies réelles de cartographie à OO: P), TDD devrait se présenter comme suit:

  1. Créez votre diagramme de déploiement, de la spécification des exigences (OFC, rien n'est dans la pierre - jamais)
  2. Choisissez un user story à mettre en œuvre
  3. Créer ou modifier votre modèle de domaine pour inclure cette histoire
  4. Créer ou modifier votre classe diagramme pour inclure cette histoire (y compris divers cours de design)
  5. Identifier les vecteurs de test.
  6. Créez les tests en fonction de l'interface que vous avez créée à l'étape 4
  7. Testez les tests (!). Ceci est une étape très importante ..
  8. Mettre en œuvre les classes
  9. test des classes
  10. Go ont une bière avec vos collègues :)
+5

Vous ne faites pas de développement Test DRIVEN si vous faites cela. Vous écrivez des tests, mais vous ne dérivez pas votre conception des cas de test. –

+2

Ye, eh bien, c'est dans les yeux du spectateur :) Comme je le vois, vous ne pouvez pas dériver 100% de votre conception des causes de test. Au moins pas efficacement - imho.Les tests sont pour les détails de mise en œuvre, pas pour le design .. Encore une fois, mon point de vue personnel. – cwap

4

Ceci est parfaitement correct comme un test de départ. Avec cela, vous définissez le comportement attendu - comment cela devrait fonctionner. Maintenant, si vous sentez que vous avez pris une morsure beaucoup plus grande que vous auriez aimé, vous pouvez temporairement ignorer ce test et écrire un test plus granulaire qui prend une partie ou au moins à mi-chemin. Ensuite, d'autres tests qui vous mèneront vers l'objectif de faire passer le premier gros test. Red-Green-Refactor à chaque étape.

Petits tests, je pense que vous ne devriez pas tester beaucoup de choses en un seul test. par exemple. Les composants D.A, B et C sont dans state1, state2 et state3 après avoir appelé Method1(), Method2() et Method3() avec ces paramètres sur D. Chaque test doit tester une seule chose. Vous pouvez rechercher SO pour les qualités de bons tests.Mais je considère que votre test soit un petit test, car il est court et concentré sur une tâche - « Obtenir Numéros de pièces de la fabrication Commander »

Mise à jour: En tant que Pour-Try suggestion (AFAIR du livre de Beck), vous pouvez vous asseoir et proposer une liste de tests d'une ligne pour le SUT sur une feuille de papier. Maintenant, vous pouvez choisir le plus facile (tests que vous êtes sûr que vous serez en mesure de faire.) Afin de construire une certaine confiance. OU vous pourriez en essayer un que vous êtes confiant à 80% mais qui a quelques zones grises (mon choix aussi) parce que cela vous aidera à apprendre quelque chose sur le SUT en cours de route. Gardez ceux que vous n'avez aucune idée de la façon de procéder pour la fin ... j'espère que ce sera plus clair au moment où les plus faciles sont faits. Sortez-les un par un au fur et à mesure qu'ils deviennent verts.

+0

Donc, cela m'a rassuré et je m'assieds pour écrire le test. Même penser à comment l'écrire est une expérience de conception. Je ne suis pas sûr si je suis satisfait de mon test, mais c'est un point de départ et cela me fait penser à quelques choses. – anonymous

+0

Ceci est précisément la contribution la plus importante de TDD .. Il conduit votre conception du point de vue du client - vous obligeant à ajouter uniquement les fonctionnalités dont a besoin au moins un client. Au départ, vous pouvez choisir d'imiter des collaborateurs, mais cela vous aide à définir l'interface la plus simple entre eux, ce qui représente une grande victoire. Pas de plaisir à avoir ou à être requis dans les futures fonctionnalités; Le refactoring continu permet également de garder votre design simple, facile à comprendre et donc maintenable. – Gishu

+0

Je suis retourné et j'ai lu les premiers 40-50 pages du livre de Beck et quelques trucs ont coulé un peu plus depuis ma dernière lecture (il y a quelques mois). Les deux choses qui aident sont a) vous pouvez pécher pour faire un test et b) vous refactoriser immédiatement une fois vert. Et oui, le fait de me concentrer sur le SUT et de le penser m'aide, en particulier en pensant à tous les contextes dans lesquels le SUT pourrait exister - il conduit à des tests plus forts et moins fragiles. – anonymous