Anti-Muster : Es müssen mindestens zwei Schlüsselelemente vorhanden sein, um ein tatsächliches Anti-Muster formal von einer einfachen schlechten Angewohnheit, einer schlechten Praxis oder einer schlechten Idee zu unterscheiden:
- Einige wiederholte Handlungs-, Prozess- oder Strukturmuster, die zunächst als vorteilhaft erscheinen, aber letztendlich mehr schlimme Konsequenzen als vorteilhafte Ergebnisse haben, und
- Eine überarbeitete Lösung, die klar dokumentiert, in der Praxis bewiesen und wiederholbar ist.
Stimmen Sie für das TDD-Anti-Pattern ab, das Sie einmal zu oft "in the wild" gesehen haben.
Der Blog-Beitrag von James Carr und verwandte Diskussion über testgetriebene Entwicklung yahoogroup
Wenn du einen 'unbenannten' gefunden hast, poste sie auch. Ein Beitrag pro Anti-Pattern bitte , damit die Stimmen für etwas zählen.
Mein berechtigtes Interesse ist es, die Top-n-Untergruppe zu finden, damit ich sie in naher Zukunft in einer Lunchbox besprechen kann.
unit-testing
tdd
anti-patterns
Gishu
quelle
quelle
Antworten:
Bürger zweiter Klasse - Testcode ist nicht so gut überarbeitet wie Produktionscode, der viel doppelten Code enthält, was die Verwaltung von Tests erschwert.
quelle
Die freie Fahrt / Huckepack - James Carr, Tim Ottinger
Anstatt eine neue Testfallmethode zu schreiben, um ein anderes / unterschiedliches Merkmal / eine andere Funktionalität zu testen , wird eine neue Behauptung (und die entsprechenden Aktionen, dh Act-Schritte von AAA) in einem vorhandenen Testfall mitgeführt .
quelle
true
nach jedem möglichen Mutator-Aufruf sein. Sie sollten also überprüfen, ob jede Invariantetrue
nach jeder Kombination von Mutator- und Eingabedaten steht, die Sie testen. Sie sollten jedoch die Duplizierung reduzieren und sicherstellen, dass Sie alle Invarianten überprüfen , einschließlich derjenigen, die derzeit keine Testfehler verursachen. Sie stellen sie also alle in einecheckInvariants()
Überprüfungsfunktion und verwenden diese in jedem Test. Der Code ändert sich und eine weitere Invariante wird hinzugefügt. Das setzen Sie natürlich auch in die Funktion ein. Aber es ist ein Freerider.Glücklicher Weg
Der Test bleibt auf glücklichen Pfaden (dh erwarteten Ergebnissen), ohne auf Grenzen und Ausnahmen zu testen.
JUnit Antipatterns
quelle
Der lokale Held
Ein Testfall, der von etwas abhängt, das für die Entwicklungsumgebung spezifisch ist, für die er geschrieben wurde, um ausgeführt zu werden. Das Ergebnis ist, dass der Test Entwicklungsboxen weitergibt, aber fehlschlägt, wenn jemand versucht, ihn an einer anderen Stelle auszuführen.
Die versteckte Abhängigkeit
Eng verwandt mit dem lokalen Helden, einem Komponententest, bei dem einige vorhandene Daten vor dem Ausführen des Tests irgendwo ausgefüllt werden müssen. Wenn diese Daten nicht ausgefüllt wurden, schlägt der Test fehl und gibt dem Entwickler nur wenig Aufschluss darüber, was er wollte oder warum… er gezwungen wurde, mehrere Hektar Code zu durchsuchen, um herauszufinden, woher die verwendeten Daten stammen sollten.
Leider viel zu oft mit alten DLLs gesehen, die von nebulösen und vielfältigen INI-Dateien abhängen, die auf einem bestimmten Produktionssystem nicht synchron sind, geschweige denn auf Ihrem Computer vorhanden sind, ohne die drei Entwickler, die für diese DLLs verantwortlich sind, ausführlich zu konsultieren. Seufzer.
quelle
Kettenbande
Einige Tests, die in einer bestimmten Reihenfolge ausgeführt werden müssen, dh ein Test ändert den globalen Status des Systems (globale Variablen, Daten in der Datenbank) und der nächste Test hängt davon ab.
Sie sehen dies häufig in Datenbanktests. Anstatt ein Rollback
teardown()
durchzuführen, schreiben Tests ihre Änderungen in die Datenbank. Eine weitere häufige Ursache ist, dass Änderungen am globalen Status nicht in try / finally-Blöcken eingeschlossen sind, die bereinigen, falls der Test fehlschlägt.quelle
The Mockery
Manchmal kann Spott gut und praktisch sein. Aber manchmal können Entwickler sich selbst verlieren und sich bemühen, das zu verspotten, was nicht getestet wird. In diesem Fall enthält ein Komponententest so viele Mocks, Stubs und / oder Fakes, dass das zu testende System überhaupt nicht getestet wird. Stattdessen werden die von Mocks zurückgegebenen Daten getestet.
Quelle: James Carrs Beitrag.
quelle
Der stille Fänger - Kelly?
Ein Test, der bestanden wird, wenn eine Ausnahme ausgelöst wird. Auch wenn die tatsächlich auftretende Ausnahme eine andere ist als die vom Entwickler beabsichtigte.
Siehe auch: Secret Catcher
quelle
Der Inspektor
Ein Komponententest, der die Kapselung verletzt, um eine 100% ige Codeabdeckung zu erreichen, aber so viel über die Vorgänge im Objekt weiß, dass jeder Versuch einer Umgestaltung den vorhandenen Test unterbricht und erfordert, dass Änderungen in der Einheit berücksichtigt werden Prüfung.
"Wie teste ich meine Mitgliedsvariablen, ohne sie öffentlich zu machen ... nur zum Testen von Einheiten?"
quelle
Übermäßiges Setup - James Carr
Ein Test, der ein umfangreiches Setup erfordert, um überhaupt mit dem Testen zu beginnen. Manchmal werden mehrere hundert Codezeilen verwendet, um die Umgebung auf einen Test mit mehreren beteiligten Objekten vorzubereiten. Dies kann es schwierig machen, wirklich festzustellen, was getestet wird, da das gesamte Setup „gerauscht“ ist. (Src: James Carrs Beitrag )
quelle
Analsonde
Ein Test, der verrückte, illegale oder auf andere Weise ungesunde Methoden verwenden muss, um seine Aufgabe auszuführen, z. B .: Lesen privater Felder mit Javas setAccessible (true) oder Erweitern einer Klasse, um auf geschützte Felder / Methoden zuzugreifen, oder Ausführen des Tests in ein bestimmtes Paket, um darauf zuzugreifen Paket globale Felder / Methoden.
Wenn Sie dieses Muster sehen, verwenden die getesteten Klassen zu viele versteckte Daten.
Der Unterschied zu The Inspector besteht darin, dass die zu testende Klasse versucht, selbst die Dinge zu verbergen, die Sie testen müssen. Ihr Ziel ist es also nicht, eine 100% ige Testabdeckung zu erreichen, sondern überhaupt etwas testen zu können. Stellen Sie sich eine Klasse vor, die nur private Felder hat, eine
run()
Methode ohne Argumente und überhaupt keine Getter. Es gibt keine Möglichkeit, dies zu testen, ohne gegen die Regeln zu verstoßen.Kommentar von Michael Borgwardt: Dies ist nicht wirklich ein Test-Antimuster, es ist Pragmatismus, mit Mängeln im zu testenden Code umzugehen. Natürlich ist es besser, diese Mängel zu beheben, aber dies ist bei Bibliotheken von Drittanbietern möglicherweise nicht möglich.
Aaron Digulla: Ich stimme irgendwie zu. Vielleicht ist dieser Eintrag wirklich besser für ein "JUnit HOWTO" -Wiki geeignet und nicht für ein Antipattern. Bemerkungen?
quelle
Der Test ohne Namen - Nick Pellow
Der Test, der hinzugefügt wird, um einen bestimmten Fehler im Bug-Tracker zu reproduzieren, und dessen Autor der Meinung ist, rechtfertigt keinen eigenen Namen. Anstatt einen vorhandenen, fehlenden Test zu verbessern, wird ein neuer Test mit dem Namen testForBUG123 erstellt.
Zwei Jahre später, wenn dieser Test fehlschlägt, müssen Sie möglicherweise zuerst versuchen, BUG-123 in Ihrem Bug-Tracker zu finden, um die Absicht des Tests herauszufinden.
quelle
Der langsame Sack
Ein Unit-Test, der unglaublich langsam läuft. Wenn Entwickler loslegen, haben sie Zeit, auf die Toilette zu gehen, etwas zu rauchen oder, schlimmer noch, den Test zu starten, bevor sie am Ende des Tages nach Hause gehen. (Src: James Carrs Beitrag )
aka die Tests, die nicht so häufig ausgeführt werden, wie sie sollten
quelle
Der Schmetterling
Sie müssen etwas testen, das Daten enthält, die sich ständig ändern, z. B. eine Struktur, die das aktuelle Datum enthält, und es gibt keine Möglichkeit, das Ergebnis auf einen festen Wert festzulegen. Der hässliche Teil ist, dass Sie sich überhaupt nicht für diesen Wert interessieren. Es macht Ihren Test nur komplizierter, ohne einen Mehrwert zu schaffen.
Die Fledermaus ihres Flügels kann einen Hurrikan auf der anderen Seite der Welt verursachen. - Edward Lorenz, Der Schmetterlingseffekt
quelle
System.DateTime.Now
die einfacheren oder deterministischeren Komponententests herauszufiltern ?toString()
eines Objekts, das die Methode nicht überschreibt. Dadurch erhalten Sie die ID des Objekts, die von der Speicheradresse abhängt. OdertoString()
enthält den Primärschlüssel des Objekts, der sich jedes Mal ändert, wenn Sie den Test ausführen. Es gibt drei Möglichkeiten, dies zu beheben: 1. Ändern Sie den Code, den Sie testen, 2. Verwenden Sie Regexp, um die variablen Teile der Testergebnisse zu entfernen, oder 3. Verwenden Sie leistungsstarke Tools, um Systemdienste zu überschreiben, damit sie vorhersehbare Ergebnisse zurückgeben.Der Flackertest (Quelle: Romilly Cocking)
Ein Test, der nur gelegentlich fehlschlägt, nicht zu bestimmten Zeiten, und der im Allgemeinen auf die Rennbedingungen innerhalb des Tests zurückzuführen ist. Tritt normalerweise auf, wenn etwas Asynchrones getestet wird, z. B. JMS.
Möglicherweise ein Super-Set für das Anti-Pattern ' Wait and See ' und das Anti-Pattern ' The Sleeper '.
Der Build ist fehlgeschlagen. Führen Sie den Build einfach erneut aus. - Anonymer Entwickler
quelle
Warten wir es ab
Ein Test, der einen eingerichteten Code ausführt und dann eine bestimmte Zeit warten muss, bevor er sehen kann, ob der zu testende Code wie erwartet funktioniert. Eine testMethod, die Thread.sleep () oder eine gleichwertige Methode verwendet, ist mit Sicherheit ein "Wait and See" -Test.
In der Regel wird dies angezeigt, wenn der Test Code testet, der ein systemexternes Ereignis wie eine E-Mail, eine http-Anforderung oder das Schreiben einer Datei auf die Festplatte generiert.
Ein solcher Test kann auch ein lokaler Held sein, da er fehlschlägt, wenn er auf einer langsameren Box oder einem überlasteten CI-Server ausgeführt wird.
Das Wait-and-See-Anti-Pattern ist nicht mit The Sleeper zu verwechseln .
quelle
Unangemessen gemeinsam genutztes Gerät - Tim Ottinger
Mehrere Testfälle im Testgerät verwenden nicht einmal das Setup / Teardown oder benötigen es. Teilweise aufgrund der Trägheit des Entwicklers beim Erstellen einer neuen Testvorrichtung ... einfacher, einfach einen weiteren Testfall zum Stapel hinzuzufügen
quelle
Der Riese
Ein Komponententest, der, obwohl er das zu testende Objekt gültig testet, Tausende von Zeilen umfassen kann und viele, viele Testfälle enthält. Dies kann ein Indikator dafür sein, dass das zu testende System ein Gottobjekt ist (James Carrs Beitrag).
Ein sicheres Zeichen für diesen ist ein Test, der mehr als ein paar Codezeilen umfasst. Oft ist der Test so kompliziert, dass er Fehler seines eigenen oder schuppigen Verhaltens enthält.
quelle
Ich werde es glauben, wenn ich einige blinkende GUIs sehe.
Eine ungesunde Fixierung / Besessenheit, die App über ihre GUI zu testen, "genau wie ein echter Benutzer".
"Sie müssen verstehen, dass Sehen Glauben ist, aber Sie müssen auch wissen, dass Glauben Sehen ist." - Denis Waitley
quelle
Der Schläfer, auch bekannt als Vesuv - Nick Pellow
Ein Test, der zu einem bestimmten Zeitpunkt und Datum in der Zukunft fehlschlagen soll. Dies wird häufig durch die Überprüfung falscher Grenzen beim Testen von Code verursacht, der ein Datums- oder Kalenderobjekt verwendet. Manchmal schlägt der Test fehl, wenn er zu einer bestimmten Tageszeit ausgeführt wird, z. B. um Mitternacht.
'The Sleeper' ist nicht mit dem Anti-Pattern ' Wait And See ' zu verwechseln .
Dieser Code wird lange vor dem Jahr 2000 ersetzt worden sein - viele Entwickler im Jahr 1960
quelle
Der tote Baum
Ein Test, bei dem ein Stub erstellt wurde, der Test jedoch nicht geschrieben wurde.
Ich habe dies tatsächlich in unserem Produktionscode gesehen:
Ich weiß nicht einmal, was ich davon halten soll.
quelle
habe heute etwas davon mitbekommen:
Wet Floor :
Der Test erstellt Daten, die irgendwo gespeichert bleiben, aber der Test wird nach Abschluss nicht bereinigt. Dies führt dazu, dass Tests (der gleiche Test oder möglicherweise andere Tests) bei nachfolgenden Testläufen fehlschlagen .
In unserem Fall hat der Test eine Datei im Verzeichnis "temp" mit den Berechtigungen des Benutzers, der den Test zum ersten Mal ausgeführt hat, herumliegen lassen. Wenn ein anderer Benutzer versucht hat, auf derselben Maschine zu testen: Ausleger. In den Kommentaren auf James Carrs Website bezeichnete Joakim Ohlrogge dies als "Sloppy Worker" und es war Teil der Inspiration für "Generous Leftovers". Ich mag meinen Namen besser (weniger beleidigend, vertrauter).
quelle
Der Kuckuck - Frank Carver
Ein Komponententest, der sich in einem Testfall mit mehreren anderen befindet und denselben (möglicherweise langwierigen) Einrichtungsprozess wie die anderen Tests im Testfall durchführt, dann jedoch einige oder alle Artefakte aus dem Setup verwirft und schafft seine eigenen.
Erweitertes Symptom für: Unangemessen freigegebenes Gerät
quelle
The Secret Catcher - Frank Carver
Ein Test, der auf den ersten Blick keine Tests durchführt, da keine Aussagen vorliegen. Aber "Der Teufel steckt im Detail". Der Test basiert wirklich auf einer Ausnahme, die ausgelöst wird, und erwartet, dass das Testframework die Ausnahme erfasst und dem Benutzer als Fehler meldet.
quelle
Assert.DoesNotThrow(SomeDelegateType act)
Stilzusicherung, die in solchen Fällen speziell verwendet werden kann. Ich finde das weniger grob als einen Testfall, der erfolgreich ist, wenn ein Konstruktor nicht null zurückgibt, aber fehlschlägt, wenn der Konstruktor wirft. Ein Konstruktor gibt niemals null zurück. (Hinweis: Gilt nur für Sprachen, in denen ein Konstruktor garantiert nicht null zurückgibt.)Der Umweltvandal
Ein "Unit" -Test, der für verschiedene "Anforderungen" in seine Umgebung gelangt und Umgebungsvariablen / -ports verwendet und festlegt. Das gleichzeitige Ausführen von zwei dieser Tests führt zu Ausnahmen für nicht verfügbare Ports usw.
Diese Tests werden zeitweise durchgeführt und lassen Entwickler Dinge wie "Führen Sie es einfach noch einmal aus" sagen.
Eine Lösung, die ich gesehen habe, besteht darin, zufällig eine zu verwendende Portnummer auszuwählen. Dies verringert die Möglichkeit eines Konflikts, löst das Problem jedoch eindeutig nicht. Wenn Sie können, verspotten Sie den Code immer so, dass er die nicht gemeinsam nutzbare Ressource nicht tatsächlich zuweist.
quelle
Der Turing-Test
Ein Testfall, der automatisch von einem teuren Tool generiert wird, das viele, viele Aussagen aus der zu testenden Klasse mithilfe einer zu cleveren Datenflussanalyse enthält. Lullt Entwickler in ein falsches Gefühl des Vertrauens, dass ihr Code gut getestet ist, und entbindet sie von der Verantwortung, qualitativ hochwertige Tests zu entwerfen und aufrechtzuerhalten. Wenn das Gerät die Tests für Sie schreiben kann, warum kann es dann nicht den Finger herausziehen und die App selbst schreiben?
Hallo Dummkopf. - Der intelligenteste Computer der Welt für einen neuen Lehrling (aus einem alten Amiga-Comic).
quelle
Der Vierzig-Fuß-Pol-Test
Diese Tests haben Angst, der Klasse, die sie testen möchten, zu nahe zu kommen. Sie wirken auf Distanz, getrennt durch unzählige Abstraktionsebenen und Tausende von Codezeilen von der Logik, die sie überprüfen. Als solche sind sie extrem spröde und anfällig für alle möglichen Nebenwirkungen, die auf der epischen Reise von und zur interessierenden Klasse auftreten.
quelle
Doppelgänger
Um etwas zu testen, müssen Sie Teile des zu testenden Codes in eine neue Klasse mit demselben Namen und Paket kopieren und Klassenpfadmagie oder einen benutzerdefinierten Klassenladeprogramm verwenden, um sicherzustellen, dass er zuerst sichtbar ist (damit Ihre Kopie ausgewählt wird) oben).
Dieses Muster weist auf eine ungesunde Anzahl versteckter Abhängigkeiten hin, die Sie mit einem Test nicht kontrollieren können.
Ich sah sein Gesicht an ... mein Gesicht! Es war wie ein Spiegel, aber mein Blut gefror.
quelle
Die Mutter Henne - Frank Carver
Ein gängiges Setup, das weit mehr kann, als die eigentlichen Testfälle benötigen. Erstellen Sie beispielsweise alle Arten komplexer Datenstrukturen, die mit scheinbar wichtigen und eindeutigen Werten gefüllt sind, wenn die Tests nur das Vorhandensein oder Fehlen von etwas bestätigen.
Erweitertes Symptom für: Unangemessen freigegebenes Gerät
Ich weiß nicht, was es tut ... Ich füge es trotzdem hinzu, nur für den Fall. - Anonymer Entwickler
quelle
Der Test alles
Ich kann nicht glauben, dass dies bisher nicht erwähnt wurde, aber Tests sollten nicht gegen das Prinzip der Einzelverantwortung verstoßen .
Ich bin so oft darauf gestoßen, dass Tests, die gegen diese Regel verstoßen, per Definition ein Albtraum sind.
quelle
Line Hitter
Auf den ersten Blick deckt Tests alles ab und die Tools zur Codeabdeckung bestätigen dies zu 100%. In Wirklichkeit treffen Tests jedoch nur Code ohne Ausgabeanalysen.
Coverage-vs-Reachable-Code
quelle