2013-03-30 11 views
24

Ich habe mehrere Pakete für eine Web-API implementiert, jede mit ihren eigenen Testfällen. Wenn jedes Paket mit go test ./api/pkgname getestet wird, bestehen die Tests. Wenn ich alle Tests gleichzeitig mit go test ./api/... ausführen möchte, scheitern die Testfälle immer.Serielle Ausführung von Paket-Tests

In jedem Testfall neu erstellen ich das gesamte Schema mit DROP SCHEMA public CASCADE, gefolgt von CREATE SCHEMA public und alle Migrationen anwenden. Die Testsuite meldet Fehler zufällig zurück und sagt, dass eine Relation/Tabelle nicht existiert, daher denke ich, dass jede Testsuite (pro Paket) irgendwie parallel ausgeführt wird, wodurch der DB-Status in Unordnung gebracht wird.

Ich habe versucht, einige Testflaggen wie go test -cpu 1 -parallel 0 ./src/api/... ohne Erfolg zu übergeben.

Könnte das Problem hier parallel laufende Tests sein, und wenn ja, wie kann ich die serielle Ausführung erzwingen?

Update:

Derzeit verwende ich diese Abhilfe, die Tests laufen, aber ich frage mich immer noch, wenn es eine bessere Lösung ist

find <dir> -type d -exec go test {} \; 
+3

Vielleicht ist das kein Go-Problem, sondern ein Testproblem. Tests sollten keinen globalen Status haben (wie eine Verbindung zu einer Datenbank) und sollten daher in der Lage sein, parallel zu laufen. – ahofmann

+4

Nun, wie soll man dann eine API testen, die auf einem DB basiert? Alles zu verspotten würde den Testzweck einfach besiegen. –

+1

Ich bin kein Fan des globalen Teststatus, aber ich sehe hier keine andere Möglichkeit. –

Antwort

28

Wie andere haben darauf hingewiesen, nicht -Parallelbit nicht die Arbeit machen (es funktioniert nur, innerhalb von Paketen). Sie können jedoch das Flag -p = 1 verwenden, um die Paketprüfungen in Serie auszuführen. Dies wird hier dokumentiert:

http://golang.org/src/cmd/go/testflag.go

aber (AFAIK) nicht auf der Kommandozeile, Hilfe gehen, etc. Ich bin nicht sicher, dass es bleiben, um gemeint (obwohl ich behaupten würde, dass, wenn es entfernt, -parallel sollte behoben sein.)

+0

Dies funktionierte perfekt für uns in genau dem gleichen Szenario. –

+0

Arbeitete perfekt! Auf der Seite, mit der Sie verlinkt sind, kann ich jedoch keinen Verweis auf dieses Flag sehen. Vielleicht haben sie die Dokumentation dafür entfernt? –

+0

Ja, scheint wahrscheinlich. –

9

Das Go-Tool zu machen läuft Unit-Tests zur Verfügung gestellt einfacher mit der Konvention, dass * _test.go-Dateien Unittests in ihnen enthalten. Da angenommen wird, dass es sich um Unittests handelt, wird angenommen, dass sie hermetisch sind. Es hört sich so an, als ob Ihre Tests entweder keine Unittests sind oder nicht, aber sie verletzen die Annahmen, die ein Unittest erfüllen sollte.

Für den Fall, dass Sie für diese Tests Unittests meinen, benötigen Sie wahrscheinlich eine Pseudo-Datenbank für Ihre Unittests. Ein Spott, vorzugsweise in Erinnerung, Ihrer Datenbank wird sicherstellen, dass der Komponententest hermetisch ist und nicht durch andere Komponententests gestört werden kann.

Für den Fall, dass Sie diese Tests als Integrationstests verstehen, sind Sie wahrscheinlich besser dran, das go-Tool für diese Tests nicht zu verwenden. Was Sie wahrscheinlich wollen, ist eine separate Test-Binärdatei zu erstellen, deren Ausführung Sie steuern und schreiben Sie Integrationstest-Skripte in dort.

Die gute Nachricht ist, dass das Erstellen eines Mock in Go wahnsinnig einfach ist. Ändern Sie Ihren Code, um eine Schnittstelle mit den Methoden zu erstellen, die für die Datenbanken wichtig sind, und schreiben Sie dann eine In-Memory-Implementierung dieser Schnittstelle für Testzwecke und übergeben Sie sie an Ihren Anwendungscode, den Sie testen möchten.

+2

Ja, ich weiß, dass ich mich darüber lustig machen könnte, aber ich möchte tatsächlich die Datenbank durchsuchen, weshalb ich die Tests wahrscheinlich in eine separate Binärdatei verschieben werde. –

+0

Es ist eigentlich überraschend einfach, einen separaten Integrationstest 'main.go' einzurichten, da' testing' den Export 'testing.Main' durchführt. –

+0

yeah, Das ist ein Teil des Grundes, warum ich es vorgeschlagen habe :-p –

3

Nur um zu klären, @ Jeremy Antwort ist immer noch die akzeptierte ein:

Da meine Integrationstests wurden nur auf einem Paket ausführen (api), entfernte ich die separaten Test binär am Ende und erstellt ein Muster zu trennen Testtypen von:

  • Unit-Tests verwenden, um die normalen TestX Namen
  • Integrationstests verwenden Test_X

Ich habe Shell-Skripte (utest.sh/itest.sh) erstellt, um beide zu starten.

  • Für Unit-Tests go test -run="^(Test|Benchmark)[^_](.*)"
  • Für Integrationstests go test -run"^(Test|Benchmark)_(.*)"
  • Run sowohl mit dem normalen go test
+0

Danke fürs Nachfassen, das war nützlich, wenn ich in dasselbe Szenario lief. – markdsievers