TDD- und Unit-Tests scheinen im Moment der große Rave zu sein. Aber ist es wirklich so nützlich im Vergleich zu anderen Formen des automatisierten Testens?
Intuitiv würde ich vermuten, dass automatisierte Integrationstests viel nützlicher sind als Komponententests. Nach meiner Erfahrung liegen die meisten Fehler in der Interaktion zwischen Modulen und nicht so sehr in der tatsächlichen (normalerweise eingeschränkten) Logik der einzelnen Einheiten. Auch Regressionen traten häufig auf, weil sich die Schnittstellen zwischen Modulen (und die Vor- und Nachbedingungen) änderten.
Verstehe ich etwas falsch oder warum werden Unit-Tests im Vergleich zu Integrationstests so stark in den Fokus gerückt? Es ist einfach so, weil davon ausgegangen wird, dass Sie Integrationstests durchführen und Unit-Tests das nächste sind, was wir lernen müssen, um uns als Entwickler zu bewerben.
Oder liefert Unit Testing einfach den höchsten Gewinn im Vergleich zur Komplexität der Automatisierung?
Welche Erfahrungen haben Sie mit automatisierten Komponententests, automatisierten Integrationstests und automatisierten Abnahmetests gemacht und welche haben nach Ihrer Erfahrung den höchsten ROI erzielt? und warum?
Wenn Sie nur eine Testform auswählen müssten, um bei Ihrem nächsten Projekt automatisiert zu werden, welche wäre das?
Danke im Voraus.
quelle
Antworten:
Ein wichtiger Faktor, der Unit-Tests äußerst nützlich macht, ist die schnelle Rückmeldung .
Überlegen Sie, was passiert, wenn Ihre App vollständig mit Integrations- / System- / Funktionstests abgedeckt ist (dies ist bereits eine ideale Situation, die in den meisten Entwicklungsgeschäften weit von der Realität entfernt ist). Diese werden oft von einem engagierten Testteam durchgeführt.
Dies kann Tage oder sogar Wochen dauern. Zu diesem Zeitpunkt haben Sie bereits an anderen Aufgaben gearbeitet, sodass Sie nicht die winzigen Details des zuvor geschriebenen Codes im Kopf haben. Darüber hinaus haben Sie in der Regel nicht einmal einen direkten Beweis dafür, wo sich der Fehler tatsächlich befindet. Daher dauert es sehr lange, den Fehler zu finden und zu beheben.
Während in Unit-Tests (TDD)
Dies alles geschieht in wenigen Minuten .
Dies soll nicht heißen, dass Integrations- / Systemtests nicht nützlich sind. Sie dienen nur unterschiedlichen Zwecken. Mit gut geschriebenen Unit-Tests können Sie einen großen Teil der Fehler im Code abfangen, bevor sie in die Integrationsphase gelangen, in der es bereits erheblich teurer ist, sie zu finden und zu beheben. Sie haben Recht, dass die Integrationstests erforderlich sind, um die Arten von Fehlern zu erkennen, die mit Komponententests nur schwer oder gar nicht zu erkennen sind. Nach meiner Erfahrung sind dies jedoch die selteneren; Die meisten der Fehler, die ich gesehen habe, sind auf ein einfaches oder sogar triviales Auslassen innerhalb einer Methode zurückzuführen.
Ganz zu schweigen davon, dass durch Unit-Tests auch Ihre Schnittstellen auf Benutzerfreundlichkeit / Sicherheit usw. getestet werden. Auf diese Weise erhalten Sie ein äußerst wichtiges Feedback zur Verbesserung Ihres Designs und Ihrer APIs. Welche IMHO kann die Wahrscheinlichkeit von Modul- / Susbsystem-Integrationsfehlern erheblich verringern: Je einfacher und sauberer eine API ist, desto geringer ist die Wahrscheinlichkeit von Missverständnissen oder Auslassungen.
Der ROI hängt von vielen Faktoren ab. Wahrscheinlich hängt der wichtigste davon ab, ob es sich bei Ihrem Projekt um ein neues oder ein älteres Projekt handelt. Bei der Entwicklung auf der grünen Wiese ist mein Rat (und meine bisherige Erfahrung), von Anfang an einen TDD-Test durchzuführen. Ich bin zuversichtlich, dass dies in diesem Fall die kostengünstigste Methode ist.
In einem Legacy-Projekt ist der Aufbau einer ausreichenden Abdeckung durch Komponententests jedoch ein großes Unterfangen, das sich nur sehr langsam auszahlt. Es ist effizienter, zu versuchen, die wichtigsten Funktionen mit System- / Funktionstests über die Benutzeroberfläche abzudecken, wenn dies möglich ist. (Es kann schwierig sein, Desktop-GUI-Apps automatisch über die GUI zu testen, obwohl sich die Tools zur Unterstützung automatisierter Tests allmählich verbessern ...). Dadurch erhalten Sie schnell ein grobes, aber wirksames Sicherheitsnetz. Anschließend können Sie nach und nach Komponententests für die wichtigsten Teile der App erstellen.
Das ist eine theoretische Frage und ich finde sie sinnlos. Alle Arten von Tests können in der Toolbox eines guten SW-Ingenieurs verwendet werden, und all diese Szenarien sind unersetzbar.
quelle
Alle Arten von Tests sind sehr wichtig und stellen sicher, dass die verschiedenen Aspekte des Systems den Spezifikationen entsprechen. Um rückwärts zu arbeiten: "Wenn ich einen Testtyp wählen müsste ..." würde ich nicht. Unit-Tests bieten mir ein anderes Feedback als Integrationstests oder interaktive Tests durch eine Person.
Hier ist die Art / der Nutzen der von uns durchgeführten Tests:
Optionaler, aber empfohlener Test:
Um zu verstehen, warum Unit Testing einen Vorteil gegenüber Integrationstests hat, müssen Sie die Größenordnungen der zusätzlichen Tests verstehen, die Sie benötigen würden, um umfassend zu sein. Für jedes mögliche Ergebnis für Einheit A muss ein Test durchgeführt werden. Dasselbe gilt für Einheit B. Wenn nun beide für eine vollständigere Lösung zusammenarbeiten, ist die Anzahl der Tests kombinatorisch. Kurz gesagt, um jede Permutation der Interaktion zwischen Einheit A und Einheit B zu testen, benötigen Sie A * B-Tests. Addiere Einheit C und die Anzahl der Tests für das Trio wäre A * B * C.
Hier wird das Konzept von Schnittstellen und Objektgrenzen sehr wichtig. Schnittstellen stellen einen bestimmten Vertrag dar. Ein Implementierer einer Schnittstelle stimmt zu, dass sie sich auf eine bestimmte Weise verhält. Ebenso kann ein Verbraucher stimmt zu einer Schnittstelle , dass sie die Umsetzung in einer bestimmten Art und Weise verwendet werden. Indem Sie einen Test schreiben, der alle Klassen erfasst, die eine Schnittstelle implementieren, können Sie auf einfache Weise testen, ob jede Implementierung die Schnittstellenverträge einhält. Das ist die halbe Wahrheit. Die andere Hälfte besteht darin, die Verbraucherseite zu testen - hier kommen Scheinobjekte ins Spiel. Das Mock ist so konfiguriert, dass sichergestellt ist, dass die Interaktionen immer den Spezifikationen entsprechen. Zu diesem Zeitpunkt sind lediglich einige Integrationstests erforderlich, um sicherzustellen, dass die Implementierungs- / Verbraucherverträge korrekt sind.
quelle
Dies sind verschiedene Tools mit unterschiedlichen Zielen:
Unit Testing ist ein Designtool (TDD) und eine fast unabdingbare Voraussetzung für das Refactoring.
Integrationstests sind großartig, um den Fortschritt des Projekts zu visualisieren und Regressionsfehler zu vermeiden.
Denken Sie daran, dass Sie mit Integrationstests nicht wirklich entwerfen können und mit Komponententests keine Regressionen finden.
quelle
Ich habe Selen ausgiebig für Hygienekontrollen verwendet.
Bei einem großen Web-Verlag, als eine neue Version veröffentlicht wurde, dauerte es in der Regel ungefähr drei Tester in ein oder zwei Stunden, um alle Familien von Websites zu besuchen und sicherzustellen, dass gemäß Testskript alles in Ordnung war. Mit Selenium konnten wir die Tests automatisieren und auf mehrere Computer und Browser verteilen. Derzeit, wenn die Testskripte ausgeführt werden, dauert es ca. 10 Minuten, bis 3 PCs automatisch dasselbe tun UND einen hübschen Bericht ausspucken.
Das Tolle an Selen ist, dass Sie es mit Unit-Testing-Frameworks wie XUnit, TestNG oder MSTest verknüpfen können.
Meiner Erfahrung nach war es äußerst wertvoll, jedoch hängt die Einrichtung von so etwas wirklich von Ihrem Projekt und Ihrem Team ab, sodass der ROI auf jeden Fall variieren wird.
quelle
Der beste ROI ist normalerweise der früheste Test, der diese Art von Fehler finden kann.
Unit-Tests sollten die meisten Fehler aufdecken, die sich nur in einer Methode oder möglicherweise in einer Komponente befinden. Es werden Fehler gefunden, die normalerweise innerhalb von Minuten behoben werden können, wobei die Gesamtumschlagszeit weniger als eine Stunde beträgt. SEHR billige Tests, SEHR billige Fehler zu finden und zu beheben! Wenn diese Fehler in den Integrationstest eingegangen sind, kann der Turn-Around eher ein Tag sein (Testläufe finden häufig nachts statt), vorausgesetzt, der Fehler wird nicht von einem anderen Fehler verdeckt. Außerdem wird es wahrscheinlich mehr Bugs geben, da anderer Code gegen den ursprünglichen Buggy-Code geschrieben wurde. Darüber hinaus wirken sich alle Neugestaltungen auf mehr Codeteile aus. Wenn mehr Fehler durchgelassen werden, müssen viele weitere Testläufe durchgeführt werden, bevor der Integrationstest abgeschlossen werden kann. Schlechte Komponententests sind oft das Herzstück von langen, kostspieligen und teuren ProzessenIntegrationszyklen testen. Durch das Überspringen von Unit-Tests wird möglicherweise die Entwicklungszeit halbiert, aber das Testen dauert mindestens drei- bis viermal so lange, das gesamte Projekt wird doppelt so lang und Sie haben immer noch eine geringere Qualität als bei Unit-Tests mit IME.
Integrationstests sind normalerweise die frühesten tatsächlichen Tests, bei denen Integrationsfehler gefunden werden können (obwohl Überprüfungsprozesse einige Fehler finden können, bevor die Software geschrieben wird oder bevor der Code getestet wird). Sie möchten diese Fehler finden, bevor Sie dem Benutzer oder der Veröffentlichung die Software anzeigen, da das Beheben von Fehlern im letzten Moment (oder das Beheben von Fehlern im laufenden Betrieb!) Sehr teuer ist. Sie können diese Fehler nicht früher finden, wenn sie billiger zu beheben wären, da Sie (per Definition) mehrere funktionierende Komponenten für die Integration benötigen. Integrationstests werden verlangsamt, wenn Fehler, die nichts mit interagierenden Teilen zu tun haben (wie kleinere Tippfehler), zuerst behoben werden müssen, bevor die interessanteren Tests überhaupt beginnen können.
Beim Testen der Benutzerakzeptanz wird sichergestellt, dass die Software das tut, was der Kunde wünscht (obwohl er hoffentlich die ganze Zeit involviert war), um das Risiko zu verringern, dass am Ende des Projekts eine große Lücke zwischen den Erwartungen und der tatsächlichen Software entsteht - SEHR teuer !). Wenn Sie dieses Teststadium erreicht haben, sollten Sie wirklich glauben, dass die meisten Fehler in Ihrem Produkt, zumindest im Vergleich zu den technischen Daten, bereits gefunden wurden. Beim Testen der Benutzerakzeptanz geht es mehr darum, sicherzustellen, dass das Produkt den Anforderungen des Kunden entspricht, als dass sichergestellt wird, dass im Vergleich zu den Spezifikationen keine Fehler auftreten.
Wenn ich nur einen Testtyp automatisieren würde, wäre es ein Unit-Test. Integrationstests können manuell durchgeführt werden und wurden von vielen großen Unternehmen über Jahre hinweg auf diese Weise durchgeführt. Es ist zeitaufwändiger, Arbeiten manuell auszuführen, die von einem Computer immer wieder ausgeführt werden können, und für die meisten Projekte weitaus teurer, ganz zu schweigen von langweiligen und fehleranfälligen Aufgaben, die jedoch ausgeführt werden können. Benutzerakzeptanztests werden häufig manuell durchgeführt, da Benutzer häufig nicht wissen, wie sie ihre Tests automatisieren sollen, während sie noch testen, was ihnen wichtig ist. Unit-Tests müssen automatisiert werden. Sie müssen in der Lage sein, alle Unit-Tests innerhalb weniger Sekunden bei Bedarf so häufig wie alle paar Minuten auszuführen. Menschen können sich mit manuellen Tests einfach nicht einmal annähern. Ganz zu schweigen davon, dass Unit-Tests im Code enthalten sind und nicht ausgeführt werden können, ohne sie über Code aufzurufen, dh zu automatisieren.
Beachten Sie, dass dies in erster Linie ein Forum für Entwickler und nicht für Tester ist. Integrationstests werden hauptsächlich von Testern durchgeführt. Unit-Tests werden von Entwicklern implementiert. Natürlich sprechen Entwickler mehr über Komponententests als über andere Testarten. Dies bedeutet nicht, dass sie andere Tests nicht für wichtig halten. Es bedeutet nur, dass sie es nicht wirklich tun (oder es seltener tun).
quelle
Ich bin der Meinung, dass Akzeptanztests in diesem Szenario König sind.
Wenn ein Commit Akzeptanztests bricht, muss es aussortiert werden.
Akzeptanztests zeigen an, wo sich Ihre Software befindet, Unit-Tests nicht.
Daher können Unit-Tests ein sehr falsches Sicherheitsgefühl vermitteln.
quelle
Die Frage ist nicht so sehr, was wichtiger ist, als was automatisiert und schnell ausgeführt werden kann.
Komponententests zeigen, ob eine kleine Komponente auf bestimmte Weise für einen bestimmten Zweck geeignet ist und in der Regel klein und schnell ausgeführt werden kann. Da sie klein sind, lassen sie sich normalerweise recht einfach automatisieren.
Integrationstests zeigen, ob Komponenten zusammenarbeiten. Sie sind normalerweise viel größer und möglicherweise nicht einfach zu automatisieren. Die Laufzeit kann länger dauern. Es ist von Vorteil, sie automatisch ausführen zu können, aber es ist eine größere Aufgabe, und sie werden sowieso nicht so oft ausgeführt.
Abnahmetests zeigen, ob ein Projekt akzeptabel ist oder nicht. Dies ist normalerweise nicht vollständig automatisierbar (obwohl automatisierte Tests möglicherweise eine Rolle spielen), da es normalerweise nicht möglich ist, die genauen und vollständigen Anforderungen in einer formalen Angelegenheit festzulegen, die weniger kompliziert ist als der Quellcode selbst. Akzeptanztests beinhalten normalerweise, dass potenzielle Benutzer Dinge mit dem System tun und feststellen, dass die Ergebnisse in jeder Hinsicht zufriedenstellend sind, was normalerweise teilweise subjektiv ist. Da Abnahmetests in der Regel einmal ausgeführt werden (verschiedene Kunden möchten normalerweise ihre eigenen separaten Abnahmetests durchführen), lohnt es sich nicht, sie zu automatisieren.
quelle