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 .
Wenn ich Unit-Tests schreibe, beschränke ich den Umfang des zu testenden Codes auf die Klasse, die ich gerade schreibe, indem ich Abhängigkeiten verspotte. Wenn ich eine Satzklasse schreibe und Satz eine Abhängigkeit von Word hat, verwende ich ein Scheinwort. Durch das Verspotten von Word kann ich mich nur auf die Benutzeroberfläche konzentrieren und die verschiedenen Verhaltensweisen meiner Satzklasse testen, wenn sie mit der Benutzeroberfläche von Word interagiert. Auf diese Weise teste ich nur das Verhalten und die Implementierung von Satz und nicht gleichzeitig die Implementierung von Word.
Nachdem ich die Komponententests geschrieben habe, um sicherzustellen, dass sich Satz korrekt verhält, wenn er mit Word basierend auf der Word-Oberfläche interagiert, schreibe ich den Integrationstest, um sicherzustellen, dass meine Annahmen zu den Interaktionen korrekt waren. Dazu liefere ich die eigentlichen Objekte und schreibe einen Test, der eine Funktion ausübt, die sowohl Satz als auch Wort verwendet.
quelle
Meine 10 Bits: D.
Mir wurde immer gesagt, dass Unit Tests das Testen einer einzelnen Komponente sind - was in vollem Umfang durchgeführt werden sollte. Dies hat in der Regel viele Ebenen, da die meisten Komponenten aus kleineren Teilen bestehen. Für mich ist eine Einheit ein funktionaler Bestandteil des Systems. Es muss also etwas Wertvolles bereitstellen (dh keine Methode zum Parsen von Zeichenfolgen, sondern möglicherweise einen HtmlSanitizer ).
Integrationstests sind der nächste Schritt, bei dem eine oder mehrere Komponenten verwendet werden und sichergestellt wird, dass sie ordnungsgemäß zusammenarbeiten. Sie müssen sich dann keine Gedanken mehr darüber machen, wie die Komponenten einzeln funktionieren. Wenn Sie jedoch HTML in Ihr HtmlEditControl eingeben , ist dies der Fall irgendwie magisch weiß, ob es gültig ist oder nicht ..
Es ist allerdings eine wirklich bewegliche Linie. Ich würde mich lieber darauf konzentrieren, dass der verdammte Code auf Hochtouren funktioniert ^ _ ^
quelle
Unit-Tests verwenden Mocks
Sie sprechen von Integrationstests, die tatsächlich die gesamte Integration Ihres Systems testen. Wenn Sie jedoch Unit-Tests durchführen, sollten Sie jede Einheit einzeln testen. Alles andere sollte verspottet werden.
Sentence
Wenn in Ihrem Fall der KlasseWord
Klasse verwendet wird, sollte IhreWord
Klasse verspottet werden. Auf diese Weise testen Sie nur IhreSentence
Klassenfunktionalität.quelle
Ich denke, wenn Sie über Integrationstests nachdenken, sprechen Sie eher von einer Kreuzung zwischen physischen als von logischen Schichten.
Wenn sich Ihre Tests beispielsweise mit dem Generieren von Inhalten befassen, handelt es sich um einen Komponententest: Wenn sich Ihr Test nur mit dem Schreiben auf die Festplatte befasst, handelt es sich immer noch um einen Komponententest. Sobald Sie jedoch sowohl die E / A als auch den Inhalt der Datei getestet haben, dann haben Sie selbst einen Integrationstest. Wenn Sie die Ausgabe einer Funktion innerhalb eines Dienstes testen, handelt es sich um einen Komponententest. Wenn Sie jedoch einen Dienstaufruf durchführen und feststellen, ob das Funktionsergebnis dasselbe ist, handelt es sich um einen Integrationstest.
Technisch gesehen kann man sowieso nicht nur eine Klasse testen. Was ist, wenn Ihre Klasse aus mehreren anderen Klassen besteht? Ist das automatisch ein Integrationstest? Das glaube ich nicht.
quelle
mit Single-Responsibility-Design, seine schwarz und weiß. Mehr als eine Verantwortung, es ist ein Integrationstest.
Beim Ententest (sieht aus, quakt, watschelt, es ist eine Ente) ist es nur ein Einheitentest mit mehr als einem neuen Objekt.
Wenn Sie in mvc einsteigen und es testen, sind Controller-Tests immer eine Integration, da der Controller sowohl eine Modelleinheit als auch eine Ansichtseinheit enthält. Wenn ich die Logik in diesem Modell teste, würde ich einen Komponententest nennen.
quelle
Die Art Ihrer Tests
Ein Komponententest von Modul X ist ein Test, der Probleme nur in Modul X erwartet (und auf Probleme prüft).
Ein Integrationstest vieler Module ist ein Test, der Probleme erwartet, die sich aus der Zusammenarbeit zwischen den Modulen ergeben, so dass diese Probleme nur mit Komponententests schwer zu finden sind.
Stellen Sie sich die Art Ihrer Tests folgendermaßen vor:
Denken Sie daran, dass ein Integrationstest möglicherweise immer noch einige seiner Abhängigkeiten aufhebt / fälscht / verspottet . Dies bietet viel Mittelweg zwischen Unit-Tests und Systemtests (die umfassendsten Integrationstests, bei denen das gesamte System getestet wird).
Pragmatischer Ansatz, beides zu nutzen
Ein pragmatischer Ansatz wäre also: Verlassen Sie sich so weit wie möglich flexibel auf Integrationstests und verwenden Sie Unit-Tests, wenn dies zu riskant oder unpraktisch wäre. Diese Art des Denkens kann nützlicher sein als eine dogmatische Unterscheidung von Komponententests und Integrationstests.
quelle
Im Unit-Test testen Sie jedes Teil isoliert:
Im Integrationstest testen Sie viele Module Ihres Systems:
und das passiert, wenn Sie nur Unit-Tests verwenden (im Allgemeinen funktionieren beide Fenster, leider nicht zusammen):
Quellen: Quelle1 Quelle2
quelle
Meiner Meinung nach lautet die Antwort "Warum ist das wichtig?"
Liegt es daran, dass Sie Unit-Tests durchführen und Integrationstests nicht? Oder umgekehrt? Natürlich nicht, Sie sollten versuchen, beides zu tun.
Liegt es daran, dass Komponententests schnell, isoliert, wiederholbar, selbstvalidierend und zeitnah sein müssen und Integrationstests dies nicht sollten? Natürlich nicht, alle Tests sollten diese sein.
Es liegt daran, dass Sie Mocks in Unit-Tests verwenden, diese aber nicht in Integrationstests? Natürlich nicht. Dies würde bedeuten, dass ich, wenn ich einen nützlichen Integrationstest habe, für einen Teil keinen Mock hinzufügen darf, aus Angst, ich müsste meinen Test in "Unit Test" umbenennen oder ihn einem anderen Programmierer übergeben, um daran zu arbeiten.
Liegt es daran, dass Unit-Tests eine Einheit und Integrationstests eine Reihe von Einheiten testen? Natürlich nicht. Von welcher praktischen Bedeutung ist das? Die theoretische Diskussion über den Umfang der Tests bricht in der Praxis ohnehin zusammen, da der Begriff "Einheit" vollständig kontextabhängig ist. Auf Klassenebene kann eine Einheit eine Methode sein. Auf Baugruppenebene kann eine Einheit eine Klasse sein, und auf Serviceebene kann eine Einheit eine Komponente sein. Und selbst Klassen verwenden andere Klassen. Welche ist die Einheit?
Es ist nicht wichtig.
Testen ist wichtig, ERSTES ist wichtig, Haare über Definitionen zu spalten ist Zeitverschwendung, die Neulinge nur zum Testen verwirrt.
quelle
Ich denke, ich würde immer noch ein paar interagierende Klassen als Komponententest bezeichnen, vorausgesetzt, die Komponententests für Klasse1 testen die Funktionen von Klasse1, und die Komponententests für Klasse2 testen ihre Funktionen und treffen auch nicht auf die Datenbank.
Ich nenne einen Test einen Integrationstest, wenn er den größten Teil meines Stapels durchläuft und sogar die Datenbank erreicht.
Ich mag diese Frage wirklich, weil mir die TDD-Diskussion manchmal etwas zu puristisch erscheint und es gut für mich ist, einige konkrete Beispiele zu sehen.
quelle
Ich mache das gleiche - ich nenne sie alle Unit-Tests, aber irgendwann habe ich einen "Unit-Test", der so viel abdeckt, dass ich ihn oft in "..IntegrationTest" umbenenne - nur eine Namensänderung, nichts anderes ändert sich.
Ich denke, es gibt eine Fortsetzung von "Atomtests" (Testen einer winzigen Klasse oder einer Methode) zu Komponententests (Klassenebene) und Integrationstests - und dann zu Funktionstests (die normalerweise viel mehr Dinge von oben nach unten abdecken). - Es scheint keinen sauberen Schnitt zu geben.
Wenn Ihr Test Daten einrichtet und möglicherweise eine Datenbank / Datei usw. lädt, handelt es sich möglicherweise eher um einen Integrationstest (Integrationstests verwenden weniger Mocks und mehr echte Klassen, aber das bedeutet nicht, dass Sie einige nicht verspotten können vom System).
quelle
Unit Testing ist eine Testmethode, mit der überprüft wird, ob die einzelnen Einheiten des Quellcodes ordnungsgemäß funktionieren.
Integrationstests sind die Phasen des Softwaretests, in denen einzelne Softwaremodule als Gruppe kombiniert und getestet werden.
Wikipedia definiert eine Einheit als den kleinsten testbaren Teil einer Anwendung, die in Java / C # eine Methode ist. Aber in Ihrem Beispiel von Wort- und Satz Klasse würde ich wahrscheinlich schreiben Sie einfach die Tests für Satz , da ich wahrscheinlich eine verwenden , finden würde Overkill Mock , um Wortklasse den Satz Klasse zu testen. Der Satz wäre also meine Einheit, und das Wort ist ein Implementierungsdetail dieser Einheit.
quelle
Integrationstests: Die Datenbankpersistenz wird getestet.
Unit-Tests: Der Datenbankzugriff wird verspottet. Codemethoden werden getestet.
quelle
Unit-Tests sind Tests gegen eine Arbeitseinheit oder einen Codeblock, wenn Sie möchten. Wird normalerweise von einem einzelnen Entwickler durchgeführt.
Integrationstests beziehen sich auf den Test, der vorzugsweise auf einem Integrationsserver durchgeführt wird, wenn ein Entwickler seinen Code in ein Quellcodeverwaltungs-Repository überträgt. Integrationstests können von Dienstprogrammen wie Cruise Control durchgeführt werden.
Sie führen also Ihre Unit-Tests durch, um zu überprüfen, ob die von Ihnen erstellte Arbeitseinheit funktioniert, und dann überprüft der Integrationstest, ob alles, was Sie dem Repository hinzugefügt haben, nichts anderes beschädigt hat.
quelle
Ich nenne Unit-Tests jene Tests, bei denen White-Box-Tests eine Klasse sind. Alle Abhängigkeiten, die für die Klasse erforderlich sind, werden durch gefälschte ersetzt (Mocks).
Integrationstests sind Tests, bei denen mehrere Klassen und ihre Interaktionen gleichzeitig getestet werden. In diesen Fällen werden nur einige Abhängigkeiten gefälscht.
Ich würde die Integrationstests von Controller nicht aufrufen, es sei denn, eine ihrer Abhängigkeiten ist eine echte (dh nicht gefälschte) (z. B. IFormsAuthentication).
Die Trennung der beiden Testarten ist nützlich, um das System auf verschiedenen Ebenen zu testen. Außerdem sind Integrationstests in der Regel langlebig und Unit-Tests sollten schnell sein. Die Unterscheidung der Ausführungsgeschwindigkeit bedeutet, dass sie unterschiedlich ausgeführt werden. In unseren Entwicklungsprozessen werden Unit-Tests beim Check-in ausgeführt (was in Ordnung ist, da sie sehr schnell sind), und Integrationstests werden ein- / zweimal pro Tag ausgeführt. Ich versuche, Integrationstests so oft wie möglich durchzuführen, aber normalerweise treffe ich die Datenbank / schreibe in Dateien / verlangsame die / etc von rpc.
Dies wirft einen weiteren wichtigen Punkt auf: Bei Unit-Tests sollte vermieden werden, dass E / A (z. B. Festplatte, Netzwerk, Datenbank) getroffen werden. Ansonsten verlangsamen sie sich sehr. Es ist ein wenig mühsam, diese E / A-Abhängigkeiten zu entwerfen - ich kann nicht zugeben, dass ich der Regel "Unit-Tests müssen schnell sein" treu geblieben bin, aber wenn ja, werden die Vorteile eines viel größeren Systems sehr schnell offensichtlich .
quelle
Einfache Erklärung mit Analogien
Die obigen Beispiele machen sich sehr gut und ich brauche sie nicht zu wiederholen. Ich werde mich daher darauf konzentrieren, Beispiele zu verwenden, um Ihnen das Verständnis zu erleichtern.
Integrationstests
Integrationstests prüfen, ob alles zusammenarbeitet. Stellen Sie sich eine Reihe von Zahnrädern vor, die in einer Uhr zusammenarbeiten. Ein Integrationstest wäre: Zeigt die Uhr die richtige Zeit an? Zeigt es in 3 Tagen immer noch die richtige Zeit an?
Es sagt Ihnen nur, ob das gesamte Stück funktioniert. Wenn es fehlschlägt: Es sagt Ihnen nicht genau, wo es fehlschlägt.
Unit Tests
Dies sind wirklich spezifische Testarten. Sie sagen Ihnen, ob eine bestimmte Sache funktioniert oder fehlschlägt. Der Schlüssel zu dieser Art von Test ist, dass nur eine bestimmte Sache getestet wird, während davon ausgegangen wird, dass alles andere einwandfrei funktioniert. Das ist der entscheidende Punkt.
Beispiel: Lassen Sie uns diesen Punkt anhand eines Beispiels näher erläutern:
Stubs verwenden
Angenommen, Ihr Auto-Integrationstest schlägt fehl. Es fährt nicht erfolgreich nach Echuca. Wo ist das Problem?
Nehmen wir nun an, Ihr Motor verwendet ein spezielles Kraftstoffeinspritzsystem und dieser Motoreinheitentest ist ebenfalls fehlgeschlagen. Mit anderen Worten, sowohl der Integrationstest als auch der Motoreinheitentest sind fehlgeschlagen. Wo ist dann das Problem? (Geben Sie sich 10 Sekunden Zeit, um die Antwort zu erhalten.)
Liegt das Problem am Motor oder am Kraftstoffeinspritzsystem?
Sie sehen das Problem hier? Sie wissen nicht genau, was fehlschlägt. Wenn Sie unterschiedliche externe Abhängigkeiten verwenden, könnte jede einzelne dieser 10 das Problem verursacht haben - und Sie wissen nicht, wo Sie anfangen sollen. Aus diesem Grund verwenden Unit-Tests Stubs, um anzunehmen, dass alles andere einwandfrei funktioniert.
quelle
Ein bisschen akademisch diese Frage, nicht wahr? ;-) Mein Standpunkt: Für mich ist ein Integrationstest der Test des gesamten Teils, nicht wenn zwei von zehn Teilen zusammenpassen. Unser Integrationstest zeigt, ob der Master-Build (mit 40 Projekten) erfolgreich sein wird. Für die Projekte haben wir Tonnen von Unit-Tests. Das Wichtigste bei Unit-Tests ist für mich, dass ein Unit-Test nicht von einem anderen Unit-Test abhängig sein darf. Für mich sind beide oben beschriebenen Tests Unit-Tests, wenn sie unabhängig sind. Für Integrationstests muss dies nicht wichtig sein.
quelle
Ich denke ja und ja. Ihr Unit-Test, der 2 Klassen umfasst, wurde zu einem Integrationstest.
Sie können dies vermeiden, indem Sie die Satzklasse mit einer Scheinimplementierung testen - die MockWord-Klasse. Dies ist wichtig, wenn diese Systemteile groß genug sind, um von verschiedenen Entwicklern implementiert zu werden. In diesem Fall wird Word allein als Einheit getestet, der Satz wird mit Hilfe von MockWord als Einheit getestet, und dann wird der Satz mit Word in die Integration getestet.
Ein Beispiel für einen echten Unterschied kann sein: 1) Ein Array von 1.000.000 Elementen kann leicht in Einheiten getestet werden und funktioniert einwandfrei. 2) BubbleSort lässt sich leicht auf einem Mock-Array mit 10 Elementen testen und funktioniert auch einwandfrei. 3) Integrationstests zeigen, dass etwas nicht so gut ist.
Wenn diese Teile von einer einzelnen Person entwickelt werden, tritt beim Unit-Test von BubbleSoft höchstwahrscheinlich ein Problem auf, nur weil der Entwickler bereits über ein echtes Array verfügt und keine Scheinimplementierung benötigt.
quelle
Darüber hinaus ist zu beachten, dass sowohl Komponententests als auch Integrationstests beispielsweise mit JUnit automatisiert und geschrieben werden können. In JUnit-Integrationstests kann die
org.junit.Assume
Klasse verwendet werden, um die Verfügbarkeit von Umgebungselementen (z. B. Datenbankverbindung) oder anderen Bedingungen zu testen.quelle
Wenn Sie ein TDD-Purist sind, schreiben Sie die Tests, bevor Sie Produktionscode schreiben. Natürlich werden die Tests nicht kompiliert, also lassen Sie zuerst die Tests kompilieren und dann die Tests bestehen.
Sie können dies mit Komponententests tun, aber nicht mit Integrations- oder Abnahmetests. Wenn Sie es mit einem Integrationstest versuchen würden, würde nichts kompiliert werden, bis Sie fertig sind!
quelle