2013-09-25 7 views
5

Ich bin neu im Komponententest und habe mehrmals gelesen, dass wir zuerst den Komponententest und dann den eigentlichen Code schreiben sollten. Ab sofort schreibe ich meine Methoden und teste dann den Code.Wie schreibe ich Unit Test zuerst und Code später?

Wenn Sie die Tests zuerst schreiben ...

Sie neigen dazu, den Code zu schreiben, um die Tests zu passen. Dies ermutigt die "einfachste Sache, die das Problem löst" Typ Entwicklung und hält Sie konzentrierte sich auf die Lösung des Problems nicht auf Meta-Probleme arbeiten.

Wenn Sie den Code zuerst schreiben ...

Sie werden die Tests zu schreiben versucht sein, den Code zu passen. In der Tat das ist das Äquivalent des Schreibens des Problems, um Ihre Antwort zu passen, die Art von rückwärts ist und wird oft zu Tests führen, die von geringeren Wert sind.

Hört sich gut an. Wie schreibe ich Komponententests, bevor ich meinen Code installiert habe? Nehme ich den Rat wörtlich? Bedeutet das, dass ich meine POCO-Klassen und -Schnittstellen an Ort und Stelle haben und Unit-Test schreiben soll?

Kann mir jemand erklären, wie dies mit einem einfachen Beispiel für das Hinzufügen von zwei Zahlen getan wird?

+0

Das Schreiben von Tests zwingt Sie dazu, darüber nachzudenken, was eine Klasse/Methode/Algorithmus tun soll * bevor * Sie es tatsächlich implementieren. Es ist so, als würde ich sagen: "Das * ist, was ich will! Ich werde mir Sorgen um das * wie * später machen." – Corak

+1

[Hier ist die Antwort, die zeigt, wie Sie beim TDD denken sollten] (http://stackoverflow.com/questions/15367568/c-sharp-how-to-properly-unit-test-a-class-that-follows- a-decorator-pattern/15368534 # 15368534) –

+0

Eine Sache zu bedenken ist, dass TDD gut ist, wenn Sie bereits ein Design haben, für das Sie an bestimmten Komponenten arbeiten. Dies kommt normalerweise nach dem Prototyp. Wenn Sie Prototyping oder RAD machen, wird TDD in die Quere kommen. –

Antwort

6

Es ist wirklich einfach. Rot, Grün, Refactor.

Rot bedeutet - Ihr Code ist komplett kaputt. Die Syntaxhervorhebung zeigt Rot und der Test wird nicht bestanden. Warum? Du hast noch keinen Code geschrieben.

Grün bedeutet - Ihre Anwendung wird erstellt und der Test wird bestanden. Sie haben den erforderlichen Code hinzugefügt.

Refactor bedeutet - reinigen Sie es und stellen Sie sicher, dass der Test bestanden wird.

Sie können durch das Schreiben eines Test etwa so beginnen:

[TestMethod] 
public void Can_Create_MathClass() { 
    var math = new MathClass(); 
    Assert.IsNotNull(math); 
} 

Dies wird fehlschlagen (RED). Wie reparierst du es? Erstellen Sie die Klasse.

public class MathClass { 
} 

Das ist es. Es geht nun über (GRÜN). Nächster Test:

[TestMethod] 
public void Can_Add_Two_Numbers() { 
    var math = new MathClass(); 
    var result = math.Add(1, 2); 
    Assert.AreEqual(3, result); 
} 

Dies auch fehlschlägt (RED). Erstellen Sie die Add Methode:

public class MathClass { 
    public int Add(int a, int b) { 
     return a + b; 
    } 
} 

Führen Sie den Test. Dies wird passieren (GRÜN).

Refactoring ist eine Frage der Bereinigung des Codes. Es bedeutet auch, dass Sie redundante Tests entfernen können. Wir wissen, wir haben die MathClass jetzt .. so können Sie den Test Can_Create_MathClass vollständig entfernen. Sobald das erledigt ist .. Sie haben REFACTOR bestanden und können weitermachen.

Es ist wichtig zu beachten, dass der Refactor-Schritt nicht nur Ihren normalen Code bedeutet. Es bedeutet auch Tests. Sie können nicht zulassen, dass sich Ihre Tests im Laufe der Zeit verschlechtern. Sie müssen sie in den Refactor-Schritt aufnehmen.

+1

Mit dem Zwischenschritt zum Übergeben von 'Can_Add_Two_Numbers' könnte die' Add'-Methode einfach '3;' zurückgeben. In einem trivialen Fall wie diesem ist es unnötig. Aber in etwas komplexeren Situationen scheint das, was offensichtlich ist, für andere und/oder Jahre später nicht so offensichtlich. – Corak

+0

Ich stimme zu, aber in der Praxis finde ich, dass dieser Schritt vollständig von der Komplexität des zu testenden Modells abhängt. Selten war es so komplex, dass ich auf diesen Pufferschritt zurückgegriffen habe. –

+0

Danke Simon. Das hat geholfen. – NoobDeveloper

2

Wenn Sie Ihre Tests zuerst vor dem Code erstellen, können Sie Ihren Code viel einfacher und schneller erstellen. Die kombinierte Zeit, die benötigt wird, um einen Komponententest zu erstellen und Code zu erstellen, um ihn zu passieren, ist ungefähr so, als ob er ihn gleich codieren würde. Aber, wenn Sie bereits die Komponententests haben, müssen Sie sie nicht nach dem Code erstellen, was Sie jetzt und viel später spart.

Durch das Erstellen eines Komponententests kann ein Entwickler wirklich überlegen, was zu tun ist. Anforderungen werden durch Tests festgenagelt. Es kann kein Missverständnis geben, wenn eine Spezifikation in Form eines ausführbaren Codes geschrieben wird.

Der Code, den Sie erstellen, ist einfach und übersichtlich und implementiert nur die gewünschten Funktionen. Andere Entwickler können anhand der Tests sehen, wie dieser neue Code verwendet wird. Eingänge, deren Ergebnisse nicht definiert sind, werden in der Testsuite nicht sichtbar sein

Es gibt auch einen Vorteil für das Systemdesign. Es ist oft sehr schwierig, einige Softwaresysteme zu testen. Diese Systeme werden in der Regel zuerst mit Code erstellt und dann von einem anderen Team getestet. Durch die Erstellung von Tests wird Ihr Design von dem Wunsch beeinflusst, alles zu testen, was für Ihren Kunden von Wert ist. Ihr Design wird dies widerspiegeln, da es einfacher zu testen ist.

1

Nehmen wir ein etwas fortgeschritteneres Beispiel: Sie möchten eine Methode schreiben, die die größte Zahl aus einer Sequenz zurückgibt.

Zum einen eine oder mehrere Einheiten Test schreiben für das Verfahren getestet werden:

int[] testSeq1 = {1, 4, 8, 120, 34, 56, -1, 3, -13}; 

Assert.That(MaxOf(testSeq1) == 120); 

Und für einige weitere Sequenzen wiederholen. Fügen Sie auch einen Null-Parameter, eine Sequenz mit einem Element und einer leeren Sequenz ein und entscheiden Sie, ob eine leere Sequenz oder ein Null-Parameter eine Ausnahme auslösen soll (und stellen Sie sicher, dass der Unit-Test eine Ausnahme für eine leere Sequenz erwartet).

Während dieses Vorgangs müssen Sie den Namen der Methode und den Typ ihrer Parameter festlegen.

An diesem Punkt wird es nicht kompilieren.

Dann schreiben Sie einen Stub für die Methode:

public int MaxOf(IEnumerable<int> sequence) 
{ 
    return 0; 
} 

An diesem Punkt es kompiliert, aber die Unit-Tests fehlschlagen.

Implementieren Sie dann MaxOf(), damit diese Komponententests jetzt bestehen.

Dadurch wird sichergestellt, dass Sie sich sofort auf die Verwendbarkeit der Methode konzentrieren, da das erste, was Sie versuchen zu tun ist, es zu verwenden - bevor Sie überhaupt anfangen, es zu schreiben. Möglicherweise möchten Sie die Deklaration der Methode zu diesem Zeitpunkt basierend auf dem Verwendungsmuster leicht ändern.

Ein Beispiel aus der Praxis würde diesen Ansatz auf die Verwendung einer ganzen Klasse anstatt nur einer Methode anwenden. Der Kürze halber habe ich die Klasse aus dem obigen Beispiel weggelassen.

0

Es ist möglich, die Komponententests vor dem Schreiben von Code zu schreiben - Visual Studio verfügt über Funktionen zum Generieren von Methoden-Stubs aus dem Code, den Sie in Ihrem Komponententest geschrieben haben. Es kann auch helfen, die Methoden zu verstehen, die das Objekt unterstützen muss - manchmal kann dies spätere Erweiterungen unterstützen (Wenn Sie eine Sicherung auf Festplatte hatten, die Sie auch überladen, um sie zu Stream zu speichern, ist dies überprüfbarer und erleichtert das Spoolen über das Netzwerk, wenn später benötigt)