Property-basiertes Testen in Go: Code schneller kaputt machen, als Sie ihn schreiben

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Wenn Unit-Tests lügen und Fehler bleiben



Sie haben 20 Unit-Tests geschrieben. Alle sind grün. CI läuft durch. Sie sind zufrieden. Und dann – ein Bug in der Produktion. Kommt Ihnen das bekannt vor? Das klassische Szenario: Sie haben nur die Fälle getestet, die Sie sich selbst ausgedacht haben. Die Realität wirft aber, wie es der Teufel will, Kombinationen auf, an die Sie nicht einmal gedacht haben.



In Go gibt es einen mächtigen, aber unterschätzten Ansatz – Property-basiertes Testen (oder Testen von Eigenschaften). Anstatt bestimmte Eingaben und Ausgaben zu überprüfen, beschreiben Sie Eigenschaften, die eine Funktion erfüllen muss, und das Framework generiert selbstständig hunderte zufälliger Testdaten. Wenn eine Eigenschaft verletzt wird – haben Sie einen Fehler gefunden.



In diesem Artikel werden wir uns ansehen, wie Sie Property-basiertes Testen in Go mit der Bibliothek gopter implementieren, echte Beispiele schreiben und sehen, welche Fehler Sie damit fangen können. Los geht's!



Was ist Property-basiertes Testen und warum wird es benötigt?



Stellen Sie sich vor, Sie testen eine Sortierfunktion. Ein typischer Unit-Test:



func TestSort(t *testing.T) {    input := []int{3, 1, 2}    result := sort(input)    expected := []int{1, 2, 3}    if !reflect.DeepEqual(result, expected) {        t.Errorf("got %v, want %v", result, expected)    }}


Okay, funktioniert. Aber was, wenn das Array leer ist? Was, wenn alle Elemente gleich sind? Was, wenn es negative Zahlen gibt? Sie können noch 10 weitere Tests schreiben, aber trotzdem etwas übersehen.



Property-basiertes Testen löst dieses Problem grundlegend: Sie formulieren Invarianten – Eigenschaften, die für jede korrekte Eingabe wahr sein müssen. Zum Beispiel für das Sortieren:



  • Die Länge des sortierten Arrays ist gleich der Länge des ursprünglichen Arrays.
  • Jedes Element des ursprünglichen Arrays ist im sortierten Array vorhanden (und umgekehrt).
  • Das Array ist aufsteigend sortiert.


Das Framework (z. B. gopter oder das integrierte testing/quick) generiert zufällige Eingabedaten und überprüft, ob alle Eigenschaften erfüllt sind. Wenn ein Fehler vorhanden ist – erfahren Sie davon, ohne zu wissen, wo Sie suchen müssen.



Go-Bibliotheken für Property-basiertes Testen



Im Go-Ökosystem gibt es mehrere Werkzeuge:



  • testing/quick – integriertes Paket, minimalistisch, aber mit eingeschränkten Möglichkeiten.
  • gopter – leistungsstarke Bibliothek mit Generatoren, Shrinking (Minimierung der Eingabedaten) und flexiblen Einstellungen. Wir empfehlen diese.
  • rapid – moderne Alternative, leistungsfähiger.


Wir werden gopter verwenden, da es die beste Dokumentation und Community hat. Installation:



go get github.com/leanovate/gopter


Unser ersten Property-basierten Test in Go schreiben



Angenommen, wir haben eine Funktion Reverse, die einen String umkehrt:



func Reverse(s string) string {    runes := []rune(s)    for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {        runes[i], runes[j] = runes[j], runes[i]    }    return string(runes)}


Welche Eigenschaft kann überprüft werden? Wenn ein String zweimal umgekehrt wird, sollten wir den ursprünglichen String erhalten:



import (    "testing"    "github.com/leanovate/gopter"    "github.com/leanovate/gopter/gen")

func TestReverseTwice(t *testing.T) { properties := gopter.NewProperties(nil)

properties.Property("reverse(reverse(s)) == s", prop.ForAll( func(s string) bool { return Reverse(Reverse(s)) == s }, gen.AnyString(), ))

properties.TestingRun(t)}


Starten Sie den Test – und gopter generiert 100 zufällige Zeichenfolgen und überprüft die Eigenschaft. Wenn alles in Ordnung ist – ist der Test grün. Wenn nicht – erhalten Sie ein Gegenbeispiel (die kleinste Zeichenfolge, bei der der Test fehlgeschlagen ist).



Bo

Blogs

Buchempfehlungen