Soll jeder Komponententest unabhängig von anderen Tests durchgeführt werden können?

24

Angenommen, Sie haben Tests für zwei Methoden einer Klasse. Bei der ersten Methode werden Daten aus einer anderen Ebene erfasst und unabhängig von der Laufzeit in einem Speicher abgelegt (z. B. in einer SQL-Tabelle), sodass alle von diesem Test verarbeiteten Daten fest im Test codiert werden. Die zweite Methode ist dafür verantwortlich, Daten von der Stelle zu nehmen, an der die erste Methode sie verlassen hat, und sie auf irgendeine Weise zu transformieren (Berechnen, Verschieben bestimmter Teile an eine andere Stelle usw.).

Nun könnte diese zweite Methode fest codierte Eingaben wie die erste haben, oder es könnte angenommen werden, dass die beiden Tests nacheinander ausgeführt werden und dort weitermachen, wo der erste Test aufgehört hat, wobei die Daten übernommen werden, die beim ersten Test tatsächlich gespeichert wurden.

Wenn Sie sich für die zweite Option entschieden hätten, hätten Sie wirklich eine gute Idee, dass die beiden Methoden gut zusammenspielen. Wenn jedoch der erste Test fehlschlug, würden alle nachfolgenden Tests fehlschlagen, was den Testvorteil einer schnelleren Fehlerisolierung zunichte macht.

Wenn Sie sich für die erste Option entscheiden, wird jede Methode unabhängig voneinander isoliert und getestet, aber Sie werden nie wirklich wissen, dass sie wirklich richtig zusammenarbeiten können.

Welches ist hier die bessere Option? Gibt es eine Alternative wie einen einzelnen Test für jede isolierte Methode mit Hardcoding und dann größere Tests, die beide Methoden in einer enthalten?

Morgan Herlocker
quelle
2
Eigentlich wünschte ich, ich könnte die Reihenfolge der Unit-Tests bei jeder Ausführung einfach nach dem Zufallsprinzip bestimmen. Im Moment laufen sie in einer unbekannten, wenn auch relativ festen Reihenfolge.
Job

Antworten:

11

Wenn Sie sich für die erste Option entscheiden, wird jede Methode unabhängig voneinander isoliert und getestet, aber Sie werden nie wirklich wissen, dass sie wirklich richtig zusammenarbeiten können.

Wenn Ihre Methoden wirklich unabhängig sind, sollte dies keine Rolle spielen. Ihre zweite Methode sollte:

a) Arbeiten Sie korrekt, wenn Sie gültige Daten vorlegen.

b) Versagen Sie vernünftig und konsistent, wenn ungültige Daten vorliegen.

Gleichermaßen sollte Ihre erste Methode dasselbe tun. Solange Sie die Fehlerfälle behandeln, arbeiten sie ordnungsgemäß zusammen.

Wenn Sie testen möchten, ob die Methoden korrekt zusammenarbeiten, ist dies ein Integrationstest und kein Komponententest.

ChrisF
quelle
27

Wenn die Tests nicht unabhängig voneinander ausgeführt werden können, handelt es sich nicht um Komponententests.

Ein Komponententest sollte sich nicht auf einen externen Status stützen, z. B. auf den Inhalt einer Datenbanktabelle. Es sollte nur eine Codeeinheit für sich alleine testen.

Tests, die einen bestimmten Status ändern oder erfordern, sind gültig. Sie können beispielsweise Teil von Integrationstests sein. In solchen Fällen ist es wichtig sicherzustellen, dass eine geeignete Einrichtung erfolgt. Dies sind jedoch keine Komponententests. In diesem Fall würde ich immer noch nicht empfehlen, dass für einen Test ein anderer Test ausgeführt werden muss. In diesem Fall sollten Sie den erforderlichen Code wahrscheinlich in eine separate Einrichtungsmethode einbeziehen. Möglicherweise haben Sie einen Test, der dann nur den Einrichtungscode aufruft und überprüft, ob beispielsweise keine Ausnahme ausgelöst wurde, und dann einen weiteren Test, der die in der Einrichtungsmethode eingerichteten Daten aktiv verwendet.

Steve
quelle
@Steve, also würden Sie in diesem Beispiel sagen: Ein Test für Methode 1, ein Test für Methode 2 und ein Test, der 1 und 2 im selben Test ausführt?
Morgan Herlocker
2
Ja. Die ersten beiden wären Unit-Tests, die dritte klingt nach einem Integrationstest.
Steve
Wenn Sie Kundenmodul und Bestellmodul haben, können Bestellungen nicht ohne Kundenbezug erstellt werden. Wie werden Sie es unabhängig vom Kundenmodul testen? Erstellen Sie einen Kundendatensatz in der Datenbank mit sql (Einfügen in Kunden) oder verwenden Sie Customer.createCustomer (). Und meiner Meinung nach ist die Verwendung der zweiten besser, da Sie keine Logik für den Test benötigen, sondern nur dann, wenn Ihr Test zum Erstellen von Kunden erfolgreich ist.
Dainius
@Dainius. In einem Unit-Test-Szenario verwenden Sie normalerweise Scheinobjekte, sodass Sie einen Scheinkunden an Ihr Bestellmodul übergeben. Sie haben Recht, dass Sie in diesem Fall SQL nicht verwenden möchten.
Steve
In jedem Szenario, in dem Methode B von Methode A abhängt, gibt es fast immer eine Methode C, die A aufruft und dann B. Da dies der Fall ist, können Sie A, B und C unabhängig voneinander testen.
Morgan Herlocker
9

Ich bin sicher, es scheint jetzt in Ordnung zu sein, Einheitentest B durchzuführen, der von dem Zustand abhängt, den der Einheitentest B hinterlassen hat. Denken Sie jedoch an ein Jahr ab jetzt, in dem Sie tausend Einheitentests haben. Möchten Sie wirklich zehn Minuten warten, bis Ihre gesamte Testsuite abgeschlossen ist, wenn Sie Änderungen vornehmen müssen?

Das hängt natürlich von Ihrem Entwicklungsstil ab, aber wenn Sie auf eine anständige testgetriebene Entwicklung hoffen möchten, bei der Sie bei der Entwicklung eines Features möglicherweise mehrere Einzeltests durchführen, sollten Sie jedem Test die Möglichkeit geben, alleine zu arbeiten.

Steve Rukuts
quelle
1
+1 Raskolnikov, ich habe nicht in Betracht gezogen, dass dies eine enorme Zeitersparnis sein würde, wenn ich später "alle Tests" durchgeführt habe.
Morgan Herlocker
3

Klingt so, als würden Sie über Test-Setups sprechen, die auf verschiedene Arten durchgeführt werden können. Sie möchten für jeden Test eine saubere Kopie der Testdaten (Fixture genannt), damit sie nicht voneinander abhängig sind.

Es gibt verschiedene Frameworks, die diese Art von Tests ermöglichen, und Tools wie DBUnit, mit denen Sie zu Beginn und am Ende von Tests und Testsuiten schnell Datenstrukturen auf- und abbauen können.

TrueDub
quelle