Warum versteckt Go Testergebnisse? (Und wie das das Leben erschwert)
\n\nStellen Sie sich vor: Sie programmieren in Go, führen go test aus, sehen einen grünen Haken... aber etwas ist schiefgelaufen. Sie haben einen Bug behoben, führen die Tests erneut aus – und wieder grünes Licht. Aber der Bug ist immer noch da! Kommt Ihnen bekannt vor? Willkommen in der Welt des Test-Cachings in Go.
Go ist eine Sprache, die Geschwindigkeit liebt. Um nicht dieselben Tests zehnmal durchzuführen, cached der Compiler die Ergebnisse. Das klingt praktisch, bis Sie in eine Situation geraten, in der der Go-Test-Cache gegen Sie arbeitet. Besonders schmerzhaft trifft es Entwickler, die mit Integrationstests, dem Dateisystem oder externen APIs arbeiten.
\n\nIn diesem Artikel analysieren wir zwei Ansätze zur Lösung des Problems: Force Retesting (erzwungener Neustart) und die vollständige Deaktivierung des Test-Caches. Sie erfahren, wann Sie was anwenden, und erhalten funktionierende Codebeispiele.
\n\nWie funktioniert das Test-Caching in Go?
\n\nBevor wir etwas kaputt machen, lassen Sie uns verstehen, wie es funktioniert. Go cached Testergebnisse basierend auf einem Hash von:
\n- \n
- Quellcode (
.go-Dateien) \n - Testdateien \n
- Umgebungsvariablen \n
- Compiler-Flags \n
Wenn sich nichts geändert hat – zeigt Go einfach das gecachte Ergebnis. Schnell? Ja. Gefährlich? Und wie! Stellen Sie sich vor, Ihr Test hängt von der Zeit, Zufallszahlen oder einem externen Dienst ab. Der Cache sagt: „Alles okay!“, obwohl der Test längst fehlschlagen würde.
\n\n// Beispiel eines Tests, der aufgrund des Caches fälschlicherweise grün wird\nfunc TestCurrentTime(t *testing.T) {\n now := time.Now()\n if now.Year() != 2024 {\n t.Errorf("Das Jahr sollte 2024 sein, erhalten %d", now.Year())\n }\n}\n\nFühren Sie diesen Test einmal aus – er wird bestanden. Ändern Sie das Jahr im Code auf 2025? Der Cache zeigt trotzdem das alte Ergebnis. Und Sie rätseln, warum CI fehlschlägt, während lokal alles „funktioniert“.
\n\nAnsatz 1: Force Retesting (erzwungener Neustart)
\n\nDie beliebteste Methode zur Bekämpfung des Caches ist das Flag -count=1. Das ist Force Retesting in Reinform. Es sagt Go: „Glaube dem Cache nicht, starte den Test neu.“
// Ausführen mit erzwungenem Neustart\ngo test -count=1 ./...\n\nWarum -count=1 und nicht -count=0? Weil -count die Anzahl der Testdurchläufe angibt. 1 ist der minimale Wert, der den Cache deaktiviert. 0 würde einfach nichts starten.
Wann Force Retesting verwenden
\n- \n
- Integrationstests, die auf eine Datenbank oder API zugreifen \n
- Tests mit Zufallsdaten (Fuzz-Tests, UUID-Generierung) \n
- Zeitabhängige Tests (Timeouts, Daten) \n
- Lokale Entwicklung, wenn Sie häufig Code ändern \n
Beispiel: Integrationstest mit Force Retesting
\n\npackage db_test\n\nimport (\n "testing"\n "time"\n)\n\nfunc TestDatabaseConnection(t *testing.T) {\n // Dieser Test hängt von einem Live-Server ab\n // Ohne -count=1 könnte er ein altes Ergebnis anzeigen\n db := connectToDatabase()\n if err := db.Ping(); err != nil {\n t.Fatalf("Verbindung fehlgeschlagen: %v", err)\n }\n \n // Simulation einer zeitlichen Verzögerung\n time.Sleep(100 * time.Millisecond)\n if err := db.Query("SELECT 1"); err != nil {\n t.Errorf("Abfrage fehlgeschlagen: %v", err)\n }\n}\n\nAusführen: go test -count=1 -v ./db/. Jetzt ist jeder Durchlauf ehrlich. Aber es gibt einen Haken: Force Retesting löst das Problem nicht global. Wenn Sie das Flag vergessen – kommt der Cache zurück.
Ansatz 2: Vollständige Deaktivierung des Test-Caches
\n\nDie zweite Option ist radikal. Sie sagen Go einfach: „Cache nichts.“ Dies geschieht über die Umgebungsvariable GOCACHE=off oder das Flag -count=1