Was ist der Unterschied zwischen Integrations- und Unit-Tests?

307

Ich kenne die sogenannte Lehrbuchdefinition von Unit-Tests und Integrationstests. Ich bin gespannt, wann es Zeit ist, Komponententests zu schreiben ... Ich werde sie schreiben, um so viele Klassen wie möglich abzudecken.

Wenn ich beispielsweise eine WordKlasse habe, schreibe ich einige Komponententests für die WordKlasse. Dann beginne ich mit dem Schreiben meiner SentenceKlasse, und wenn sie mit der WordKlasse interagieren muss, schreibe ich meine Komponententests oft so, dass sie beide testen Sentenceund Word... zumindest an den Stellen, an denen sie interagieren.

Sind diese Tests im Wesentlichen zu Integrationstests geworden, weil sie jetzt die Integration dieser beiden Klassen testen, oder handelt es sich nur um einen Komponententest, der zwei Klassen umfasst?

Im Allgemeinen schreibe ich aufgrund dieser unsicheren Linie selten tatsächlich Integrationstests ... oder verwende das fertige Produkt, um zu überprüfen, ob alle Teile ordnungsgemäß funktionieren, obwohl sie manuell durchgeführt und selten über den Rahmen hinaus wiederholt werden von jedem einzelnen Merkmal?

Verstehe ich Integrationstests falsch oder gibt es wirklich nur einen sehr geringen Unterschied zwischen Integrations- und Komponententests?

Mike Stone
quelle

Antworten:

300

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;
}

DoSomethingist 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, DoSomethingsollten 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 Logdefekt 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, Logwird 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 System mit einer kaputten Klasse

Ein einzelner Fehler führt zu mehreren Funktionsstörungen und mehrere Integrationstests schlagen fehl.

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.

Der gleiche Fehler wird 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, Logsind rot
  • Alle Ihre Unit-Tests sind grün, nur der Unit-Test für Logist 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 .

Arialdo Martini
quelle
6
Eine wirklich gute Antwort! Ich möchte jedoch nur hinzufügen, dass Spott nicht nur für Unit-Tests gedacht ist. Es könnte auch in vielen Integrationstestfällen sehr nützlich sein.
n.Stenvang
1
Gute Antwort! Ich stimme zwei Punkten einfach nicht ganz zu: 1) Integrationstests sind "nutzlos, um zu erraten, wo das Problem liegen könnte"; und 2) dass "ein Komponententest niemals 2 Klassen umfassen sollte". Ich habe viele Integrationstests erstellt, und wenn sie nicht funktionieren, ist es normalerweise nicht schwer, die Ursache des Problems zu bestimmen, vorausgesetzt, Sie erhalten eine vollständige Stapelverfolgung oder eine einzelne fehlgeschlagene Behauptung (in diesem Fall kann es schwieriger sein, die Quelle zu finden, aber nicht so sehr, da der Integrationstest einen enthaltenen Kontext zum Debuggen bietet. (Fortsetzung)
Rogério
5
Unit-Tests können mehrere Klassen ausüben, sofern es sich nicht um öffentliche Klassen handelt, für die separate Unit-Tests durchgeführt werden sollten. Ein Fall ist, wenn eine öffentlich getestete Klasse andere nicht öffentliche Hilfsklassen verwendet, die nur zur Unterstützung der öffentlichen Klasse existieren. In diesem Fall umfasst die "Einheit" zwei oder mehr Klassen. Ein anderer Fall ist, dass die meisten Klassen Klassen von Drittanbietern verwenden (String / String-Klasse, Auflistungsklassen usw.), die keinen Sinn machen, verspottet oder isoliert zu werden. Wir betrachten sie einfach als stabile und zuverlässige Abhängigkeiten, die außerhalb des Testbereichs liegen.
Rogério
2
Bei Integrationstests ist es etwas schwieriger, das Root-Problem zu finden, aber Sie können es trotzdem debuggen und das Root-Problem finden. Angenommen, Komponententests schlagen nicht oft fehl, dann dauert es möglicherweise selten etwas länger, Fehler zu beheben, wenn Sie nur Integrationstests haben. Dann erhalten Sie jedoch den Mehrwert des Testens der Komponentenintegration und sparen Zeit beim Schreiben die Einheit testet. Ich denke, diese Behauptung (die von meinem Chef kam) ist falsch, aber ich bin nicht sicher, wie ich ihn überzeugen kann, irgendwelche Ideen?
BornToCode
1
Durch die Argumentation in dieser Antwort könnte man argumentieren, dass es möglicherweise zeitsparender ist, das Schreiben von Komponententests zu überspringen und die eingesparte Zeit damit zu verbringen, die Quelle für fehlgeschlagene Integrationstests zu finden, wenn diese fehlschlagen.
62

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.

Larry Foulkrod
quelle
43

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 ^ _ ^

Rob Cooper
quelle
23

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. SentenceWenn in Ihrem Fall der Klasse WordKlasse verwendet wird, sollte Ihre WordKlasse verspottet werden. Auf diese Weise testen Sie nur Ihre SentenceKlassenfunktionalität.

Robert Koritnik
quelle
Ich weiß, dass dies ein alter Beitrag ist, aber ich bin gerade darauf gestoßen. Was wäre, wenn Sie eine dritte Klasse namens Font hätten, mit der die Satzklasse interagiert, und Sie die Funktionalität zwischen Word- und Satzklasse testen möchten, dann müssten Sie die Font-Klasse verspotten, aber dies macht sie nicht zu einem Komponententest. Ich sage also, dass die Verwendung von Mocks nicht unbedingt zu einem Komponententest wird. Mocks können auch in Integrationstests verwendet werden.
n.Stenvang
2
Natürlich Mocks können in Integrationstests verwendet werden, sondern um eine Einheit Test tatsächlich sein als solche alles extern an das Gerät sollte simuliert . Wenn Integrationstests Mocks verwenden, handelt es sich wahrscheinlich um Teilintegrationstests (sofern ein solcher Begriff vorhanden ist). Es gibt natürlich Teilintegrationstests, die von oben nach unten oder von unten nach oben sind. Letztere erfordern normalerweise keine Verspottungen, während frühere dies tun.
Robert Koritnik
17

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.

Jon Limjap
quelle
8
"Technisch gesehen können Sie sowieso nicht nur eine Klasse testen. Was ist, wenn Ihre Klasse aus mehreren anderen Klassen besteht?" Nun, ein "strenger" Unit-Test würde einfach alle Abhängigkeiten verspotten / stubben. Es ist jedoch fraglich, ob dies immer praktisch ist ...
Sleske
2
Das ist wahr, Sieske - das Wichtigste ist, Abhängigkeiten auf ein absolutes Minimum zu beschränken.
Jon Limjap
-1, ein Komponententest testet nicht eine einzelne Funktion, sondern eine einzelne Softwarefunktion oder -klasse, dh er testet eine logische Softwareeinheit.
CharlesB
12

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.

Entwicklung von Chris
quelle
10

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:

  • Risikominderung : Dafür sind Tests gedacht. Nur eine Kombination aus Unit-Tests und Integrationstests kann zu einer vollständigen Risikominderung führen, da Unit-Tests einerseits die ordnungsgemäße Interaktion zwischen Modulen nicht testen können und Integrationstests andererseits nur die Funktionalität eines nicht trivialen Moduls ausüben können zu einem kleinen Grad.
  • Testschreibaufwand : Integrationstests können Aufwand sparen, da Sie dann möglicherweise keine Stubs / Fakes / Mocks schreiben müssen. Unit-Tests können jedoch auch Aufwand sparen, wenn die Implementierung (und Wartung!) Dieser Stubs / Fakes / Mocks einfacher ist als die Konfiguration des Testaufbaus ohne sie.
  • Verzögerung bei der Testausführung : Integrationstests mit schwergewichtigen Vorgängen (z. B. Zugriff auf externe Systeme wie DBs oder Remote-Server) sind in der Regel langsam (er). Dies bedeutet, dass Unit-Tests viel häufiger ausgeführt werden können, was den Debugging-Aufwand verringert, wenn etwas fehlschlägt, da Sie eine bessere Vorstellung davon haben, was Sie in der Zwischenzeit geändert haben. Dies ist besonders wichtig, wenn Sie testgetriebene Entwicklung (TDD) verwenden.
  • Debug - Aufwand : Wenn ein Integrationstest nicht besteht , aber keine der Unit - Tests ist, kann dies sehr unangenehm sein, weil es so viel Code ist , dass beteiligt kann das Problem enthalten. Dies ist kein großes Problem, wenn Sie zuvor nur einige Zeilen geändert haben - aber da Integrationstests langsam ausgeführt werden, haben Sie sie möglicherweise nicht in so kurzen Intervallen ausgeführt ...

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.

Lutz Prechelt
quelle
10

Im Unit-Test testen Sie jedes Teil isoliert: Geben Sie hier die Bildbeschreibung ein

Im Integrationstest testen Sie viele Module Ihres Systems:

Geben Sie hier die Bildbeschreibung ein

und das passiert, wenn Sie nur Unit-Tests verwenden (im Allgemeinen funktionieren beide Fenster, leider nicht zusammen):

Geben Sie hier die Bildbeschreibung ein

Quellen: Quelle1 Quelle2

Michu93
quelle
Sie haben drei Bilder, aber nur zwei Quellen.
Gerrit
1
@gerrit werfen Sie einen Blick in die erste Quelle - zwei Bilder sind von dort
Michu93
1
Ich liebe diese Antwort 👏
Dzenis H.
8

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.

David Sackstein
quelle
5
-1 Definition ist das, was es Menschen ermöglicht, dieselben Begriffe zu verwenden, ohne immer zu erklären, was sie bedeuten, und ist für die Zusammenarbeit von wesentlicher Bedeutung. Daher ist es wichtig, den Unterschied zwischen beiden Begriffen zu verstehen.
CharlesB
Wie @CharlesB bereits erwähnt hat, ist es wichtig, nicht jedes Mal zu erklären oder festzustellen, dass jeder eine andere Definition hat, was zu Verwirrung führt. Tests werden anders geschrieben und anders ausgeführt, dies bedeutet jedoch nicht, dass beide nicht durchgeführt werden sollten, indem die Unterschiede definiert werden sollen.
Shane
Die Schlussfolgerung der Antwort mag extrem sein, aber die meisten Punkte sind durchaus gültig: Unit-Tests und Integrationstests sind bis auf ihre Granularität meistens dasselbe - und es ist nicht klar, wo eine Linie zwischen ihnen gezogen werden sollte.
Lutz Prechelt
Dies hilft nicht, wenn Sie eine gemeinsame Sprache in einem professionellen Umfeld erstellen. Obwohl Sie meistens Recht haben, spielt es keine Rolle, dass eine gemeinsame Sprache zu Missverständnissen und Verwirrung im Team führt. Ich denke, die beste Option ist, das Team über ihre Begriffe und Definitionen zu einigen.
user924272
4

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.

Lance Fisher
quelle
4

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).

Michael Neale
quelle
4

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.

grom
quelle
4

Integrationstests: Die Datenbankpersistenz wird getestet.
Unit-Tests: Der Datenbankzugriff wird verspottet. Codemethoden werden getestet.

Pascal
quelle
3

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.

Christian Hagelid
quelle
2

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 .

CVertex
quelle
2

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:

  • Nehmen wir als Beispiel ein Auto.
  • Integrationstest für ein Auto: zB fährt das Auto nach Woop Woop und zurück? Wenn dies der Fall ist, können Sie mit Sicherheit sagen, dass ein Auto von einem Gesamtstandpunkt aus funktioniert. Es ist ein Integrationstest. Wenn es ausfällt, haben Sie keine Ahnung, wo es tatsächlich ausfällt: Ist es der Kühler, das Getriebe, der Motor oder der Vergaser? Sie haben keine Ahnung. Es könnte alles sein.
  • Unit Test für ein Auto: Funktioniert der Motor? Bei diesem Test wird davon ausgegangen, dass alles andere im Auto einwandfrei funktioniert. Auf diese Weise können Sie sehr sicher sein, dass das Problem im Motor liegt, wenn dieser spezielle Komponententest fehlschlägt. So können Sie das Problem schnell isolieren und beheben.

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.

BKSpurgeon
quelle
1

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.

John Smithers
quelle
1

Sind diese Tests im Wesentlichen zu Integrationstests geworden, weil sie jetzt die Integration dieser beiden Klassen testen? Oder ist es nur ein Unit-Test, der 2 Klassen umfasst?

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.

Pavel Feldman
quelle
1

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.AssumeKlasse verwendet werden, um die Verfügbarkeit von Umgebungselementen (z. B. Datenbankverbindung) oder anderen Bedingungen zu testen.

Paulo Merson
quelle
0

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!

StevePoling
quelle