Wann sollte ich Integrationstests schreiben?

30

Nach den TDD-Regeln werden Komponententests vor dem Produktionscode geschrieben. Wie steht es jedoch mit Integrationstests, die die Interaktion zwischen konkreten (nicht nachgebildeten) verdrahteten Objekten ausüben?

Sollten sie vor dem Komponententest oder nach dem Seriencode geschrieben werden, um nur die "Verkabelung" zu testen?

Beachten Sie, dass es sich nicht um Akzeptanz- oder Funktionstests handelt, sondern um Integrationstests auf niedrigerer Ebene.

Chedy2149
quelle

Antworten:

49

Das Rspec-Buch schlägt neben anderen BDD-Ressourcen einen Zyklus wie diesen vor:

Bildbeschreibung hier eingeben

Im Wesentlichen ist der Prozess:

While behaviour required
    Write an integration test for a specific behaviour
    While integration test failing
        Write a unit test to fulfil partial behavior
        While unit test failing
            Write code to make unit test pass
        Commit
        While refactoring can be done
            Refactor
            While unit test failing
                Write code to make unit test pass
            Commit
    Push

Haftungsausschluss: Ich habe keinen Zweifel daran, dass dies zum besten Code und Produkt führt, aber es kann zeitaufwändig sein. Es gibt alle Arten von Schwierigkeiten mit Daten und Determinismus, wenn es darum geht zu sagen, dass Integrationstests immer bestanden werden sollten. Es ist nicht unter allen Umständen angemessen. Manchmal muss man nur Sachen aus der Tür holen.

Das heißt, einen idealen Prozess im Auge zu haben, ist großartig. Es gibt Ihnen einen Punkt, von dem aus Sie Kompromisse eingehen können.

pdr
quelle
2
Danke @pdr, aber ich habe angegeben, dass ich nicht über Akzeptanztests gesprochen habe, die vor / zu Beginn einer Iteration geschrieben wurden. Ich interessiere mich für Integrationstests auf niedrigerer Ebene.
Chedy2149
@ chedy2149: Akkh. Verpasste diesen Kommentar. Bevor ich meine Antwort entferne, sollten Sie im Zusammenhang mit Integrationstests genauer definieren, was Sie unter "niedriger" verstehen.
pdr
Untere Ebene: Welches Verhalten von Benutzern oder Clients nicht angegeben wird und welches zum Testen von Klassen- / Komponenteninteraktionen verwendet wird, haben Entwickler erwartet.
Chedy2149
4
Eigentlich macht es keinen Unterschied, ob Sie "Akzeptanztest" oder "Integrationstest" in dieses Bild einfügen - es ist eine idealisierte Ansicht für jede Art von Tests auf verschiedenen Abstraktionsebenen. Aber IMHO ist das eigentliche Problem nicht, dass dies "zeitaufwändig" sein kann - das eigentliche Problem ist, dass das Schreiben von Integrationstests "im Voraus" gegen eine öffentliche Schnittstelle, die noch mit Hilfe von TDD entworfen wird, wie das Schießen auf ein "sich bewegendes Ziel" ist ".
Doc Brown
@DocBrown, ist Ihre Antwort also nach dem Produktionscode und vor der Veröffentlichung?
Chedy2149
10

Ein reales Projekt hat mir gezeigt, dass es nicht möglich ist, Komponententests zu schreiben, und dann ist die Integration und sogar die entgegengesetzte Richtung falsch :-) Also schreibe ich normalerweise Komponententests zusammen mit den Integrationstests.

Warum? Lassen Sie mich schreiben, wie ich beide Arten von Tests sehe:

  1. Komponententests - Neben Wikipedia und allen bekannten Informationen helfen Komponententests dabei, Ihr Design einzugrenzen, Ihr Modell und Ihre Beziehungen zu verbessern. Der Ablauf ist einfach: Sobald Sie mit der Eingabe eines neuen Projekts / einer neuen Komponente beginnen, erstellen Sie die meiste Zeit eine Art PoC . Wenn Sie fertig sind, haben Sie immer lange Methoden, lange Klassen, nicht kohärente Methoden und Klassen usw.

    Unit-Tests helfen Ihnen dabei, diese Probleme zu beseitigen, da Sie echte Unit-Tests mit den oben beschriebenen Mock-Klassen (ohne Abhängigkeit von anderen Komponenten) nicht testen können. Ein grundlegendes Zeichen für nicht testbaren Code ist ein großer verspottender Teil der Tests, da Sie gezwungen sind, viele Abhängigkeiten (oder Situationen) zu verspotten.

  2. Integrationstests - korrekte und funktionierende Tests sagen Ihnen, dass Ihre neue Komponente (oder Komponenten) zusammen oder mit anderen Komponenten arbeiten - dies ist die übliche Definition. Ich habe festgestellt, dass Integrationstests Ihnen hauptsächlich dabei helfen, den Ablauf für die Verwendung Ihrer Komponente auf der Verbraucherseite zu definieren .

    Dies ist sehr wichtig, da Ihnen manchmal gesagt wird, dass Ihre API von außen keinen Sinn ergibt.

Was passiert, wenn ich später Unit-Tests und Integrationstests geschrieben habe?

Ich habe nette Klassen, klares Design, gute Konstruktoren, kurze und kohärente Methoden, IoC-fähig usw. Nachdem ich meine Klasse / API einem Verbraucher gegeben habe, z. B. einem Entwickler aus der Integration oder einem GUI-Team, konnte er meine API nicht verwenden, da dies unlogisch erscheint , seltsam. Er war nur verwirrt. Also habe ich API nach seiner Ansicht repariert, aber es mussten auch viele Tests neu geschrieben werden, da ich dazu gedrängt wurde, die Methoden und manchmal sogar den Ablauf für die Verwendung der API zu ändern.

Was passiert, wenn ich später Integrationstests und Unit-Tests geschrieben habe?

Ich habe exakten Fluss, gute Bedienbarkeit. Was ich auch habe, sind große Klassen, nicht kohärenter Code, keine Protokollierung, lange Methoden. Spaghetti-Code

Was ist mein Rat?

Ich habe folgenden Ablauf gelernt:

  1. Entwickeln Sie das Grundgerüst Ihres Codes
  2. Schreiben Sie Integrationstests, aus denen hervorgeht, ob dies aus Verbrauchersicht sinnvoll ist. Grundlegender Anwendungsfall ist fürs Erste ausreichend. Der Test funktioniert offensichtlich nicht.
  3. Schreiben Sie Code zusammen mit Unit-Tests für jede Klasse.
  4. Schreiben Sie den Rest / das Fehlen von Integrationstests. Es wäre besser, diesen Test innerhalb von # 3 zu implementieren, wie Sie Ihren Code verbessern.

Beachten Sie, dass ich eine kleine Präsentation über Unit- / Integrationstests gemacht habe (siehe Folie 21, in der das Skelett beschrieben wird).

Martin Podval
quelle
5

Unit Tests werden verwendet, um das kleinstmögliche testbare Stück Software in einer Anwendung zu testen und deren Funktionalität zu testen. Jedes Gerät wird separat getestet, bevor es zu Teilen oder größeren Komponenten der Anwendung zusammengefügt wird.

Hier kommen Integrationstests ins Spiel :
Sie testen diese neu erstellten Teile, die aus den zuvor getesteten Einheiten bestehen, während sie diese Teile zusammenfügen. Am besten schreiben Sie die Tests an dieser Stelle, während Sie die Anwendung selbst schreiben.

Ben McDougall
quelle
Ihre Antwort lautet also nach dem Seriencode?
Chedy2149
Dies beantwortet die Frage nicht. Er fragt, ob Produktionscode geschrieben wurde, nachdem Integrationstests geschrieben wurden. Ihre Antwort kann in beide Richtungen erfolgen.
Reactgular
1
@MathewFoscarini - aktualisierte Antwort. Hoffe es wird jetzt klarer.
Ben McDougall
Im Hinblick auf die Unit - Tests, würde ich Ausgabetag mit „kleinsten möglichen Bit - Software“. Testen Sie, was im Vertrag enthalten ist (z. B. die öffentlichen Methoden eines Objekts, die exportierten Funktionen einer Bibliothek), da der Vertrag definiert, was funktionieren muss. Andere Dinge sind überprüfbar, doch dies ist nicht nur Zeitverschwendung, sondern auch kontraproduktiv.
Itsbruce
3

Ich neige dazu, Integrationstests als sehr ähnlich wie Unit-Tests anzusehen. Dabei behandle ich eine Teilmenge des Codes als Black Box. Integrationstests sind also nur eine größere Kiste.

Ich ziehe es vor, sie vor dem Seriencode zu schreiben. Dies hat den Vorteil, dass ich mir merken kann, welche Teile ich noch nicht verkabelt habe oder dass ich ein Detail in der Objektinteraktion geringfügig geändert habe.

Schleis
quelle
Es gibt verschiedene Teststufen: White-Box-Komponententest, White-Box-Integrationskomponententest. Komponenten-Blackbox-Test, Integrations-Blackbox-Test. Es gibt auch Tests des Integrationssystems.
Alexander.Iljushkin
2

Abgesehen von Abnahmetests schreibe ich Integrationstests in der Regel nur an den Grenzen einer Anwendung, um zu überprüfen, ob sie sich gut in Systeme oder Komponenten von Drittanbietern integrieren lassen.

Die Idee ist, Adapterobjekte zu erstellen, die aus der Art und Weise übersetzen, wie der Dritte mit den Anforderungen Ihrer Anwendung spricht, und diese Übersetzer mit dem realen externen System zu testen. Ob du diesen Test zuerst oder den Test zuletzt machst, halte ich für weniger wichtig als bei deinen regulären Unit-Tests, weil

  • Die von TDD bereitgestellten Erkenntnisse zum Design sind hier nicht so wichtig, da das Design im Voraus bekannt ist und in der Regel nichts besonders Komplexes involviert ist. Sie ordnen lediglich Dinge von einem System zu einem anderen zu.

  • Abhängig von dem Modul / System, das Sie in Angriff nehmen möchten, kann es eine Menge Exploration, Konfigurationsbastelarbeiten und Probenvorbereitung erfordern, was Zeit in Anspruch nimmt und nicht wirklich gut in eine kurze TDD-Rückkopplungsschleife passt.

Wenn Sie sich jedoch wirklich wohler fühlen, wenn Sie Ihren Adapter schrittweise in kleinen, sicheren Schritten aufbauen, würde ich auf jeden Fall empfehlen, zuerst zu testen, da dies nicht schaden kann.

Beispiele für diesen Ansatz finden Sie hier: http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html (6. Absatz) http://blog.8thlight.com/eric- smith / 2011/10/27 / thats-not-yours.html

guillaume31
quelle
Hier geht es um Integrationstests, mit denen die Interaktionen zwischen "unserem System" und Bibliotheken von Drittanbietern überprüft werden. Wie wäre es beispielsweise mit dem Testen von Interaktionen auf einer Plattform während der Entwicklung eines Plug-ins?
Chedy2149
Obwohl ich nur wenig Erfahrung mit der Plug-in-Entwicklung habe, kann es sein, dass sie sich unterscheiden, da sie von Natur aus eng mit der Host-Anwendung verbunden sind. Vielleicht möchten Sie diese Integration in vollem Umfang nutzen und entscheiden, dass Sie keine Adapterschicht benötigen. In diesem Fall würde ich allerdings sehr vorsichtig mit der Testleistung sein - abhängig von der Host-Anwendung kann das direkte Aufrufen der API in einer großen Anzahl Ihrer Tests sehr langsam sein. Wenn Sie sich davor fürchten, können Sie jederzeit auf den Ansatz der "zusätzlichen Abstraktionsebene" zurückgreifen und Mocks + Integrationstests für Adapter verwenden.
Guillaume31
1

Also wollte ich die erste Antwort akzeptieren, aber sie wurde gelöscht.
Um es
in einer gegebenen Iteration zusammenzufassen:

  1. Unit-Test schreiben
  2. Schreiben Sie den Seriencode
  3. Schreiben Sie Integrationstests, um Interaktionen zu testen

Berücksichtigen Sie die Integrationstests 1 und 2, um die Testbarkeit auf der Integrationsebene zu gewährleisten.

Integrationstests werden nicht notwendigerweise von Ende zu Ende in Schritt 3 geschrieben. Sie können teilweise zwischen Schritt 1 und 2 geschrieben werden.

Chedy2149
quelle
3
Diese Zusammenfassung ignoriert vollständig die iterative Natur des Prozesses. Sobald die API Ihres Produktionscodes zu einem gewissen Grad stabil ist, können Sie mit dem Schreiben von Integrationstests beginnen. Anschließend können Sie Ihren Produktionscode erneut bearbeiten und möglicherweise Ihre Integrationstests ändern oder erweitern. In den meisten Fällen schreiben Sie also keine Integrationstests nach dem Seriencode. In der Regel führen Sie beides bis zu einem gewissen Grad parallel durch. Und tatsächlich hängt dies auch stark davon ab, welche Art von Software Sie verwenden. "Schwarz-Weiß" -Denken bringt Sie nicht weiter.
Doc Brown
Guter Punkt. Die Antwort scheint den iterativen Charakter von Design durch Refactoring zu ignorieren.
Chedy2149
0

Unit-Tests testen einzelne Codeblöcke in Ihrem Projekt.
Integrationstests testen, wie Ihr Code mit anderem Code kommuniziert. Mit anderen Worten, sie testen die Schnittstelle Ihres Codes.

Schreiben Sie Unit-Tests, wenn Sie Code hinter einer Schnittstelle entwickeln.
Schreiben Sie Integrationstests, wenn Sie die Schnittstelle oder einen Code entwickeln, der die Schnittstelle implementiert.

Dies bedeutet, dass Sie Integrationstests manchmal sehr spät in einem Projekt schreiben, da der Großteil der Arbeit hinter der Benutzeroberfläche liegt: Zum Beispiel ein Compiler, ein bestimmter Webservice, der mehrere Logikebenen implementiert, oder ... etwas, das viel Aufwand mit sich bringt interne Logik.

Wenn Sie jedoch eine Reihe von REST-Services implementieren oder das Datenmodell umgestalten und Unterstützung für XA-Transaktionen hinzufügen, werden Sie fast sofort mit der Entwicklung von Integrationstests beginnen, da sich der größte Teil Ihrer Arbeit auf die Schnittstelle konzentriert, unabhängig davon, ob es sich um eine handelt die REST-API oder wie das Programm das Datenmodell verwendet.

Marco
quelle
Würden Sie zustimmen zu sagen, dass Unit-Tests Whitebox-Tests und Integrationstests Blackbox-Tests sind?
Chedy2149
Das hängt leider davon ab. Technologien für Integrationstests haben sich in den letzten Jahren enorm verbessert (zumindest in der Java-Welt), so dass ich 1 Klasse testen kann - aber auf einem Anwendungsserver. Dann stellt sich die Frage, wo die Grenze zwischen Unit-Tests und Integrationstests liegt. Handelt es sich um einen Integrationstest, wenn Sie Ihren Code testen, der mit anderen Technologien kompatibel ist, oder um einen Integrationstest, wenn Sie Ihre gesamte Anwendung testen - jedoch nicht unbedingt in der Umgebung, in der sie ausgeführt werden soll?
Marco
Kurz gesagt, in einigen Fällen handelt es sich bei Integrationstests um Black-Box-Tests - aber nicht in allen Fällen.
Marco
Zur Info : Wiki definiert Integraionstests als "die Phase des Softwaretests, in der einzelne Softwaremodule kombiniert und als Gruppe getestet werden"
Marco
Genau, Marco. Auf jeder Komponentenebene gibt es Integrationen. Code-Ebene, Anwendungsebene, Systemebene.
Alexander.Iljushkin