[JAVA] TDD Trainingszusammenfassung

TDD-Zyklus und Babyschritt

Lassen Sie uns zunächst über die Prämisse einer testgetriebenen Entwicklung sprechen. In der testgetriebenen Entwicklung werden wir mit der Entwicklung fortfahren und den folgenden Zyklus durchlaufen.

Red -> Green -> Refactor

Red

Sie schreiben den Test, der zuerst fehlschlägt. Was bedeutet das?

Implementieren Sie für den Implementierungscode die ** Schnittstelle ** (die Implementierung ist leer, aber der Typ ist klar definiert und kann vom Test aufgerufen werden). Es sollte kein Kompilierungsfehler sein.

class FizzBuzz {
    public static String fizzbuzz(int num) {
       return null;
    }
}

Dann schreiben Sie den Testcode. Dies entspricht dem Entwerfen und Definieren von Anforderungen. Zu diesem Zeitpunkt sollte der Testcode niemals gemäß der Implementierung geschrieben werden **. ** ** **

public class FizzBuzzTest {
    @Test
public void Die Nummer 3 ist fizz() {
        assertThat(FizzBuzz.fizzbuzz(3), is("fizz"));
    }
}

Der Test wird natürlich fehlschlagen. Das Wichtigste dabei ist, dass ** Rot ** den Weg zur nächsten Implementierung weist und zu einem ** lebendigen Design ** wird.

FizzBuzzTest >Die Nummer 3 ist fizz FAILED
    java.lang.AssertionError:
    Expected: is "fizz"
         but: was null
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.junit.Assert.assertThat(Assert.java:956)
        at org.junit.Assert.assertThat(Assert.java:923)
        at FizzBuzzTest.Die Nummer 3 ist Fizz(FizzBuzzTest.java:9)

Green

Grün hat eine ** minimale ** Implementierung, die den Test besteht. Wenn der Testcode (Design) zu diesem Zeitpunkt keinen Fehler enthält, dürfen Sie ihn überhaupt nicht manipulieren. Führen Sie den kürzesten Weg zur Straße, die auf die Implementierung zeigt. Schreiben Sie beispielsweise keinen Code wie folgt, egal wie gut Sie die Antwort kennen: Ich werde später erklären, warum Sie die Antwort nicht schreiben sollten.

public class FizzBuzz {

    public static String fizzbuzz(int num) {
        if(num % 3 == 0) {
            return "fizz";
        }
        else {
            return null;
        }
    }
}

Die Mindestimplementierung ist wie folgt.

public class FizzBuzz {

    public static String fizzbuzz(int num) {
        return "fizz";
    }
}

Refactor

Wenn es nichts Besonderes gibt, wird es übersprungen.

Wieder rot

Es ist der nächste TDD-Zyklus. Die Sache zu tun ist die gleiche. Schreiben Sie einen fehlgeschlagenen Test und zeigen Sie auf den nächsten Pfad.

public class FizzBuzzTest {
    @Test
public void Die Nummer 3 ist fizz() {
        assertThat(FizzBuzz.fizzbuzz(3), is("fizz"));
    }

    @Test
public void Die Nummer 5 ist Buzz() {
        assertThat(FizzBuzz.fizzbuzz(5), is("buzz"));
    }
}

Jetzt ist es ein Fehler, weil es ein Mann ist, der "Fizz" zurückgibt, egal welche Zahl kommt.

FizzBuzzTest >Die Nummer 5 ist Buzz FAILED
    java.lang.AssertionError:
    Expected: is "buzz"
         but: was "fizz"
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.junit.Assert.assertThat(Assert.java:956)
        at org.junit.Assert.assertThat(Assert.java:923)
        at FizzBuzzTest.Die Nummer 5 ist Buzz(FizzBuzzTest.java:14)

Zum zweiten Mal Grün

Schreiben Sie die Antwort natürlich nicht plötzlich wie zuvor. Beachten Sie nur die Mindestimplementierung. Benutze deinen Kopf nicht. Überlegen Sie, in gutem Tempo zum nächsten Zyklus überzugehen.

public class FizzBuzz {

    public static String fizzbuzz(int num) {
        if(num == 3) {
            return "fizz";
        } else {
            return "buzz";
        }
    }
}

Refactoring wird erneut ignoriert

Es sieht gut aus ...

Es ist an der Zeit, Red3 zu verstehen

Fügen wir ein Vielfaches von 3 außer 3 ein.

public class FizzBuzzTest {
    @Test
public void Die Nummer 3 ist fizz() {
        assertThat(FizzBuzz.fizzbuzz(3), is("fizz"));
    }

    @Test
public void Die Nummer 6 ist fizz() {
        assertThat(FizzBuzz.fizzbuzz(6), is("fizz"));
    }

    @Test
public void Die Nummer 5 ist Buzz() {
        assertThat(FizzBuzz.fizzbuzz(5), is("buzz"));
    }
}

Es geht in die else-Klausel und gibt "Buzz" zurück, so dass es rot wird.

FizzBuzzTest >Die Nummer 6 ist fizz FAILED
    java.lang.AssertionError:
    Expected: is "fizz"
         but: was "buzz"
        at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
        at org.junit.Assert.assertThat(Assert.java:956)
        at org.junit.Assert.assertThat(Assert.java:923)
        at FizzBuzzTest.Die Nummer 6 ist Fizz(FizzBuzzTest.java:14)

Endlich Green implementiert

Wenn Sie die Mindestimplementierung vorantreiben möchten, können Sie den folgenden bösen Code endlos schreiben. Kehren wir jedoch zu den Anforderungen zurück und implementieren Sie ihn.

public class FizzBuzz {

    public static String fizzbuzz(int num) {
        //Wie erwartet, spielt das herum!
        if(num == 3 || num == 6){
            return "fizz";
        } else {
            return "buzz";
        }
    }
}

Ja. Dies ist eine einfache Implementierung! Fragen wir uns, warum wir das hier nicht plötzlich tun sollten. Angenommen, Sie haben diese Implementierung im Fall von Nummer 3. Würden Sie dann einen Test schreiben, wenn num 6 ist? Da Menschen im Grunde genommen auf diejenigen hinarbeiten, die sich wohl fühlen, ist es wahrscheinlich, dass sie nicht schreiben werden. Da diesmal FizzBuzz das Thema ist, erkenne ich, dass "so etwas kann man keinen Fehler machen", aber Menschen sind Kreaturen, die Fehler machen, und selbst einfache Implementierungen, die normalerweise durchgeführt werden, neigen dazu, die Überprüfung zu überspringen und Fehler zu machen.

public class FizzBuzz {

    public static String fizzbuzz(int num) {
        if(num % 3 == 0) {
            return "fizz";
        } else {
            return "buzz";
        }
    }
}

Ich möchte den Testzyklus hier stoppen und zusammenfassen. Der wichtige Punkt hierbei ist, dass Sie durch Starten des Testzyklus von Test zuerst (Rot zuerst) verhindern können, dass die Implementierung führt, und die Garantie erhalten, dass die Implementierung vom Test abgedeckt wird und der Test nicht ausreicht. Und es war sehr wichtig, das gleiche Problem wie beim Test zuerst durch kleine Schritte zu lösen und die Granularität der Probleme, mit denen sofort konfrontiert wird, zu verringern und das Implementierungstempo zu erhöhen (verwenden Sie nicht das Gehirn). .. Für diejenigen, die noch nie zuvor TDD gemacht haben, ist es sehr wichtig, die Einstellung zu wechseln, daher ist es wichtig, ** täglich zu trainieren **. Kein Athlet kann eine aktive Rolle spielen, ohne zu üben. Versuchen Sie, den TDD-Zyklus vor einem einfachen Beispiel zu schützen und ein Gefühl für den Babyschritt zu bekommen.

Testgeschwindigkeit und -menge

Ob TDD langsam ist oder nicht, wird häufig als Tagesordnungspunkt angesprochen. Wird die Entwicklungsgeschwindigkeit durch das Schreiben des Tests verlangsamt? Betrachten wir das obige FizzBuzz-Beispiel. Implementieren Sie FizzBuzz sofort. Möchten Sie es so liefern, wie es ist? Wahrscheinlich nicht. Ich weiß nicht, ob es sich um eine Benutzeroberfläche oder eine CLI handelt, aber ich werde es wahrscheinlich ausführen und überprüfen.

printf Möchten Sie debuggen? Wenn ja, sollten Sie dies möglicherweise wie folgt überprüfen.

―― 3 ist Sprudel --Nächste, 5 ist Buzz

Das? Du weißt etwas ... Korrekt. TDD ist derselbe Ablauf, mit dem Sie die Anwendung tatsächlich überprüfen. Was ist der Unterschied? Die Ausführungsbestätigung ist nur eine Ad-hoc-Überprüfung. Wenn eine Änderung im Code auftritt, wird die Bestätigung bedeutungslos und nur "Sie" bestätigen sie. Stellen Sie sich vor, dies ist eine komplexe Verflechtung von Funktionen wie bei einem echten Produkt. Möchten Sie TDD? Möchten Sie manuell prüfen?

Grundsätzlich werde ich weiterhin über die Anzahl der Tests schreiben, bis meine Angst verschwindet. Darüber hinaus wächst der doppelte Code im Testcode. In diesem Fall ist es eine gute Idee, geeignete Refactoring- und parametrisierte Tests durchzuführen.

Recommended Posts

TDD Trainingszusammenfassung
Zusammenfassung
Objektorientierte Zusammenfassung
Rspec, TDD (1)
Ransack Zusammenfassung