Perspektive:
Machen wir also einen Schritt zurück und fragen, bei welchen Themen TDD uns helfen möchte. TDD versucht uns zu helfen, festzustellen, ob unser Code korrekt ist oder nicht. Und mit richtig meine ich: "Entspricht der Code den Geschäftsanforderungen?" Das Verkaufsargument ist, dass wir wissen, dass in Zukunft Änderungen erforderlich sind, und wir möchten sicherstellen, dass unser Code auch nach diesen Änderungen korrekt bleibt.
Ich spreche diese Perspektive an, weil ich denke, dass es leicht ist, sich in den Details zu verlieren und aus den Augen zu verlieren, was wir erreichen wollen.
Grundsätze - SAP:
Ich bin zwar kein TDD-Experte, aber ich denke, Sie vermissen einen Teil dessen, was das Single Assertion Principle (SAP) zu lehren versucht. SAP kann wie folgt umformuliert werden: "Test eins nach dem anderen". Aber TOTAT lässt sich nicht so leicht von der Zunge rollen wie SAP.
Wenn Sie immer nur eine Sache testen, konzentrieren Sie sich auf einen Fall. ein Weg; eine Randbedingung; ein Fehlerfall; eine was auch immer pro Test. Und die treibende Idee dahinter ist, dass Sie wissen müssen, was kaputt gegangen ist, als der Testfall fehlgeschlagen ist, damit Sie das Problem schneller lösen können. Wenn Sie mehrere Bedingungen (dh mehr als eine Sache) innerhalb eines Tests testen und der Test fehlschlägt, haben Sie viel mehr Arbeit an Ihren Händen. Sie müssen zuerst herausfinden, welcher der mehreren Fälle fehlgeschlagen ist, und dann herausfinden, warum dieser Fall fehlgeschlagen ist.
Wenn Sie eine Sache nach der anderen testen, ist Ihr Suchbereich viel kleiner und der Fehler wird schneller identifiziert. Denken Sie daran, dass "eine Sache nach der anderen testen" Sie nicht unbedingt davon ausschließt, mehr als eine Prozessausgabe gleichzeitig zu betrachten. Wenn ich beispielsweise einen "bekannten guten Pfad" teste, erwarte ich möglicherweise, dass ein bestimmter, resultierender Wert foo
sowie ein anderer Wert in bar
angezeigt werden, und kann dies foo != bar
als Teil meines Tests überprüfen. Der Schlüssel besteht darin, die Ausgabeprüfungen basierend auf dem getesteten Fall logisch zu gruppieren.
Grundsätze - PMP:
Ebenso vermisse ich ein bisschen, was das Private Method Principle (PMP) uns beibringen muss. PMP ermutigt uns, das System wie eine Black Box zu behandeln. Für eine bestimmte Eingabe sollten Sie eine bestimmte Ausgabe erhalten. Es ist Ihnen egal, wie die Blackbox die Ausgabe generiert. Sie kümmern sich nur darum, dass Ihre Ausgaben mit Ihren Eingaben übereinstimmen.
PMP ist eine wirklich gute Perspektive, um die API-Aspekte Ihres Codes zu betrachten. Es kann Ihnen auch dabei helfen, den Umfang der zu testenden Elemente zu bestimmen. Identifizieren Sie Ihre Schnittstellen und stellen Sie sicher, dass sie die Bedingungen ihrer Verträge erfüllen. Sie müssen sich nicht darum kümmern, wie die (auch als privat bezeichneten) Methoden hinter der Benutzeroberfläche ihre Arbeit erledigen. Sie müssen nur überprüfen, ob sie das getan haben, was sie tun sollten.
Angewandte TDD ( für Sie )
Ihre Situation ist also etwas faltiger als bei einer normalen Anwendung. Die Methoden Ihrer App sind statusbehaftet, sodass ihre Ausgabe nicht nur von der Eingabe, sondern auch von den zuvor ausgeführten Aktionen abhängt. Ich bin sicher, ich sollte <insert some lecture>
hier über den Staat sprechen, der schrecklich ist und bla bla bla, aber das hilft wirklich nicht, dein Problem zu lösen.
Ich gehe davon aus, dass Sie eine Art Zustandsdiagramm-Tabelle haben, in der die verschiedenen möglichen Zustände und die erforderlichen Schritte zum Auslösen eines Übergangs aufgeführt sind. Wenn Sie dies nicht tun, benötigen Sie es, da es die Geschäftsanforderungen für dieses System ausdrückt.
Die Tests: Zuerst müssen Sie eine Reihe von Tests durchführen, mit denen sich der Status ändert. Im Idealfall stehen Tests zur Verfügung, die alle möglichen Statusänderungen durchführen. Ich kann jedoch einige Szenarien vorstellen, in denen Sie möglicherweise nicht in vollem Umfang vorgehen müssen.
Als Nächstes müssen Sie Tests erstellen, um die Datenverarbeitung zu validieren. Einige dieser Zustandstests werden beim Erstellen der Datenverarbeitungstests wiederverwendet. Angenommen, Sie haben eine Methode Foo()
mit unterschiedlichen Ausgaben, die auf einem Init
und -Zustand basieren State1
. Sie möchten Ihren ChangeFooToState1
Test als Einrichtungsschritt verwenden, um die Ausgabe zu testen, wenn "eingeschaltet" Foo()
ist State1
.
Es gibt einige Implikationen hinter diesem Ansatz, die ich erwähnen möchte. Spoiler, hier werde ich die Puristen verärgern
Zunächst müssen Sie akzeptieren, dass Sie in einer Situation etwas als Test und in einer anderen Situation ein Setup verwenden. Einerseits scheint dies eine direkte Verletzung von SAP zu sein. Wenn Sie jedoch logischerweise ChangeFooToState1
zwei Ziele definieren, entsprechen Sie immer noch dem Geist dessen, was SAP uns beibringt. Wenn Sie sicherstellen müssen, dass sich der Status Foo()
ändert, verwenden Sie dies ChangeFooToState1
als Test. Und wenn Sie die Foo()
Ausgabe von State1
" validieren müssen, wenn ", dann verwenden Sie ChangeFooToState1
als Setup.
Der zweite Punkt ist, dass Sie aus praktischer Sicht keine vollständig randomisierten Komponententests für Ihr System wünschen. Sie sollten alle Statusänderungstests ausführen, bevor Sie die Ausgabevalidierungstests ausführen. SAP ist sozusagen der Leitgedanke hinter dieser Bestellung. Um festzustellen, was offensichtlich sein sollte - Sie können etwas nicht als Setup verwenden, wenn es als Test fehlschlägt.
Etwas zusammensetzen:
Mithilfe Ihres Zustandsdiagramms generieren Sie Tests, um die Übergänge abzudecken. Wiederum generieren Sie anhand Ihres Diagramms Tests, um alle vom Status abhängigen Fälle der Eingabe- / Ausgabedatenverarbeitung abzudecken.
Wenn Sie diesem Ansatz folgen, sollten die bloated, complicated, long, and difficult to write
Tests etwas einfacher zu handhaben sein. Im Allgemeinen sollten sie kleiner und übersichtlicher (dh weniger kompliziert) sein. Sie sollten beachten, dass die Tests auch entkoppelt oder modular sind.
Nun, ich sage nicht, dass der Prozess völlig schmerzfrei sein wird, da das Schreiben guter Tests einige Anstrengungen erfordert. Und einige von ihnen werden immer noch schwierig sein, weil Sie einen zweiten Parameter (Zustand) auf einige Ihrer Fälle abbilden. Abgesehen davon sollte es ein wenig offensichtlicher sein, warum es einfacher ist, Tests für ein zustandsloses System zu erstellen. Wenn Sie diesen Ansatz jedoch für Ihre Anwendung anpassen, sollten Sie feststellen, dass Sie nachweisen können, dass Ihre Anwendung ordnungsgemäß funktioniert.