Ich lerne TDD mit c #, soweit ich weiß , sollte Test die Entwicklung vorantreiben , dh erstmal einen Fehlertest schreiben schreiben, nachdem der Code mit dem absoluten Minimum geschrieben wurde , um den Test zu bestehen, und dann ein Refactoring durchführen.
Es heißt aber auch, dass " Program to Interface, nicht Implementation ", also schreibe zuerst ein Interface . Hier setzt meine Verwirrung ein. Wenn ich zuerst Interface schreibe, verstößt es gegen zwei Dinge
Der für die Schnittstelle geschriebene Code wird nicht durch einen Test gesteuert .
Es ist nicht das Nötigste offensichtlich kann ich es mit einer einfachen Klasse schreiben.
Soll ich anfangen, auch Tests für das Interface zu schreiben? Was soll ich ohne Implementierung testen?
Wenn diese Frage albern klingt, tut mir das leid, aber ich bin total verwirrt. Vielleicht nehme ich die Dinge zu wörtlich.
quelle
interface
für alles zu verwenden. Aclass
bietet auch eine Schnittstelle, da Sie Implementierungsdetails inprivate
Variablen ausblenden können .contract
. Dies kann beispielsweise die Form einer abstrakten Klasse haben, sollte jedoch keine virtuelle Klasse / Methode sein, da Sie sie nicht instanziieren können sollten.Antworten:
Ihre erste Verletzung ("Der für die Schnittstelle geschriebene Code wird nicht von einem Test gesteuert.") Ist ungültig. Nehmen wir ein einfaches Beispiel. Angenommen, Sie schreiben eine Taschenrechner-Klasse und schreiben eine Additionsoperation. Welchen Test könntest du schreiben?
Ihr Test hat gerade die Schnittstelle definiert. Es ist die
add
Methode, sehen Sie?add
Nimmt zwei Argumente und gibt ihre Summe zurück. Sie können später feststellen, dass Sie mehrere Taschenrechner benötigen, und zu diesem Zeitpunkt eine (in diesem Fall) Java-Schnittstelle extrahieren. Ihre Tests sollten sich dann nicht ändern, da Sie das getestet haben öffentliche Schnittstelle dieser Klasse .Auf einer theoretischeren Ebene sind Tests die ausführbare Spezifikation für ein System. Schnittstellen zu einem System sollten von den Benutzern dieses Systems gesteuert werden. Tests sind die erste Methode, mit der Sie Interaktionen definieren müssen.
Ich glaube nicht, dass Sie Interface-Design von Test-Design trennen können. Das Definieren von Interaktionen und das Entwerfen von Tests für diese sind dieselbe mentale Operation. Wenn ich diese Informationen an eine Schnittstelle sende, erwarte ich ein bestimmtes Ergebnis. Wenn etwas mit meiner Eingabe nicht stimmt, erwarte ich diesen Fehler. Sie können diese Entwurfsarbeit auf Papier machen und dann Ihre Tests daraus schreiben, oder Sie können sie gleichzeitig machen - es ist nicht wirklich wichtig.
quelle
new Calculator()
stimmt die Implementierung? Wenn eine neue Implementierung erforderlich ist, führen Sie dann möglicherweise einen Multiplikationsrechner aus, und Sie müssen den zu verwendenden Test ändern,new AdditionCalculator()
damit er weiterhin besteht. Oder vermisse ich etwas?Was machen wir, wenn wir eine schreiben
interface
? Schreiben wir Code oder entwerfen wir?Ich bin kein Fan von Test Driven Design, aber ich liebe Test Driven Development . Persönlich habe ich meine besten Ergebnisse erzielt, wenn ich die Klasse im Voraus entworfen habe, indem ich die Schnittstelle entworfen habe, bevor ich einen Test schreibe. Ich zähle die Schnittstelle nicht als Code. Die Schnittstelle ist ein Design, das ich mit TDD implementieren werde. Es ist wahrscheinlich, dass sich eine Entwicklung ändert, während ich arbeite, aber es ist meine Roadmap (zusammen mit meiner Testliste).
Ich werde aufhören, bevor ich anfange zu schimpfen, aber hoffentlich ist das eine hilfreiche Art, darüber nachzudenken.
quelle
Es hängt alles davon ab, wie orthodox / religiös Sie TDD machen möchten .
Da Sie gerade lernen, sollten Sie experimentieren, um einen persönlichen Workflow zu erhalten, der für Sie funktioniert.
Wenn Sie es nach den Büchern machen wollen , schreiben Sie zuerst einen Test, der offensichtlich scheitern wird, weil Sie überhaupt nicht mit Code beginnen. Dann schreiben Sie einen Code, um den Test zu bestehen. In diesem Fall steht es Ihnen frei, den vorhandenen Code zu überarbeiten, da Sie einen Test haben, der eine Art Sicherheitsnetz für Überarbeitungen bietet. Die Entscheidung, ein Interface zu verwenden, ist eine Art Umgestaltung.
Neben TDD oder nicht: Die Frage, ob eine Schnittstelle verwendet werden soll oder nicht, ist zunächst nicht interessant. Wenn Sie sicher sind, dass Sie ein unterschiedliches Verhalten haben, das Sie auf mehrere Objekte verteilen möchten, ist es natürlich sinnvoll, über die Verwendung einer Schnittstelle nachzudenken. Wenn Sie beispielsweise eine Ausgabe für verschiedene Ziele haben, ist es sinnvoll, diese über zu implementieren ein Interface Writer und haben unterschiedliche Klassen für die Ausgabe ( FileWriter , Printer etc.). Es ist zwar ein gängiges Sprichwort , an eine Schnittstelle zu schreiben , aber das bedeutet nicht: Verwenden Sie eine Schnittstelle für alles . Manchmal ist es eine Ebene der Indirektion zu viel. Btw. Gleiches gilt für Dienstleistungen. Aber das ist ein anderes Thema.
Auf der anderen Seite könnten Sie testgetrieben auf eine andere Weise entwickeln: Entwerfen Sie Ihren Code für Testbarkeit. Das heißt, Sie schreiben Code, der einfach zu testen ist - obwohl Sie die Tests anschließend schreiben . Es spielt keine Rolle, ob Sie Tests vorher oder nachher schreiben, solange Sie sie testen.
quelle
TDD oder BDD würde bedeuten, zuerst Ihre Domain-Interfaces zu bearbeiten und dann nach meiner Interpretation Tests gegen sie zu schreiben. Die Implementierung einer Schnittstelle weist ein erwartetes Verhalten auf.
Es ist immer noch ein Test vor Code, da eine Schnittstelle keine testbare Logik enthält. Dies ist die Struktur, für die Sie einen Test schreiben.
Ich würde es wie folgt machen
Schreiben Sie das semi-formale Verhalten (Gegeben: Wann: Dann :)
Schreiben Sie die Schnittstelle (um die Verkapselungsmethode für das Host-Verhalten zu verwenden).
Schreiben Sie den Test, den es identifiziert (geben Sie das Gegebene ein, rufen Sie das Wann auf, testen Sie das Dann)
Schreiben / Ändern Sie den Beton (Klasse, die die Schnittstelle implementiert), um den Test zu bestehen
quelle
Schreiben Sie niemals Tests, bevor Sie die Schnittstellen entworfen haben. Wenn Sie darüber nachdenken, welche Arten von Tests zu schreiben sind (Testdesign), sollten Sie Ihre Anwendung nicht gleichzeitig entwerfen (Architektur). Denken Sie nicht gleichzeitig an zwei Dinge. Haben Sie von der Trennung von Bedenken gehört? Dies gilt nicht nur für die physische Struktur Ihres Codes, sondern auch für Ihren Denkprozess.
Entscheiden Sie zuerst, wie Ihre Anwendung gestaltet werden soll. Dies bedeutet, dass Sie Ihre Schnittstellen und die Beziehungen zwischen diesen Schnittstellen entwerfen. Bis Sie dies getan haben, sollten Sie nicht über Tests nachdenken. Sobald Sie wissen, was Ihre Schnittstellen sind, können Sie sie entweder zuerst erstellen und dann Tests gegen sie schreiben oder Tests zuerst schreiben und sie dann erstellen. In letzterem Fall können Sie die Tests natürlich nicht kompilieren. Ich sehe keinen Schaden oder Verstoß gegen die TDD-Philosophie in der Erstellung der Schnittstellen vor den Tests.
quelle
interface
, nicht auf den allgemeinen Begriff "Schnittstelle".Es ist in Ordnung, die Schnittstelle / den Code / den Test zur gleichen Zeit zu schreiben, solange ihre Einbindung in das Projekt atomar ist.
Es sei denn, Ihr Chef ist religiös in Bezug auf TDD. In diesem Fall müssen Sie wahrscheinlich eine leere Schnittstelle schreiben -> test -> minimaler Code (sinnloser Schritt) -> mehr Tests -> sinnloser Code -> mehr Tests -> endlich den echten Code schreiben - > fertig.
quelle