2008-10-03 3 views
33

Nachdem ich diese Methode der Entwicklung vor kurzem entdeckt habe, finde ich es eine ziemlich schöne Methode. Also, für mein erstes Projekt habe ich eine kleine DLL Code (in C# .NET, für was es wert ist), und ich möchte eine Reihe von Tests für diesen Code machen, aber ich bin ein wenig verloren, wie und Wo soll man anfangen.Verschieben von vorhandenen Code zu Test Driven Development

Ich benutze NUnit, und VS 2008, irgendwelche Tipps, welche Art von Klassen zu beginnen, was für Tests zu schreiben, und alle Tipps im Allgemeinen, wie Code über Test-basierte Entwicklung zu bewegen wäre sehr geschätzt.

Antwort

53

Siehe das Buch Working Effectively with Legacy Code von Michael Feathers.

Zusammenfassend ist es eine Menge Arbeit, vorhandenen Code in testbaren und getesteten Code umzuwandeln; Manchmal ist es zu viel Arbeit, um praktisch zu sein. Es hängt davon ab, wie groß die Codebasis ist und wie stark die verschiedenen Klassen und Funktionen voneinander abhängen.

Refactoring ohne Tests führt zu Änderungen im Verhalten (d. H. Fehler). Und Puristen werden sagen, dass es nicht wirklich umstrukturiert wird, weil es keine Tests gibt, um zu überprüfen, dass sich das Verhalten nicht ändert.

Anstatt Test auf der ganzen Linie zu Ihrer gesamten Anwendung auf einmal hinzuzufügen, fügen Sie Tests hinzu, wenn Sie in einem Bereich von Code arbeiten. Wahrscheinlich müssen Sie wieder zu diesen "Hotspots" zurückkehren.

Fügen Sie Tests von unten nach oben hinzu: Testen Sie kleine, unabhängige Klassen und Funktionen auf Korrektheit.

Fügen Sie Tests von oben nach unten hinzu: Testen Sie ganze Subsysteme als schwarze Felder, um zu sehen, ob sich ihr Verhalten mit den Änderungen im Code ändert. Und so können Sie durch sie gehen, um herauszufinden, was vor sich geht. Dieser Ansatz wird Ihnen wahrscheinlich den größten Nutzen bringen.

Machen Sie sich zunächst keine Gedanken darüber, was das "richtige" Verhalten ist, während Sie Tests hinzufügen, um Verhaltensänderungen zu erkennen und zu vermeiden. Große, noch nicht getestete Systeme haben oft interne Verhaltensweisen, die möglicherweise falsch erscheinen, von denen jedoch andere Teile des Systems abhängen.

Denken Sie über isolierte Abhängigkeiten wie Datenbank, Dateisystem, Netzwerk nach, damit sie während des Testens für Scheindatenanbieter ausgetauscht werden können.

Wenn das Programm keine internen Schnittstellen hat, Linien, die die Grenze zwischen einem Subsystem/Layer und einem anderen definieren, dann müssen Sie möglicherweise versuchen, diese einzuführen und an ihnen zu testen.

Auch automatische Spott Frameworks wie Rhinomocks oder Moq können helfen, bestehende Klassen hier zu verspotten. Ich habe die Notwendigkeit für sie in Code für Testbarkeit nicht wirklich gefunden.

+0

Ich denke, Ihre Antwort ist viel besser mit dem zusammenfassenden Text: Wir können mehr Details von den Links erhalten, wenn wir wollen, aber wir können Ihre Position verstehen, ohne durchzulesen. –

4

Testbarer Code ist leicht zu erkennen - durch die begleitenden Tests. Wenn es welche gibt, muss es testbar sein. Wenn es keine gibt - nehmen Sie das Gegenteil an. ;)

Das sagte: Test Driven Development (TDD) ist weniger eine Teststrategie als vielmehr eine Designstrategie. Die Tests, die Sie zuerst schreiben, helfen Ihnen, die Oberfläche Ihrer Klassen zu gestalten und den Umfang Ihrer Klassen (oder Subsysteme) richtig zu machen.

Die Tests, die Sie während TDD erstellt und später durchgeführt haben, machen gute Tests, sind aber nur ein (sehr willkommener) Nebeneffekt dieser Designphilosophie.

Dies gesagt, erwarten Sie etwas Widerstand von Ihrem Code gegen getestet werden.Hören Sie auf Ihren Code und ändern Sie die Schnittstelle, um leicht testbar zu sein. Sie werden es wahrscheinlich neu gestalten, wenn Sie mit dem Schreiben von Tests beginnen.

+1

Ich weiß nichts über den Widerstand gegen Tests, aber ich habe es geschafft, einen Fehler, der früher vom VS-Formular-Designer vor einer Weile vorgebracht wurde, wieder zu enthüllen, der mir eine Menge Probleme gab, indem ich einen Test schrieb bedecke diese Möglichkeit. Yay! –

10

Working Effectively with Legacy Code ist meine Bibel, wenn es darum geht, Code ohne Tests in eine Einheit-getestete Umgebung zu migrieren, und es gibt auch eine Menge Einblick, was Code einfach zu testen und zu testen macht.

Ich fand auch Test Driven Development by Example und Pragmatic Unit Testing: in C# with NUnit, um eine anständige Einführung in das Testen von Einheiten in dieser Umgebung zu sein.

Ein einfacher Ansatz zum Starten von TDD ist es, Tests von diesem Tag an zu schreiben und sicherzustellen, dass Sie immer dann, wenn Sie Ihren vorhandenen (uneinheitsgetesteten) Code berühren müssen, Tests schreiben, die das bestehende Verhalten des System, bevor Sie es ändern, damit Sie diese Tests nachher wiederholen können, um Ihr Vertrauen zu erhöhen, dass Sie nichts gebrochen haben.

1

Ihre DLL bietet eine Art von Service. Was müssen Sie für jeden Dienst tun, bevor Sie diesen Dienst erhalten, welche Parameter sollten Sie übergeben, um diesen Dienst zu erhalten, wie würden Sie wissen, dass der angeforderte Dienst korrekt ausgeführt wurde?

Sobald Sie die Antworten auf diese Fragen haben, können Sie einen ersten Test schreiben. Solche Tests würden eher als Unit-Tests Characterization tests genannt werden, wären aber wahrscheinlich einfacher zu schreiben als Unit-Tests, wenn die DLL nicht mit TDD entwickelt wurde.

Charakterisierungstests werden auch in M. Feathers '"Effective with Legacy Code" diskutiert, was in anderen Antworten empfohlen wird.

Stellen Sie sicher, dass Sie zuvor einen fehlerhaften Test geschrieben haben, um eine neue Codezeile hinzuzufügen.

9

Ich nenne es "Test Driven Reverse Engineering".

Start "am Ende" - jede Klasse kann separat untersucht werden und ein Test dafür geschrieben. Im Zweifelsfall erraten.

Wenn Sie gewöhnliche TDD in Vorwärtsrichtung machen, behandeln Sie den Test als heilig und gehen davon aus, dass der Code wahrscheinlich defekt ist. Manchmal ist der Test falsch, aber Ihre Startposition ist, dass es der Code ist.

Wenn Sie TDRE tun, ist der Code heilig - bis Sie beweisen können, dass der Code einen seit langem bestehenden Bug hat. Im umgekehrten Fall schreiben Sie Tests um den Code herum und optimieren die Tests, bis sie funktionieren und behaupten, dass der Code funktioniert.

Dann können Sie in den schlechten Code graben. Einige schlechte Cades werden vernünftige Testfälle haben - das muss nur aufgeräumt werden. Ein wenig schlechter Code wird jedoch auch einen Testfall haben, der sinnlos ist. Dies kann ein Fehler sein oder ein ungeschicktes Design, das Sie korrigieren können.

Um zu beurteilen, ob der Code tatsächlich falsch ist, müssen Sie auch bei allgemeinen Testfällen ganz oben beginnen. Live-Daten, die tatsächlich funktionieren, sind ein Anfang. Auch Live-Daten, die einen der bekannten Bugs erzeugen, sind ebenfalls ein guter Anfang.

Ich habe kleine Code-Generatoren geschrieben, um Live-Daten in Unittest-Fälle zu verwandeln. Auf diese Weise habe ich eine konsistente Basis für Tests und Refactoring.

Verwandte Themen