it-swarm.com.de

Unit Testing Anti-Pattern-Katalog

Anti-Pattern: Es müssen mindestens zwei Schlüsselelemente vorhanden sein, um ein tatsächliches Anti-Pattern formal von einem einfachen Bad zu unterscheiden Gewohnheit, schlechte Praxis oder schlechte Idee:

  • Einige wiederholte Handlungsmuster, Prozesse oder Strukturen, die zunächst als vorteilhaft erscheinen, letztendlich jedoch schlimmere Folgen haben als vorteilhafte Ergebnisse
  • Eine überarbeitete Lösung, die klar dokumentiert, in der Praxis bewährt und wiederholbar ist.

Stimmen Sie für das TDD-Anti-Pattern ab, das Sie einmal zu oft "in the wild" gesehen haben.
Der Blogbeitrag von James Carr und Zugehörige Diskussion zu Testlaufwerksentwicklung yahoogroup

Wenn Sie einen "unbenannten" gefunden haben ... posten Sie ihn auch. Bitte einen Beitrag pro Anti-Pattern , damit die Stimmen für etwas zählen.

Mein persönliches Interesse ist es, die Top-n-Untergruppe zu finden, damit ich sie in naher Zukunft in einem Lunchbox-Treffen besprechen kann.

203
Gishu

Bürger zweiter Klasse - Der Testcode wurde nicht so gut überarbeitet wie der Produktionscode, da er viel duplizierten Code enthält, was es schwierig macht, Tests aufrechtzuerhalten.

70
Ilja Preuß

The Free Ride/Piggyback - James Carr, Tim Ottinger
Anstatt eine neue Testfallmethode zu schreiben, um zu testen ein weiteres/unterschiedliches Merkmal/Funktionalität, wird eine neue Behauptung (und die entsprechenden Aktionen, dh Schritte von AAA ausführen) in einem vorhandenen Testfall ausgeführt .

67
Gishu

Glücklicher Weg

Der Test bleibt auf guten Wegen (d. H. Erwarteten Ergebnissen), ohne auf Grenzen und Ausnahmen zu testen.

JUnit Antipatterns

64
Geoglyph

Der lokale Held

Ein Testfall, der von etwas abhängig ist, das für die Entwicklungsumgebung spezifisch ist, auf der er geschrieben wurde, um ausgeführt zu werden. Das Ergebnis ist, dass der Test Entwicklungsboxen weiterleitet, aber fehlschlägt, wenn jemand versucht, ihn anderswo auszuführen.

Die versteckte Abhängigkeit

Eng verwandt mit dem lokalen Helden, einem Komponententest, der voraussetzt, dass einige vorhandene Daten irgendwo gefüllt wurden, bevor der Test ausgeführt wird. Wenn diese Daten nicht ausgefüllt wurden, schlägt der Test fehl und überlässt dem Entwickler nur einen kleinen Hinweis darauf, was er wollte oder warum er sie dazu zwingt, durch mehrere Hektar Code zu graben, um herauszufinden, woher die verwendeten Daten stammen sollten.


Leider viel zu oft mit alten .dlls gesehen, die von nebulösen und abwechslungsreichen .ini-Dateien abhängen, die auf einem bestimmten Produktionssystem ständig nicht synchron sind, geschweige denn auf Ihrem Computer vorhanden sind, ohne die drei Entwickler, die für diese DLLs verantwortlich sind, eingehend zu konsultieren. Seufzer.

59
annakata

Chain Gang

Eine Reihe von Tests, die in einer bestimmten Reihenfolge ausgeführt werden müssen, d. H. Ein Test ändert den globalen Status des Systems (globale Variablen, Daten in der Datenbank), und der oder die nächsten Tests hängen davon ab.

Sie sehen dies häufig in Datenbanktests. Anstatt ein Rollback in teardown() durchzuführen, schreiben die 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 bei einem Fehlschlagen des Tests bereinigt werden.

58
Aaron Digulla

The Mockery
Manchmal kann Spott gut und praktisch sein. Aber manchmal verlieren Entwickler sich selbst und bemühen sich herauszufinden, was nicht getestet wird. In diesem Fall enthält ein Komponententest so viele Mocks, Stubs und/oder Fakes, dass das getestete System überhaupt nicht getestet wird. Stattdessen werden die von Mocks zurückgegebenen Daten getestet.

Quelle: James Carrs Beitrag.

56
Gishu

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, die der Entwickler beabsichtigt hat.
Siehe auch: Geheimfänger

[Test]
[ExpectedException(typeof(Exception))]
public void ItShouldThrowDivideByZeroException()
{
   // some code that throws another exception yet passes the test
}
40
Gishu

Der Inspektor
Ein Komponententest, der gegen die Kapselung verstößt, um eine 100% ige Codeabdeckung zu erreichen, aber so viel über die Vorgänge im Objekt weiß, dass jeder Versuch der Umgestaltung den vorhandenen Test unterbricht und jede Änderung widerspiegelt im Unit-Test.


'Wie teste ich meine Mitgliedsvariablen, ohne sie öffentlich zu machen ... nur für Unit-Tests?'

34
Gishu

Übermäßige Einrichtung - 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 aufgrund des „Rauschens“ des gesamten Setups schwierig machen, wirklich festzustellen, was getestet wird. (Src: James Carrs Beitrag )

34
Gishu

Analsonde

Ein Test, der verrückte, illegale oder auf andere Weise ungesunde Methoden anwenden muss, um seine Aufgabe zu erfüllen, z. B .: Lesen privater Felder mit Javas setAccessible (true) oder Erweitern einer Klasse, um auf geschützte Felder/Methoden zuzugreifen oder den Test in einem bestimmten Paket durchführen müssen, um auf globale Felder/Methoden des Pakets zuzugreifen.

Wenn Sie dieses Muster sehen, verwenden die getesteten Klassen zu viele versteckte Daten.

Der Unterschied zu The Inspector besteht darin, dass die getestete 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 enthält, eine run() -Methode ohne Argumente und ohne Getter. Es gibt keine Möglichkeit, dies zu testen, ohne die Regeln zu brechen.


Kommentar von Michael Borgwardt: Dies ist kein wirkliches Test-Antimuster, es ist Pragmatismus, mit Mängeln im getesteten 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 Antimuster. Bemerkungen?

32
Aaron Digulla

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, dass er keinen eigenen Namen verdient. 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.

26
npellow

Der langsame Stoß

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 )

a.k.a. die Tests, die nicht so häufig ausgeführt werden, wie sie sollten

25
Gishu

Der Schmetterling

Sie müssen etwas testen, das Daten enthält, die sich ständig ändern, wie 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 diesen Wert überhaupt nicht interessieren. Dies macht Ihren Test nur komplizierter, ohne dass ein Mehrwert entsteht.

Die Fledermaus seines Flügels kann einen Hurrikan auf der anderen Seite der Welt verursachen. - Edward Lorenz, Der Schmetterlingseffekt

20
Aaron Digulla

Der Flackertest (Quelle: Romilly Cocking)

Ein Test, der nur gelegentlich und nicht zu bestimmten Zeiten fehlschlägt und im Allgemeinen auf die Rennbedingungen im Test zurückzuführen ist. Tritt normalerweise beim Testen von asynchronen Objekten auf, z. B. JMS.

Möglicherweise ein Super-Set für das Anti-Pattern ' Wait and See ' und ' The Sleeper '.

Der Build ist fehlgeschlagen, na ja, führen Sie den Build einfach erneut aus. - Anonymer Entwickler

19
Stuart

Abwarten und sehen

Ein Test, der einen Setup-Code ausführt und dann eine bestimmte Zeit warten muss, bevor er "sehen" kann, ob der zu testende Code wie erwartet funktioniert. Eine Testmethode, 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 Ereignis außerhalb des Systems generiert, z. B. eine E-Mail, eine http-Anforderung oder eine Datei auf die Festplatte schreibt.

Ein solcher Test kann auch ein Local Hero 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 zu verwechseln mit The Sleeper .

19
npellow

npassend geteiltes Gerät - Tim Ottinger
Mehrere Testfälle in der Testvorrichtung benötigen nicht einmal das Setup/Teardown. Teilweise aufgrund der Trägheit des Entwicklers, um eine neue Testvorrichtung zu erstellen. Einfacher ist es, einen weiteren Testfall zum Stapel hinzuzufügen

17
Gishu

Der Riese

Ein Komponententest, der, obwohl er das zu testende Objekt gültig testet, Tausende von Zeilen umfassen und viele, viele Testfälle enthalten kann. Dies kann ein Hinweis darauf sein, dass das getestete System ein Gott-Objekt (James Carrs Beitrag) ist.

Ein sicheres Zeichen für diesen Test ist ein Test, der mehr als ein paar Codezeilen umfasst. Oft ist der Test so kompliziert, dass er selbst Fehler oder Schuppen enthält.

16
Gishu

Ich werde es glauben, wenn ich einige blinkende GUIs sehe
Eine ungesunde Fixierung/Besessenheit beim Testen der App über ihre GUI "genau wie ein echter Benutzer"

Das Testen von Geschäftsregeln über die GUI ist eine schreckliche Form der Kopplung. Wenn Sie Tausende von Tests über die GUI schreiben und dann Ihre GUI ändern, brechen Tausende von Tests ab.
Testen Sie stattdessen nur GUI-Dinge über die GUI und koppeln Sie die GUI mit einem Dummy-System anstelle des realen Systems, wenn Sie diese Tests ausführen. Testen Sie Geschäftsregeln über eine API, an der die GUI nicht beteiligt ist. - Bob Martin

“Sie müssen verstehen, dass Sehen Glauben ist, aber auch wissen, dass Glauben Sehen ist.” - Denis Waitley

15
Gishu

Der Schläfer, alias Vesuv - Nick Pellow

Ein Test, der zu einem bestimmten Zeitpunkt und zu einem bestimmten Zeitpunkt in der Zukunft nicht bestanden werden soll. Dies wird häufig durch eine falsche Überprüfung der Grenzen beim Testen von Code verursacht, der ein Datums- oder Kalenderobjekt verwendet. Manchmal kann der Test fehlschlagen, wenn er zu einer bestimmten Tageszeit ausgeführt wird, beispielsweise um Mitternacht.

'The Sleeper' ist nicht mit dem ' Wait And See ' Anti-Pattern zu verwechseln.

Dieser Code wird lange vor dem Jahr 2000 ersetzt worden sein - Viele Entwickler im Jahr 1960

14
npellow

Der tote Baum

Ein Test, bei dem ein Stub erstellt wurde, der Test jedoch nicht geschrieben wurde.

Ich habe das tatsächlich in unserem Produktionscode gesehen:

class TD_SomeClass {
  public void testAdd() {
    assertEquals(1+1, 2);
  }
}

Ich weiß nicht einmal, was ich davon halten soll.

11
Reverend Gonzo

Der Kuckuck - Frank Carver
Ein Komponententest, der sich in einem Testfall mit mehreren anderen befindet und denselben (möglicherweise langwierigen) Einrichtungsvorgang wie die anderen Tests im Testfall ausführt, dann jedoch einige oder alle Artefakte aus dem Einrichtungs- und schafft seine eigenen.
Fortgeschrittenes Symptom von: nicht ordnungsgemäß freigegebenes Gerät

11
Gishu

habe heute davon gehört:

nasser Boden:
Der Test erstellt Daten, die irgendwo gespeichert bleiben, aber der Test wird nach Abschluss nicht bereinigt. Dies führt dazu, dass Tests (derselbe Test oder möglicherweise andere Tests) bei nachfolgenden Testläufen fehlschlagen.

In unserem Fall hat der Test eine Datei im Verzeichnis "temp" zurückgelassen, mit den Berechtigungen des Benutzers, der den Test zum ersten Mal ausgeführt hat. Wenn ein anderer Benutzer versucht hat, auf derselben Maschine zu testen: Ausleger. In den Kommentaren zu James Carrs Website hat Joakim Ohlrogge dies als "Sloppy Worker" bezeichnet und es war Teil der Inspiration für "Generous Leftovers". Ich mag meinen Namen besser (weniger beleidigend, vertrauter).

11
Zac Thompson

Der Vierzig-Fuß-Pole-Test

Aus Angst, der Klasse, die sie testen wollen, zu nahe zu kommen, werden diese Tests in einer Entfernung durchgeführt, die durch unzählige Abstraktionsebenen und Tausende von Codezeilen von der zu überprüfenden Logik getrennt ist. Als solche sind sie extrem spröde und anfällig für alle möglichen Nebenwirkungen, die auf der epischen Reise von und zu der Klasse von Interesse auftreten.

10
bhumphreys

Der Turing Test

Ein Testfall, der automatisch von einem teuren Tool generiert wird, das viele, viele Aussagen von der getesteten Klasse mithilfe einer allzu cleveren Analyse des Datenflusses gesammelt hat. Lullt die Entwickler in ein falsches Gefühl des Vertrauens, dass ihr Code gut getestet ist, und entbindet sie von der Verantwortung, 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).

10
bhumphreys

Der Umweltvandal

Ein 'Unit'-Test, der für verschiedene' Anforderungen 'in seine Umgebung gelangt, indem Umgebungsvariablen/-ports verwendet und festgelegt werden. Das gleichzeitige Ausführen von zwei dieser Tests führt zu Ausnahmen bezüglich nicht verfügbarer Ports usw.

Diese Tests werden zeitweise durchgeführt und lassen die Entwickler Dinge wie "einfach noch einmal ausführen" sagen.

Eine Lösung, die ich gesehen habe, ist die zufällige Auswahl einer zu verwendenden Portnummer. Dies verringert die Möglichkeit eines Konflikts, löst jedoch das Problem eindeutig nicht. Wenn Sie also die Möglichkeit haben, verspotten Sie den Code immer so, dass die nicht teilbare Ressource nicht zugewiesen wird.

10
gcrain

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 verlässt sich wirklich darauf, dass eine Ausnahme ausgelöst wird, und erwartet, dass das Testframework die Ausnahme erfasst und dem Benutzer als Fehler meldet.

[Test]
public void ShouldNotThrow()
{
   DoSomethingThatShouldNotThrowAnException();
}
10
Gishu

Doppelgänger

Um etwas zu testen, müssen Sie Teile des zu testenden Codes in eine neue Klasse mit demselben Namen und demselben Paket kopieren und Klassenpfadmagie oder einen benutzerdefinierten Klassenlader verwenden, um sicherzustellen, dass er zuerst sichtbar ist (damit Ihre Kopie ausgewählt wird) oben).

Dieses Muster weist auf eine ungesunde Menge versteckter Abhängigkeiten hin, die Sie mit einem Test nicht kontrollieren können.

Ich sah in sein Gesicht ... mein Gesicht! Es war wie ein Spiegel, aber mein Blut gefroren.

9
Aaron Digulla

Die Henne - Frank Carver
Ein gemeinsames Setup, das weit mehr leistet als die eigentlichen Testfälle. So können beispielsweise alle Arten von komplexen Datenstrukturen erstellt werden, die mit scheinbar wichtigen und eindeutigen Werten gefüllt sind, wenn die Tests nur das Vorhandensein oder Nichtvorhandensein von etwas bestätigen.
Fortgeschrittenes Symptom von: nicht ordnungsgemäß freigegebenes Gerät

Ich weiß nicht, was es tut ... Ich füge es trotzdem hinzu, nur für den Fall. - Anonymer Entwickler

7
Gishu

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 definitionem ein Alptraum sind, der aufrechterhalten werden muss.

7
thegreendroid

Line Hitter

Tests decken auf den ersten Blick alles ab, und Tools zur Codeabdeckung bestätigen dies zu 100%. In der Realität treffen Tests jedoch nur Code ohne Ausgabeanalysen.

Abdeckung-gegen-erreichbaren-Code

6

Die verbundenen Zwillinge

Tests, die von Personen als "Komponententests" bezeichnet werden, aber wirklich Integrationstests sind, da sie nicht von Abhängigkeiten isoliert sind (Dateikonfiguration, Datenbanken, Dienste, mit anderen Worten die Teile, die in Ihren Tests nicht getestet wurden, wurden faul und wurden nicht isoliert) und scheitern aufgrund von Abhängigkeiten, die gestubbt oder verspottet werden sollten.

0
PositiveGuy