Ich teste eine REST-API. Angenommen, es wird eine JSON-Struktur zurückgegeben. Was ist der beste Ansatz zum Testen des Servers? Jeder Testschritt kann nur erfolgreich sein, wenn alle vorherigen erfolgreich waren.
Struktur A: Testen Sie alles auf einmal
- Test method 1:
- make server request
- assert http response code was 200
- assert returned file is not empty
- assert returned file has valid JSON syntax
- assert returned JSON contains key X
Dies scheint die beste Lösung zu sein.
Vorteile:
- Nur eine Serveranforderung
- Ich teste das Verhalten als Ganzes. "Gibt der Server einen JSON mit dem Schlüssel X zurück?"
Struktur B: Fügen Sie jedem Test nach und nach Asserts hinzu
- Test method 1:
- make server request
- assert http response code was 200
- Test method 2:
- make server request
- assert returned file is not empty
- Test method 3:
- make server request
- assert returned file has valid JSON syntax
- Test method 4:
- make server request
- assert returned JSON contains key X
So habe ich angefangen und war überzeugt, dass dies der richtige Weg sein sollte, da jede Methode nur eine einzige Sache testet und dies zu einer besseren Trennung führt. Aber jetzt denke ich, da dies keine Unit-Tests sind, ist meine Trennung nicht angemessen und ich sollte das Verhalten als Ganzes testen.
Struktur C: Einmalige Anforderung stellen und separate Testmethoden für die zwischengespeicherte Antwort ausführen
- make server request and cache it (allow read-only access)
- Test method 1:
- assert http response code was 200 on cached server request
- Test method 2:
- assert returned file is not empty on cached server request
- Test method 3:
- assert returned file has valid JSON syntax on cached server request
- Test method 4:
- assert returned JSON contains key X on cached server request
Vorteile:
- Keine wiederholte (teure) Serveranfrage
- Hat immer noch Single-Assert-Testmethoden
Welches ist die sinnvollste Teststruktur?
testing
acceptance-testing
mrplow
quelle
quelle
Antworten:
Best Practices haben immer einen Zweck, einen Grund dahinter. Es ist immer eine gute Idee, diese Gründe in Ihrem Design zu berücksichtigen - insbesondere, wenn Sie entscheiden möchten, wie und wie schwer es ist, diese Best Practices zu befolgen.
In diesem Fall besteht der Hauptgrund dafür, dass jeder Test zu einer einzigen Sache wird, darin, dass die zweite nicht getestet wird, wenn die erste fehlschlägt. Da zu viele Meinungsmacher es zu verdienen scheinen, alles auf das kleinstmögliche Maß zu brechen und jedes Stück so weit wie möglich aufzublähen, entstand die Idee, dass jeder Test eine einzige Behauptung enthalten sollte.
Folge dem nicht blind. Selbst wenn jeder Test eine Sache testen sollte, sollten Sie dennoch überlegen, wie groß oder klein jede "Sache" sein soll, und um dies zu tun, müssen Sie bedenken, warum jeder Test eine Sache testen soll - um sicherzugehen Ein Fehler in der ersten Sache lässt die zweite Sache nicht ungetestet.
Sie müssen sich also fragen: "Brauche ich diese Garantie hier wirklich?"
Angenommen, im ersten Testfall liegt ein Fehler vor - der HTTP-Antwortcode ist dies nicht
200
. Sie beginnen also, den Code zu hacken, herauszufinden, warum Sie nicht den Antwortcode erhalten haben, den Sie haben sollten, und beheben das Problem. Und was jetzt?Es gibt noch einige Dinge zu beachten:
Abhängigkeiten von Behauptungen
Ich weiß, dass die von Ihnen beschriebenen Tests nur ein Beispiel sind und Ihre tatsächlichen Tests wahrscheinlich komplizierter sind. Was ich also sagen werde, ist möglicherweise nicht so stark gültig wie die tatsächlichen Tests, aber es kann dennoch etwas effektiv sein, so dass Sie Vielleicht möchten Sie es in Betracht ziehen.
Wenn Sie einen REST-Service (oder ein anderes HTTP-Protokoll) haben, der Antworten im JSON-Format zurückgibt, schreiben Sie normalerweise eine einfache Client-Klasse, mit der Sie die REST-Methoden wie reguläre Methoden verwenden können, die reguläre Objekte zurückgeben. Unter der Annahme, dass der Client separate Tests hat, um sicherzustellen, dass es funktioniert, hätte ich die ersten 3 Behauptungen verworfen und nur 4 behalten!
Warum?
Sie müssen also nicht alle diese Tests ausführen - führen Sie einfach den vierten Test aus. Wenn einer der Fehler auftritt, die die ersten drei zu erkennen versuchen, schlägt der Test mit einer geeigneten Ausnahme fehl, bevor Sie überhaupt die tatsächliche Bestätigung erhalten.
Wie möchten Sie die Berichte erhalten?
Angenommen, Sie erhalten keine E-Mails von einem Testserver, sondern die QS-Abteilung führt die Tests aus und benachrichtigt Sie über fehlgeschlagene Tests.
Jack von QA klopft an deine Tür. Er sagt, dass die erste Testmethode fehlgeschlagen ist und die REST-Methode einen schlechten Antwortcode zurückgegeben hat. Sie danken ihm und suchen nach der Grundursache.
Dann kommt Jen von der Qualitätssicherung und sagt, dass die dritte Testmethode fehlgeschlagen ist - die REST-Methode hat keinen gültigen JSON im Antworttext zurückgegeben. Sie sagen ihr, dass Sie sich diese Methode bereits ansehen, und Sie glauben, dass dasselbe, was dazu geführt hat, dass ein fehlerhafter Exit-Code zurückgegeben wurde, auch dazu geführt hat, dass etwas zurückgegeben wurde, das kein gültiger JSON ist und eher wie ein Exception-Stack-Trace aussieht.
Sie können wieder arbeiten, aber dann kommt Jim von der Qualitätssicherung und sagt, dass die vierte Testmethode fehlgeschlagen ist und die Antwort keinen X-Schlüssel enthält ...
Sie können nicht einmal nach dem Grund suchen, da es schwierig ist, Code anzuzeigen, wenn Sie keinen Computerbildschirm haben. Wenn Jim schnell genug wäre, hätte er rechtzeitig ausweichen können ...
E - Mails von dem Testserver sind leichter zu entlassen, aber immer noch - würden Sie nicht lieber nur mitteilen, ONCE , dass etwas mit dem Testverfahren, und Blick auf den relevanten Testprotokollen selbst falsch ist?
quelle
Wenn Sie davon ausgehen können, dass sich eine Serveranforderung mit denselben Parametern immer gleich verhält, ist Methode B fast sinnlos. Warum sollten Sie viermal dieselbe Methode aufrufen, um viermal dieselben Antwortdaten zu erhalten, wenn ein Aufruf ausreicht?
Und wenn Sie dies nicht sicher annehmen können und es Teil des Tests machen möchten, ist es möglicherweise besser, den Test A mehrmals auszuführen.
Die einzige hypothetische Situation, in der B einen Nutzen haben könnte, besteht darin, dass in Ihrem Testframework nur explizite Testmethoden ein- und ausgeschaltet werden können und Sie erwarten, dass dies für die einzelnen Schritte Ihres Tests erforderlich ist.
Alternative C scheint A mit dem einen Vorteil zu kombinieren, den ich oben für B erwähnt habe. Wenn Ihr Testframework eine einfache Strukturierung Ihres Codes ohne großen Aufwand über B ermöglicht, ist dies ein praktikabler Ansatz. Dies fügt A jedoch eine zusätzliche Komplexität hinzu, sodass ich es nur verwenden würde, wenn ich jemals die einzelnen Tests ein- und ausschalten möchte, andernfalls das YAGNI-Prinzip anwenden und mich an die einfachste Lösung (A) halten möchte.
TLDR: Beginnen Sie mit A, wenn Sie sicher sind, dass immer alle Asserts in einem Test ausgeführt werden sollen, und überarbeiten Sie C, wenn Sie feststellen, dass Sie die einzelnen Asserts von außen leichter kontrollieren müssen.
quelle
Vermeiden Sie wie bei jedem Code eine vorzeitige Optimierung. Schreiben Sie zuerst Ihre Tests so, dass sie einfach zu lesen und zu warten sind. Wenn die Tests zu langsam werden, optimieren Sie sie. In Ihrem ziemlich einfachen Beispiel sind A und B beide leicht zu lesen und zu warten. Wählen Sie also das gewünschte aus, bis die Dinge zu langsam (Struktur B) oder zu kompliziert (Struktur A) werden.
Wenn Ihr Server zustandslos ist, können Sie die tatsächliche Antwort mit einer erwarteten Antwort vergleichen, um die gesamte Nachricht auf einmal zu überprüfen. Dies geht natürlich zu Lasten der Lesbarkeit.
Wenn Ihr Server voll ist und Sie mehrere langsame API-Aufrufe ausführen müssen, um den Server für den Test in einen Zustand zu versetzen, müssen Sie einen anderen Ansatz wählen, oder die Ausführung Ihrer Tests kann Minuten dauern. Sie können beispielsweise eine Datenbankaktualisierung ausführen, um Daten in eine Testdatenbank einzufügen, damit Sie ein Objekt schnell in einen geeigneten Status zum Testen bringen können. Der Test ist schnell und lesbar, aber schwieriger zu warten. Alternativ können Sie möglicherweise eine Fassade vor die API schreiben, sodass aus mehreren API-Aufrufen einzelne API-Aufrufe werden, die dem von Ihnen getesteten Geschäftsprozess besser entsprechen.
quelle
Tests sollten keine gemeinsamen Dinge haben - von Grund auf vermeiden Sie den Einfluss eines Tests auf einen anderen. Auf diese Weise können Sie auch Tests in zufälliger Reihenfolge ausführen.
Der C-Weg sollte also nicht akzeptiert werden.
Fragen Sie sich beim Schreiben von Code (oder vielleicht sogar beim Erstellen von etwas anderem) immer: "Warum gibt es solche Praktiken?"
Warum sagen wir, dass es für alles verschiedene Tests geben sollte?
Es gibt zwei Fälle, in denen Sie dies benötigen:
Es gibt zwei Gründe, warum Sie mit diesen Fällen konfrontiert sind:
Wenn Sie aus irgendeinem Grund nicht mindestens einem dieser Gründe erklären kann zu haben , einfach blind die nehmen Struktur B .
Im anderen Fall (ich hoffe , dass Sie hier) Sie wählen ein .
Sie können diese Frage auch auf der Website zur Softwarequalitätssicherung und zum Testen von Stackexchange stellen.
quelle