Der Hauptunterschied besteht für mich darin, dass Integrationstests zeigen, ob eine Funktion funktioniert oder defekt ist, da sie den Code in einem realitätsnahen Szenario belasten. Sie rufen eine oder mehrere Softwaremethoden oder -funktionen auf und testen, ob sie wie erwartet funktionieren.
Im Gegenteil, ein Unit-Test , der eine einzelne Methode testet, basiert auf der (oft falschen) Annahme, dass der Rest der Software korrekt funktioniert, da jede Abhängigkeit explizit verspottet wird.
Wenn ein Komponententest für eine Methode, die eine Funktion implementiert, grün ist, bedeutet dies nicht, dass die Funktion funktioniert.
Angenommen, Sie haben irgendwo eine Methode wie diese:
public SomeResults DoSomething(someInput) {
var someResult = [Do your job with someInput];
Log.TrackTheFactYouDidYourJob();
return someResults;
}
DoSomething
ist für Ihren Kunden sehr wichtig: Es ist eine Funktion, die einzige Sache, die zählt. Deshalb sollten Sie in der Regel eine Gurke Spezifikation schreiben sie behaupten: Sie wollen überprüfen und kommunizieren die Funktion arbeitet oder nicht.
Feature: To be able to do something
In order to do something
As someone
I want the system to do this thing
Scenario: A sample one
Given this situation
When I do something
Then what I get is what I was expecting for
Kein Zweifel: Wenn der Test erfolgreich ist, können Sie bestätigen, dass Sie eine funktionierende Funktion bereitstellen. Dies können Sie als Business Value bezeichnen .
Wenn Sie einen Komponententest für schreiben möchten, DoSomething
sollten Sie (mithilfe einiger Mocks) so tun, als ob die restlichen Klassen und Methoden funktionieren (dh alle Abhängigkeiten, die die Methode verwendet, funktionieren ordnungsgemäß), und sicherstellen, dass Ihre Methode funktioniert.
In der Praxis machen Sie so etwas wie:
public SomeResults DoSomething(someInput) {
var someResult = [Do your job with someInput];
FakeAlwaysWorkingLog.TrackTheFactYouDidYourJob(); // Using a mock Log
return someResults;
}
Sie können dies mit Dependency Injection oder einer Factory-Methode oder einem Mock Framework tun oder einfach die zu testende Klasse erweitern.
Angenommen, es liegt ein Fehler vor Log.DoSomething()
. Glücklicherweise wird die Gherkin-Spezifikation sie finden und Ihre End-to-End-Tests werden fehlschlagen.
Die Funktion funktioniert nicht, weil sie Log
defekt ist und nicht, weil [Do your job with someInput]
sie ihre Arbeit nicht erledigt. Übrigens [Do your job with someInput]
liegt die alleinige Verantwortung für diese Methode.
Angenommen, Log
wird in 100 anderen Features und in 100 anderen Methoden von 100 anderen Klassen verwendet.
Ja, 100 Funktionen werden fehlschlagen. Glücklicherweise schlagen auch 100 End-to-End-Tests fehl und decken das Problem auf. Und ja: Sie sagen die Wahrheit .
Es ist eine sehr nützliche Information: Ich weiß, dass ich ein defektes Produkt habe. Es sind auch sehr verwirrende Informationen: Sie sagen mir nichts darüber, wo das Problem liegt. Es teilt mir das Symptom mit, nicht die Grundursache.
Doch DoSomething
‚s Unit - Test ist grün, weil es eine Fälschung ist mit Log
, gebaut , um nie zu brechen. Und ja: es lügt eindeutig . Es kommuniziert, dass eine defekte Funktion funktioniert. Wie kann es nützlich sein?
(Wenn DoSomething()
der Komponententest fehlschlägt, stellen Sie sicher, dass er [Do your job with someInput]
einige Fehler aufweist.)
Angenommen, dies ist ein System mit einer fehlerhaften Klasse:
Ein einzelner Fehler führt zu mehreren Funktionsstörungen und mehrere Integrationstests schlagen fehl.
Auf der anderen Seite wird derselbe Fehler nur einen Unit-Test brechen.
Vergleichen Sie nun die beiden Szenarien.
Der gleiche Fehler wird nur einen Unit-Test brechen.
- Alle Ihre Funktionen, die das defekte verwenden,
Log
sind rot
- Alle Ihre Unit-Tests sind grün, nur der Unit-Test für
Log
ist rot
Tatsächlich sind Komponententests für alle Module, die eine fehlerhafte Funktion verwenden, grün, da sie mithilfe von Mocks Abhängigkeiten entfernt haben. Mit anderen Worten, sie laufen in einer idealen, vollständig fiktiven Welt. Und dies ist die einzige Möglichkeit, Fehler zu isolieren und zu suchen. Unit Testing bedeutet Spott. Wenn Sie nicht verspotten, sind Sie keine Unit-Tests.
Der Unterschied
Integrationstests zeigen, was nicht funktioniert. Sie können jedoch nicht erraten, wo das Problem liegen könnte.
Unit-Tests sind die einzigen Tests, die Ihnen sagen, wo genau der Fehler liegt. Um diese Informationen zu zeichnen, müssen sie die Methode in einer verspotteten Umgebung ausführen, in der alle anderen Abhängigkeiten ordnungsgemäß funktionieren sollen.
Deshalb denke ich, dass Ihr Satz "Oder ist es nur ein Unit-Test, der 2 Klassen umfasst" irgendwie verschoben ist. Ein Unit-Test sollte niemals 2 Klassen umfassen.
Diese Antwort ist im Grunde eine Zusammenfassung dessen, was ich hier geschrieben habe: Unit-Tests lügen, deshalb liebe ich sie .