J'apprends TDD en utilisant c #, pour autant que je sache, le test devrait conduire le développement , c'est-à-dire d' abord écrire un test qui échoue après avoir écrit le code minimum pour passer le test, puis refactoriser.
Mais il est également dit que " Programmer vers l'interface, pas la mise en œuvre ", alors écrivez d' abord une interface . C'est là que ma confusion commence, si j'écris d'abord Interface, cela viole deux choses
Le code écrit pour l'interface n'est pas piloté par test .
Ce n'est pas le strict minimum, je peux évidemment l'écrire avec une classe simple.
Dois-je également commencer par écrire des tests d'interface? sans implémentation, que vais-je tester?
Si cette question semble stupide, désolé pour cela, mais je suis complètement confus. Peut-être que je prends les choses trop à la lettre.
la source
interface
pour tout. Aclass
fournit également une interface, car vous pouvez masquer les détails d'implémentation dans desprivate
variables.contract
. Cela pourrait être sous la forme d'une classe abstraite, par exemple, bien qu'il ne devrait pas s'agir d'une classe / méthode virtuelle car vous ne devriez pas pouvoir l'instancier.Réponses:
Votre première violation («Le code qui est écrit pour l'interface n'est pas pilotée par le test.») N'est pas valide. Prenons un exemple trivial. Supposons que vous écrivez une classe de calculatrice et que vous écrivez une opération d'addition. Quel test pourriez-vous passer?
Votre test vient de définir l'interface. C'est la
add
méthode, tu vois?add
prend deux arguments et retourne leur somme. Vous pourrez déterminer ultérieurement que vous avez besoin de plusieurs calculatrices et extraire une interface Java (dans ce cas) à ce moment-là. Vos tests ne devraient pas changer alors, puisque vous avez testé l' interface publique de cette classe.À un niveau plus théorique, les tests sont la spécification exécutable d'un système. Les interfaces avec un système doivent être pilotées par les utilisateurs de ce système et les tests sont la première méthode dont vous disposez pour définir les interactions.
Je ne pense pas que vous puissiez séparer la conception d'interface de la conception de test. Définir les interactions et concevoir des tests pour elles sont la même opération mentale - lorsque j'envoie ces informations dans une interface, j'attends un certain résultat. Quand quelque chose ne va pas avec mon entrée, je m'attends à cette erreur. Vous pouvez faire ce travail de conception sur papier, puis écrire vos tests à partir de cela, ou vous pouvez les faire en même temps - cela n'a pas vraiment d'importance.
la source
new Calculator()
la mise en œuvre est-elle correcte? Si une nouvelle implémentation est nécessaire, vous feriez peut-être alors un MultiplicationCalculator, et vous auriez besoin de changer le test à utilisernew AdditionCalculator()
pour qu'il passe encore? Ou est-ce que je manque quelque chose?Que faisons-nous quand nous écrivons un
interface
? Écrivons-nous du code ou concevons-nous?Je ne suis pas fan de la notion de Test Driven Design, mais j'aime Test Driven Development . Personnellement, j'ai obtenu mes meilleurs résultats lorsque je conçois la classe à l'avance en concevant l'interface avant d'écrire un test. Je ne compte pas l'interface comme du code. L'interface est une conception que je vais implémenter en utilisant TDD. Il est probable que cela change une évolution au fur et à mesure que je travaille, mais c'est ma feuille de route (avec ma liste de tests).
Je m'arrêterai avant de commencer à déclamer, mais j'espère que c'est une façon utile pour vous d'y penser.
la source
Tout dépend de la façon dont vous voulez faire du TDD orthodoxe / religieux .
Puisque vous apprenez, vous devez expérimenter pour obtenir un flux de travail personnel, qui fonctionne pour vous.
Si vous voulez le faire selon les livres , vous écrivez d'abord un test, qui échouera évidemment, car vous commencez sans aucun code. Ensuite, vous écrivez du code pour réussir le test. Si cela est fait, vous êtes libre de refactoriser le code existant, car vous avez un test qui fournit une sorte de filet de sécurité pour les refactorings. Décider d'utiliser une interface est une sorte de refactoring.
Outre TDD ou non: La question de savoir si utiliser une interface ou non n'est pas intéressante en premier lieu. Bien sûr, si vous êtes sûr, vous avez un comportement différent que vous souhaitez répartir sur plusieurs objets, il est logique de penser à utiliser une interface: par exemple, si vous avez une sorte de sortie vers différentes destinations, il est logique de l'implémenter via une interface Writer et ont différentes classes pour la sortie ( FileWriter , Printer etc.). Bien que ce soit un dicton courant d' écrire sur une interface , cela ne signifie pas: utiliser une interface pour tout . Parfois, c'est un niveau d'indirection trop important. Btw. il en va de même pour les services. Mais c'est un sujet différent.
D'un autre côté, vous pouvez développer le test piloté d'une autre manière: concevoir votre code pour la testabilité. Cela signifie que vous écrivez du code, qui est facile à tester - bien que vous écriviez les tests par la suite . Peu importe si vous écrivez des tests avant ou après, tant que vous testez de toute façon.
la source
TDD ou BDD signifierait Faire d'abord vos interfaces de domaine, puis écrire des tests par rapport à elles par mon interprétation. L'implémentation d'une interface a un comportement attendu.
c'est toujours un test avant le code car une interface ne contient aucune logique testable, c'est la structure contre laquelle vous écrivez un test.
Je le ferais comme suit
Écrivez le comportement semi-formel (étant donné: quand: alors :)
Écrire l'interface (pour héberger la méthode d'encapsulation du comportement)
Écrivez le test qu'il identifie (entrez le donné, appelez le quand, testez le alors)
Écrire / modifier le béton (classe qui implémente l'interface) pour réussir le test
la source
N'écrivez jamais de tests avant d'avoir conçu les interfaces. Lorsque vous pensez aux types de tests à écrire (conception de test), vous ne devez pas également concevoir (architecturer) simultanément votre application. Ne pensez pas à deux choses en même temps. Avez-vous entendu parler de la séparation des préoccupations? Cela s'applique non seulement à la structure physique de votre code mais également à votre processus de réflexion.
Décidez d'abord comment votre application doit être conçue. Cela signifie que vous concevez vos interfaces et les relations entre ces interfaces. Jusqu'à ce que vous ayez fait cela, vous ne devriez pas commencer à penser aux tests. Une fois que vous savez quelles sont vos interfaces, vous pouvez soit les créer d'abord, puis écrire des tests contre elles, soit écrire des tests d'abord, puis les créer. Dans ce dernier cas, vous ne pourrez évidemment pas compiler les tests. Je ne vois aucun mal ni aucune violation de la philosophie TDD dans la création des interfaces avant les tests.
la source
interface
mot clé C # , pas au terme général "interface".C'est correct d'écrire l'interface / le code / le test en même temps tant que leur incorporation dans le projet est atomique.
Sauf si votre patron est religieux à propos de TDD, auquel cas vous devrez probablement écrire une interface vide -> test -> code minimal (étape inutile) -> plus de tests -> plus de code inutile -> plus de tests -> enfin écrire le vrai code - > terminé.
la source