Ich stelle diese Frage zu Problemen, die ich bei TDD-Projekten hatte. Beim Erstellen von Komponententests sind mir die folgenden Herausforderungen aufgefallen.
- Generieren und Pflegen von Scheindaten
Es ist schwierig und unrealistisch, große Scheindaten zu verwalten. Es ist noch schwieriger, wenn sich die Datenbankstruktur ändert.
- GUI testen
Selbst mit MVVM und der Möglichkeit, die GUI zu testen, ist viel Code erforderlich, um das GUI-Szenario zu reproduzieren.
- Testen Sie das Geschäft
Ich habe die Erfahrung gemacht, dass TDD gut funktioniert, wenn Sie es auf einfache Geschäftslogik beschränken. Komplexe Geschäftslogik ist jedoch schwer zu testen, da die Anzahl der Testkombinationen (Testbereich) sehr groß ist.
- Widerspruch in den Anforderungen
In der Realität ist es schwierig, alle Anforderungen zu analysieren und zu entwerfen. Oft führen Anforderungen an eine Notiz zu Widersprüchen, da das Projekt komplex ist. Der Widerspruch wird erst spät in der Umsetzungsphase festgestellt. TDD setzt voraus, dass die Anforderungen zu 100% korrekt sind. In solchen Fällen ist zu erwarten, dass bei der Erstellung von Tests widersprüchliche Anforderungen erfasst werden. Das Problem ist jedoch, dass dies in komplexen Szenarien nicht der Fall ist.
Ich habe die Frage gelesen: Warum funktioniert TDD?
Funktioniert TDD wirklich für komplexe Unternehmensprojekte oder ist es praktisch auf den Projekttyp beschränkt?
Antworten:
Falsch.
Unit-Tests erfordern keine "großen" Scheindaten. Es sind genügend Scheindaten erforderlich, um die Szenarien zu testen, und nicht mehr.
Außerdem bitten die wirklich faulen Programmierer die Fachexperten, einfache Tabellenkalkulationen der verschiedenen Testfälle zu erstellen. Nur eine einfache Tabelle.
Dann schreibt der faule Programmierer ein einfaches Skript, um die Tabellenzeilen in Komponententestfälle umzuwandeln. Es ist wirklich ziemlich einfach.
Wenn sich das Produkt weiterentwickelt, werden die Arbeitsblätter der Testfälle aktualisiert und neue Komponententests generiert. Mach es die ganze Zeit. Es funktioniert wirklich.
Was? "Reproduzieren"?
Der Zweck von TDD ist es, Dinge für die Testbarkeit zu entwerfen (Test Drive Development). Wenn die GUI so komplex ist, muss sie umgestaltet werden, um einfacher und testbarer zu sein. Einfacher bedeutet auch schneller, wartbarer und flexibler. Aber meistens bedeutet einfacher prüfbarer.
Das kann wahr sein.
Es ist jedoch sehr hilfreich, die Fachexperten aufzufordern, die wichtigsten Testfälle in einer einfachen Form (wie einer Tabelle) bereitzustellen.
Die Tabellenkalkulationen können ziemlich groß werden. Aber das ist in Ordnung, da ich ein einfaches Python-Skript verwendet habe, um die Arbeitsblätter in Testfälle umzuwandeln.
Und. Ich musste einige Testfälle manuell schreiben, da die Tabellen unvollständig waren.
Jedoch. Als die Benutzer "Bugs" meldeten, fragte ich einfach, welcher Testfall in der Tabelle falsch war.
In diesem Moment korrigierten die Fachexperten entweder die Tabelle oder fügten Beispiele hinzu, um zu erklären, was passieren sollte. Die Fehlerberichte können - in vielen Fällen - eindeutig als Testfallproblem definiert werden. Meiner Erfahrung nach macht die Definition des Fehlers als fehlerhafter Testfall die Diskussion sehr viel einfacher.
Anstatt Experten zuzuhören, die versuchen, einen überkomplexen Geschäftsprozess zu erklären, müssen die Experten konkrete Beispiele für den Prozess erstellen.
Wenn Sie TDD nicht verwenden, müssen die Anforderungen unbedingt zu 100% stimmen. Einige behaupten, dass TDD unvollständige und sich ändernde Anforderungen tolerieren kann, während ein Ansatz ohne TDD nicht mit unvollständigen Anforderungen funktionieren kann.
Wenn Sie TDD nicht verwenden, wird der Widerspruch erst spät in der Implementierungsphase festgestellt.
Wenn Sie TDD verwenden, wird der Widerspruch früher festgestellt, wenn der Code einige Tests besteht und andere Tests nicht bestehen. In der Tat liefert TDD den Beweis für einen Widerspruch zu einem früheren Zeitpunkt im Prozess, lange vor der Implementierung (und Argumente während der Benutzerakzeptanztests).
Sie haben Code, der einige Tests besteht und andere nicht besteht. Sie betrachten nur diese Tests und Sie finden den Widerspruch. In der Praxis funktioniert das sehr, sehr gut, denn jetzt müssen sich die Benutzer über den Widerspruch streiten und konsistente, konkrete Beispiele für das gewünschte Verhalten liefern.
quelle
Ja
Meine erste Erfahrung mit TDD bestand darin, an den Middleware-Komponenten für ein Linux-basiertes Mobiltelefon zu arbeiten. Das ergab schließlich Millionen von Quellcodezeilen, die wiederum 9 Gigabyte Quellcode für verschiedene Open-Source-Komponenten erforderten.
Von allen Autoren von Komponenten wurde erwartet, dass sie sowohl eine API als auch eine Reihe von Komponententests vorschlagen und diese von einem Peer-Committee überprüfen lassen. Niemand erwartete beim Testen Perfektion, aber für alle öffentlich zugänglichen Funktionen musste mindestens ein Test durchgeführt werden, und sobald eine Komponente der Quellcodeverwaltung unterzogen wurde, mussten alle Komponententests immer bestanden werden (auch wenn dies der Fall war, weil die Komponente fälschlicherweise meldete) es hat gut funktioniert).
Zumindest teilweise auf TDD zurückzuführen und darauf, dass alle Komponententests immer bestanden wurden, erschien die Version 1.0 früh, unter dem Budget und mit erstaunlicher Stabilität.
Nach der Veröffentlichung von 1.0 forderten die Unternehmen auf, die Durchführung von TDD zu beenden und die Anforderung, dass Komponententests bestanden werden, zu streichen, da sie den Umfang aufgrund von Kundenanforderungen schnell ändern wollten. Es war erstaunlich, wie schnell die Qualität auf die Toilette ging, und dann folgte der Zeitplan.
quelle
removed the requirement that unit tests pass. It was astonishing how quickly quality went down the toilet, and then the schedule followed it.
- Es ist, als würde man seinem F1-Fahrer sagen, dass er keine Boxenstopps einlegen darf, weil es zu lange dauert ... Idiotisch.Ich würde sagen, je komplexer das Projekt ist, desto mehr profitieren Sie von TDD. Die Hauptvorteile sind die Nebenwirkungen, durch die TDD Sie zwingt, den Code in viel kleineren, viel unabhängigeren Blöcken zu schreiben. Hauptvorteile sind:
a) Sie erhalten eine sehr viel frühere Validierung Ihres Designs, da Ihre Rückkopplungsschleife aufgrund von Tests von Anfang an viel enger ist.
b) Sie können Kleinigkeiten austauschen und sehen, wie das System reagiert, da Sie die ganze Zeit über eine Testabdeckung erstellt haben.
c) Der fertige Code wird dadurch viel besser.
quelle
Funktioniert TDD wirklich für komplexe Projekte?
Ja. Nicht jedes Projekt, so wurde mir gesagt, funktioniert gut mit TDD, aber die meisten Geschäftsanwendungen sind in Ordnung, und ich wette, diejenigen, die nicht gut funktionieren, wenn sie auf reine TDD-Weise geschrieben sind, könnten ohne größere Probleme auf ATDD-Weise geschrieben werden.
Generieren und Verwalten von Scheindaten
Halten Sie Ihre Daten klein und haben Sie nur das, was Sie benötigen. Dies ist anscheinend kein beängstigendes Problem. Versteh mich nicht falsch, es ist ein Schmerz. Aber es lohnt sich.
Testen der Benutzeroberfläche
Testen Sie die MVVM und stellen Sie sicher, dass sie ohne die Ansicht getestet werden kann. Ich fand das nicht schwieriger als das Testen eines anderen Teils der Geschäftslogik. Testen Sie die Ansicht in Code, den ich nicht tue. An dieser Stelle testen Sie jedoch nur die Bindungslogik, von der man hofft, dass sie schnell erkannt wird, wenn Sie einen schnellen manuellen Test durchführen.
Testen des Geschäfts
Kein Problem gefunden. Viele kleine Tests. Wie ich oben sagte, sind einige Fälle (Sudoku-Puzzle-Löser scheinen sehr beliebt zu sein) anscheinend schwierig, TDD zu machen.
TDD setzt voraus, dass die Anforderungen zu 100% korrekt sind
. Woher hast du diese Idee? Alle agilen Praktiken akzeptieren, dass sich die Anforderungen ändern. Sie müssen wissen, was Sie tun, bevor Sie es tun, aber das ist nicht dasselbe, als wenn die Anforderungen 100% betragen müssen. TDD ist eine gängige Praxis in Scrum, bei der die Anforderungen (User Stories) per definitionem nicht zu 100% vollständig sind.
quelle
Zunächst einmal glaube ich, dass es bei Ihrem Problem mehr um Unit-Tests im Allgemeinen als um TDD geht, da ich in Ihren Aussagen nichts wirklich TDD-spezifisches (Test-First + Rot-Grün-Refactor-Zyklus) sehe.
Was meinen Sie mit Scheindaten? Ein Mock soll genau genommen kaum Daten enthalten, dh keine anderen Felder als das eine oder andere, die im Test benötigt werden, und keine anderen Abhängigkeiten als das zu testende System. Das Einrichten einer Scheinerwartung oder eines Rückgabewerts kann in einer Zeile erfolgen, also nichts Schreckliches.
Wenn Sie meinen, dass die Datenbank Änderungen erfährt, ohne dass die entsprechenden Änderungen am Objektmodell vorgenommen wurden, sind genau die Unit-Tests hilfreich, um Sie davor zu warnen. Andernfalls müssen Änderungen am Modell offensichtlich in den Komponententests berücksichtigt werden, aber bei Kompilierungsangaben ist dies eine einfache Sache.
Sie haben Recht, das Testen der GUI (View) ist nicht einfach, und viele Leute tun es auch ohne (außerdem gehört das Testen der GUI nicht zu TDD). Im Gegensatz dazu ist es einer der Hauptgründe für das Testen von Mustern wie MVC oder MVVM, wenn Sie Ihren Controller / Presenter / ViewModel / eine beliebige Zwischenschicht testen.
Wenn Ihre Geschäftslogik komplex ist, ist es normal, dass Ihre Komponententests schwer zu entwerfen sind. Es liegt an Ihnen, sie so atomar wie möglich zu gestalten und jeweils nur eine Verantwortung des zu prüfenden Objekts zu prüfen. Unit-Tests werden in einer komplexen Umgebung umso mehr benötigt, als sie ein Sicherheitsnetz bieten, das garantiert, dass Sie bei Änderungen am Code nicht gegen Geschäftsregeln oder -anforderungen verstoßen.
Absolut nicht. Erfolgreiche Software setzt voraus, dass die Anforderungen zu 100% korrekt sind. Wenn die Vision fehlerhaft ist, werden auch Ihr Code und Ihre Software Komponententests sein oder nicht ... Und hier leuchten Komponententests: Mit ausreichend expliziten Testtiteln werden Ihre Entwurfsentscheidungen und die Interpretation der Anforderungen transparent, was es einfacher macht, darauf hinzuweisen Finden Sie heraus, was beim nächsten Mal geändert werden muss, wenn Ihr Kunde sagt: "Diese Geschäftsregel ist nicht so, wie ich es gerne hätte."
quelle
Ich muss lachen, wenn ich jemanden beschweren höre, dass er TDD nicht zum Testen seiner Anwendung verwenden kann, weil seine Anwendung so kompliziert ist. Was ist die Alternative? Haben Sie Testaffen, die auf einem Hektar großen Tastaturgebiet herumtollen? Lassen Sie die Benutzer die Tester sein? Was sonst? Natürlich ist es schwierig und komplex. Denken Sie, dass Intel die Chips erst testet, wenn sie ausgeliefert werden? Wie "head-in-the-sand" ist das?
quelle
Ich habe festgestellt, dass TDD (und Unit-Tests im Allgemeinen) aus einem ähnlichen Grund praktisch unmöglich sind: Komplexe, neuartige und / oder unscharfe Algorithmen. Das Problem, auf das ich bei den Forschungsprototypen, die ich schreibe, am häufigsten stoße, ist, dass ich keine Ahnung habe, was die richtige Antwort ist, außer meinen Code auszuführen. Es ist zu kompliziert, für alles andere als lächerlich triviale Fälle einigermaßen von Hand herauszufinden. Dies gilt insbesondere dann, wenn der Algorithmus Heuristiken, Approximationen oder Nichtdeterminismus umfasst. Ich versuche immer noch, die Funktionalität auf niedrigerer Ebene zu testen, von der dieser Code abhängt, und verwende Asserts stark zur Überprüfung der Integrität. Meine letzte Möglichkeit zum Testen besteht darin, zwei verschiedene Implementierungen zu schreiben, idealerweise in zwei verschiedenen Sprachen, wobei zwei verschiedene Bibliotheksgruppen verwendet werden, und die Ergebnisse zu vergleichen.
quelle
Aus meiner Erfahrung: Ja für Unittests (Test von Modulen / Features isoliert), da diese meist nicht die von Ihnen genannten Probleme haben: (Gui, Mvvm, Business-Modell). Ich hatte nie mehr als 3 Mocks / Stubs, um einen Unittest zu erfüllen (aber möglicherweise erfordert Ihre Domain mehr).
Ich bin mir jedoch nicht sicher, ob TDD die Probleme lösen könnte, die Sie bei der Integration oder den End-to-End-Tests mit BDD-ähnlichen Tests angesprochen haben .
Aber zumindest einige Probleme können reduziert werden .
Dies ist der Fall, wenn Sie eine vollständige Abdeckung auf der Ebene des Integrationstests oder des End-to-End-Tests durchführen möchten. Es könnte einfacher sein, die vollständige Berichterstattung auf einer unbeschreiblichen Ebene durchzuführen.
Beispiel: Überprüfen komplexer Benutzerberechtigungen
Das Testen der Funktion
IsAllowedToEditCusterData()
auf einer Integrationstestebene würde erfordern, dass verschiedene Objekte nach Informationen über Benutzer, Domäne, Kunde, Umgebung ... gefragt werden.Diese Teile zu verspotten ist ziemlich schwierig. Dies gilt insbesondere dann, wenn
IsAllowedToEditCusterData()
diese unterschiedlichen Objekte bekannt sein müssen.Auf einer Unittest-Ebene hätten Sie eine Funktion
IsAllowedToEditCusterData()
, die zum Beispiel 20 Parameter akzeptiert, die alles enthalten, was die Funktion wissen muss. DaIsAllowedToEditCusterData()
muss man nicht wissen, welche Felder auser
, adomain
, acustomer
, .... das hat man einfach zu testen.Als ich implementieren musste, hatte
IsAllowedToEditCusterData()
ich zwei Überladungen davon:Eine Überladung, die nichts weiter tut, als diese 20 Parameter abzurufen und dann die Überladung mit den 20 Parametern aufzurufen, die die Entscheidungen treffen.
(Meine
IsAllowedToEditCusterData()
hatte nur 5 Parameter und ich brauchte 32 verschiedene Kombinationen, um es vollständig zu testen)Beispiel
quelle
Die traurige Antwort ist, dass bei großen komplexen Projekten nichts wirklich funktioniert!
TDD ist so gut wie nichts anderes und besser als die meisten anderen, aber TDD allein garantiert keinen Erfolg bei einem großen Projekt. Es wird jedoch Ihre Erfolgschancen erhöhen. Insbesondere in Kombination mit anderen Projektmanagementdisziplinen (Anforderungsüberprüfung, Anwendungsfälle, Anforderungsverfolgbarkeitsmatrix, Code-exemplarische Vorgehensweisen usw.).
quelle
Denken Sie daran, dass Unit-Tests erzwungene Spezifikationen sind . Dies ist besonders bei komplexen Projekten von Nutzen. Wenn Ihre alte Codebasis keine Tests zum Sichern hat, wird sich niemand trauen, etwas zu ändern, weil sie Angst haben, etwas zu beschädigen.
"Wtf. Warum gibt es diese Code-Verzweigung überhaupt? Weiß nicht, vielleicht braucht es jemand, lass es besser, als jemanden zu verärgern ..." Im Laufe der Zeit werden die komplexen Projekte zu einem Müllland.
Bei Tests kann jeder mit Zuversicht sagen: "Ich habe drastische Änderungen vorgenommen, aber alle Tests sind noch nicht abgeschlossen." Per Definition hat er nichts gebrochen. Dies führt zu agileren Projekten, die sich entwickeln können. Vielleicht ist einer der Gründe, warum wir immer noch Leute brauchen, um COBOL zu warten, dass das Testen seitdem nicht populär war: P
quelle
Ich habe gesehen, dass ein großes komplexes Projekt völlig fehlgeschlagen ist, als TDD exklusiv verwendet wurde, dh ohne zumindest in einem Debugger / einer IDE einzurichten. Die Scheindaten und / oder Tests erwiesen sich als unzureichend. Die tatsächlichen Daten des Beta-Clients waren vertraulich und konnten weder kopiert noch protokolliert werden. Das Entwicklerteam konnte also niemals die schwerwiegenden Fehler beheben, die auftraten, wenn auf reale Daten verwiesen wurde, und das gesamte Projekt wurde verschrottet, alle feuerten, das ganze Stück.
Die Möglichkeit, dieses Problem zu beheben, bestand darin, es in einem Debugger am Clientstandort zu starten, mit den realen Daten zu vergleichen, den Code mit Haltepunkten, Überwachungsvariablen, Überwachungsspeicher usw. zu durchlaufen. Wer glaubte, sein Code könne die schönsten Elfenbeintürme schmücken, der hatte in einem Zeitraum von fast einem Jahr noch nie eine App gestartet. Das hat mich umgehauen.
Balance ist also wie alles der Schlüssel. TDD mag gut sein, aber verlassen Sie sich nicht ausschließlich darauf.
quelle
Ich denke schon, Test Driven Development funktioniert wirklich
quelle
Wenn die Kombination aus Budget, Anforderungen und Teamfähigkeiten im Quadranten des Projektraums steht und heißt, "hoffentlich alle aufgeben, die hier eintreten", ist es per definitionem mit überwältigender Wahrscheinlichkeit wahrscheinlich, dass das Projekt scheitert.
Vielleicht sind die Anforderungen komplex und volatil, die Infrastruktur instabil, das Team jünger und mit hohem Umsatz, oder der Architekt ist ein Idiot.
In einem TDD-Projekt besteht das Symptom für diesen bevorstehenden Fehler darin, dass Tests nicht termingerecht geschrieben werden können. Sie versuchen, nur um herauszufinden, "das wird so lange dauern , und wir haben nur das ".
Andere Ansätze zeigen andere Symptome, wenn sie fehlschlagen. am häufigsten Lieferung eines Systems, das nicht funktioniert. Politik und Verträge werden entscheiden, ob dies vorzuziehen ist.
quelle
TDD
Das klingt im Vorfeld vielleicht schmerzhaft, ist aber auf lange Sicht Ihr bester Freund. Vertrauen Sie mir,TDD
dass die Anwendung auf lange Sicht wirklich wartbar und sicher ist.quelle