Benötige ich einen Komponententest, wenn ich bereits einen Integrationstest habe?

47

Wenn ich bereits einen Integrationstest für mein Programm habe und alle bestanden haben, habe ich das gute Gefühl, dass es funktionieren wird. Was sind dann die Gründe, Unit-Tests zu schreiben / hinzuzufügen? Da ich ohnehin schon Integrationstests schreiben muss, schreibe ich nur Unit-Tests für Teile, die nicht durch Integrationstests abgedeckt sind.

Was ich weiß, sind die Vorteile des Unit-Tests gegenüber dem Integrationstest

  • Klein und daher schnell zu laufen (aber das Hinzufügen eines neuen Geräts zum Testen von etwas wird bereits durch den Integrationstest getestet, was bedeutet, dass mein gesamter Testanzug größer und länger läuft)
  • Das Auffinden von Fehlern ist einfacher, da nur eine Sache getestet wird (aber ich kann mit dem Schreiben eines Komponententests beginnen, um jedes einzelne Teil zu überprüfen, wenn mein Integrationstest fehlgeschlagen ist).
  • Finden Sie Fehler, die möglicherweise nicht im Integrationstest gefunden wurden. zB Fehler maskieren / ausgleichen. (Aber wenn meine Integrationstests alle bestanden haben, was bedeutet, dass mein Programm funktioniert, gibt es sogar einen versteckten Fehler. Diese Fehler zu finden / zu beheben hat keine hohe Priorität, es sei denn, sie brechen zukünftige Integrationstests oder verursachen Leistungsprobleme.)

Und wir wollen immer weniger Code schreiben, aber beim Schreiben von Unit-Tests wird viel mehr Code benötigt (hauptsächlich Setup-Mock-Objekte). Der Unterschied zwischen einigen meiner Komponententests und Integrationstests besteht darin, dass ich bei Komponententests Scheinobjekte und bei Integrationstests echte Objekte verwende. Welche haben viele Duplikate und ich mag keinen duplizierten Code, auch in Tests, weil dies Overhead hinzufügen, um das Verhalten des Codes zu ändern (Refactor-Tool kann nicht alle Arbeit die ganze Zeit).

Bryan Chen
quelle
Wie umfangreich sind Ihre Integrationstests aus Neugier? Wenn Sie eine komplexe Logik haben, decken Ihre Integrationstests sie alle oder nur einen Teil davon ab und welche Teile sind für das Geschäft wichtig oder zufällig?
civan
Diese Frage scheint mehrdeutig. Angenommen, ich habe eine Rails-Controller-Methode, die einen Interaktor aufruft ( github.com/collectiveidea/interactor ). Ich habe mich entschlossen, Integrationstests für meine Controller-Methode zu schreiben (da ich ohne diese Tests nicht vertrauen kann, dass mein API-Endpunkt funktioniert). Hier gibt es mindestens zwei Fragen: (1) Soll ich auch Unit-Tests für meine Controller-Methoden schreiben (dh soll ich Unit-Tests schreiben, die das gleiche Verhalten wie meine Integrationstests testen), und (2) soll ich auch Unit-Tests schreiben für meinen Interakteur? Ich würde diese beiden Fragen in bestimmten Geschäftskontexten unterschiedlich beantworten.
Daniel

Antworten:

33

Sie haben gute Argumente für und gegen Unit-Tests vorgebracht. So dass Sie sich fragen, Muss ich Wert in den positiven Argumente sehen, die die Kosten in die negativen überwiegen? Ich sicher tun:

  • Klein und schnell ist ein netter Aspekt beim Testen von Einheiten, wenn auch keineswegs der wichtigste.
  • Das Lokalisieren von Fehlern ist extrem wertvoll. Viele Studien zur professionellen Softwareentwicklung haben gezeigt, dass die Kosten eines Fehlers mit zunehmendem Alter stark ansteigen und sich in der Software-Bereitstellungs-Pipeline niederschlagen.
  • Das Auffinden von maskierten Fehlern ist wertvoll. Wenn Sie wissen, dass für eine bestimmte Komponente alle Verhaltensweisen überprüft wurden, können Sie sie auf eine Weise verwenden, die zuvor nicht verwendet wurde. Wenn die einzige Überprüfung über Integrationstests erfolgt, wissen Sie nur, dass sich die aktuellen Verwendungen korrekt verhalten.
  • In der Praxis ist das Verspotten kostspielig, und das Aufrechterhalten von Verspottungen ist doppelt so hoch. Wenn Sie "interessante" Objekte oder Schnittstellen verspotten, müssen Sie möglicherweise sogar Tests durchführen, um sicherzustellen, dass Ihre verspiegelten Objekte Ihre realen Objekte korrekt modellieren!

In meinem Buch überwiegen die Vor- und Nachteile.

Ross Patterson
quelle
2
Ist es nicht billiger, in realen Fällen zu spotten ? Sie stellen nur die Erwartungen an die Nachrichten ein, die der Mock erhält, und legen fest, was er zurückgibt.
Dogweather
10
@ Dogweather Mocks funktionieren gut, wenn sie zum ersten Mal erstellt werden. Wenn die Zeit vergeht und das reale Objekt geändert wird, müssen sich die Mocks damit ändern. Nach 10 Jahren und 6000 Testeinheiten ist es sehr schwierig zu wissen, dass Ihre "erfolgreichen" Tests wirklich erfolgreich sind.
Ross Patterson
1
Abgesehen davon sind "10 Jahre und 6.000 Komponententests" Zahlen aus persönlicher Erfahrung, keine Übertreibung.
Ross Patterson
3
Ich habe bereits 2004 oder 2005 damit begonnen, automatisierte Entwicklertests (Unit und Integration, aber hauptsächlich letztere) zu schreiben, und eine erweiterte Verspottungsbibliothek für Java entwickelt. Viele Male habe ich mehrere Tests Integration aus dem gleichen Grunde zu brechen (wie eine Änderung des DB oder ein Netzwerk ändern), und ich „niedrigere Ebene“ Integrationstests für wiederverwendbare Komponenten manchmal schreiben, aber immer noch, ich viel lieber auf nur haben Integrationstests. Einzeltests mit Spott sind es meistens nicht wert. Ich wende das Verspotten nur als Hilfsmittel für die Integrationstests an.
Rogério
Ihr letzter Punkt scheint dem Argument zu widersprechen, das Sie vorbringen. In diesem Aufzählungspunkt sprechen Sie sich gegen das Schreiben unnötiger Verspottungen aus, was ein Argument gegen das Schreiben von Komponententests für Teile ist, die bereits durch Integrationstests abgedeckt sind. Ihr Argument spricht sich jedoch dafür aus, Komponententests für Teile zu schreiben, die bereits durch Integrationstests abgedeckt sind. Könnten Sie bitte Ihre Absicht hier @RossPatterson erklären?
Daniel
8

Ich halte es nicht für wichtig, einen vorhandenen Integrationstestfall als unwichtig neu zu implementieren.

Integrationstests sind für ältere Nicht-Tdd-Anwendungen oft viel einfacher zu schreiben, da die zu testenden Funktionen normalerweise eng miteinander verbunden sind, so dass das isolierte Testen von Einheiten (= nicht testen) schwierig / teuer / unmöglich sein kann.

> Then what are the reasons to write/add unit tests?

Meiner Meinung nach ist eine testgetriebene Entwicklung am effektivsten, wenn Sie die Komponententests vor dem eigentlichen Code schreiben . Auf diese Weise wird der Code, der die Tests erfüllt, mit einem Minimum an externen Referenzen, die leicht zu testen sind, klar getrennt.

Wenn der Code bereits ohne die Komponententests vorhanden ist, ist das anschließende Schreiben der Komponententests in der Regel sehr aufwändig, da der Code nicht für einfache Tests geschrieben wurde.

Wenn Sie TDD ausführen, ist der Code automatisch einfach zu testen.

k3b
quelle
2
Wenn ich eine Legacy-Anwendung mit Nein habe unit-testsund unit-testsbestimmte Teile einbeziehen möchte , ist es Ihrer Meinung nach besser, zuerst integration testsden Code für die Legacy- Anwendung zu schreiben . Sobald das geschrieben ist, können Sie die enge Kopplung lösen und Funktionen mit Schnittstellen erstellen, die getestet werden können? Da Sie das integration-testbereits geschrieben haben, können Sie dann bei jedem Umgestaltungsschritt überprüfen, ob die neue Version des Codes noch wie gewünscht funktioniert?
Alpha_989
2
@ alpha_989, das ist meiner Meinung nach sehr viel und ich bin offen für andere Ideen, aber ich würde Integrationstests Unit-Tests für Legacy-Code vorziehen. In beiden Fällen müssten Sie sicher sein, dass die Methoden ordnungsgemäß funktionieren, bevor Sie Tests hinzufügen. Durch Integrationstests wird jedoch sichergestellt, dass die allgemeinen Erwartungen der Methoden im Gegensatz zu einzelnen Codeelementen funktionieren.
Britt Wescott
5

Integrationstests sollten nur sicherstellen, dass mehrere Komponenten wie erwartet zusammenarbeiten. Ob die Logik der einzelnen Komponenten korrekt ist oder nicht, sollte durch Unit-Tests überprüft werden.
Die meisten Methoden haben mehrere mögliche Ausführungspfade. Denken Sie an Wenn-Dann-Sonst-Werte, Eingabevariablen mit unerwarteten oder einfach falschen Werten usw. Normalerweise denken Entwickler nur an den glücklichen Pfad: den normalen Pfad, der nicht schief geht. In Bezug auf diese anderen Pfade haben Sie zwei Möglichkeiten: Sie können Ihren Endbenutzer diese Pfade anhand der Aktionen untersuchen lassen, die er in der Benutzeroberfläche ausführt, und hoffen, dass sie Ihre Anwendung nicht zum Absturz bringen, oder Sie können Komponententests schreiben, die dies bestätigen das Verhalten dieser anderen Pfade und ergreifen Maßnahmen, wo erforderlich.

Stefan Billiet
quelle
4

Einige der Gründe, auf die Sie in Ihrer Frage hingewiesen haben, sind wirklich wichtig und könnten für sich genommen durchaus für Unit-Tests sprechen, aber für YMMV. Wie oft führen Sie beispielsweise Ihre integrierte Testsuite aus? Ich habe die Erfahrung gemacht, dass integrierte Tests früher oder später so langsam werden, dass Sie sie nicht jedes Mal ausführen, wenn Sie eine Änderung vornehmen, und die Zeit zwischen dem Einfügen und Erkennen eines Fehlers sich verlängert.

Ein großer Fehler, den Sie möglicherweise machen, besteht darin, dem zu vertrauen

Find bug that may not be caught in integration test. e.g. masking/offsetting bugs.

ist nicht wichtig. Erwarten Sie, dass Ihre Benutzer die Fehler für Sie finden? Ich bin der Meinung, dass es gefährlich ist, wenn man sich auf Abdeckungen aus integrierten Tests verlässt. Man kann sehr leicht einen hohen Abdeckungsgrad erzielen, aber in Wirklichkeit testet man nur sehr wenig.

Ich denke der kanonische Verweis gegen integrierte Tests sind die Beiträge von JBrains:

http://www.jbrains.ca/permalink/integrated-tests-are-a-scam-part-1

falls du sie noch nicht gelesen hast

Schließlich ist IMO das Feedback, das Sie von den Komponententests für Ihr Design erhalten können, von unschätzbarem Wert. Ein Design nach Bauchgefühl zu beurteilen und sich auf integrierte Tests zu verlassen, kann ebenfalls ein Fehler sein.

José Ricardo
quelle
Ich verstehe diesen Artikel nicht wirklich. Es gibt also viele Codepfade und Integrationstests können nicht alle abdecken ... also? Dasselbe gilt für Komponententests, es sei denn, Ihre Einheiten sind so unbedeutend, dass sie sinnlos sind.
Casey,
Das ist eher ein Argument gegen die Einschränkung der Codeabdeckung als das, dass Sie eine Menge Unit-Tests schreiben und Integrationstests vermeiden sollten.
Casey
1

Wenn Sie davon ausgehen, dass Sie Ihren Code jemals modifizieren oder umgestalten müssen, sind Unit-Tests unerlässlich. Unit-Tests zeigen nicht nur Fehler zum Zeitpunkt des Codeschreibens, sondern auch, wann neue Fehler auftreten, wenn mehr Code geschrieben wird.

Ja, es ist viel besser, zuerst Ihre Integrations- und Unit-Tests zu schreiben, aber es ist sehr wertvoll, sie zu haben, auch wenn sie später geschrieben werden.

Matthew Flynn
quelle
3
Ich glaube nicht, dass Sie den Fall gemacht haben. Integrationstests würden auch Fehler im Code aufdecken und sind in der Lage, Fehler zu erkennen, die Unit-Tests nicht erkennen.
Casey