Welchen Wert hat das Einchecken in nicht bestandenen Komponententests?

13

Es gibt zwar Möglichkeiten, die Ausführung von Komponententests zu verhindern, aber welchen Wert hat die Überprüfung fehlgeschlagener Komponententests?

Ich werde ein einfaches Beispiel verwenden: Groß- und Kleinschreibung. Der aktuelle Code unterscheidet zwischen Groß- und Kleinschreibung. Eine gültige Eingabe in die Methode ist "Cat" und würde eine Enumeration von Animal.Cat zurückgeben. Die gewünschte Funktionalität der Methode sollte jedoch nicht zwischen Groß- und Kleinschreibung unterscheiden. Wenn also die beschriebene Methode "cat" bestanden würde, könnte sie möglicherweise so etwas wie Animal.Null anstelle von Animal.Cat zurückgeben, und der Unit-Test würde fehlschlagen. Zwar würde eine einfache Codeänderung dazu führen, dass dies funktioniert, ein komplexeres Problem kann jedoch Wochen dauern, aber die Identifizierung des Fehlers mit einem Komponententest könnte eine weniger komplexe Aufgabe sein.

Die Anwendung, die derzeit analysiert wird, verfügt über 4 Jahre Code, der "funktioniert". Jüngste Diskussionen zu Komponententests haben jedoch Mängel im Code ergeben. Einige benötigen lediglich eine explizite Implementierungsdokumentation (z. B. Groß- / Kleinschreibung beachten oder nicht beachten) oder Code, der den Fehler basierend auf dem aktuellen Aufruf nicht ausführt. Es können jedoch Komponententests erstellt werden, die bestimmte Szenarien ausführen, in denen der Fehler angezeigt wird und gültige Eingaben sind.

Welchen Wert hat das Einchecken von Komponententests, die den Fehler beheben, bis jemand den Code korrigieren kann?

Sollte dieser Komponententest mit Ignorieren, Priorität, Kategorie usw. gekennzeichnet werden, um zu bestimmen, ob ein Build auf der Grundlage der ausgeführten Tests erfolgreich war? Schließlich sollte der Komponententest erstellt werden, um den Code auszuführen, sobald er behoben wurde.

Einerseits zeigt es, dass identifizierte Fehler nicht behoben wurden. Auf der anderen Seite könnten Hunderte von fehlgeschlagenen Komponententests in den Protokollen auftauchen und diejenigen aussortieren, die aufgrund eines Code-Check-ins fehlschlagen oder ausfallen sollten.

Jim G.
quelle
Das ist eine Möglichkeit, diese Testabdeckungszahlen zu erhöhen.
JeffO
Wenn Sie sich bereits bemüht haben, den Komponententest zu schreiben, warum sollten Sie ihn dann umschreiben müssen, wenn Sie sich entscheiden, das Problem zu beheben? Nur weil es eingecheckt ist, heißt das nicht, dass es in der Suite ausgeführt werden muss. (Sie können eine Kategorie für "Bekannte Probleme" erstellen und diese Tests als Rückstand / TODO-Liste behandeln.)
Caleb,

Antworten:

17

Ich mag es nicht, wenn kaputte Unittests eingecheckt werden, weil sie unnötigen Lärm verursachen. Nach jedem unittest müsste ich alle fehlgeschlagenen Probleme überprüfen (rot). Ist es rot, weil es ein neues Problem gibt oder weil es ein altes offenes gibt, um es zu tun / zu beheben. Dies ist nicht in Ordnung, wenn es mehr als 20 Unittests gibt.

Stattdessen benutze ich

  • [Ignore("Reason")]Attribut, das das Ergebnis gelb oder gelb macht
  • throw new NotImplementedException()das macht das Ergebnis grau

Hinweis: Ich verwende NUnit für .net. Ich bin mir nicht sicher, ob die "graue" Funktion in anderen unittesten Frameworks vorhanden ist.

Ich mag die folgende Bedeutung von Unit-Testergebnissen.

  • grün: alles fertig
  • grau: Geplante neue Funktionen, die mit niedriger Priorität ausgeführt werden müssen
  • gelb: Fehler sind noch nicht behoben. Sollte bald behoben sein
  • rot: neue Bugs. Sollte sofort behoben werden

Alles außer "rot" kann eingecheckt werden.

Um die Frage zu beantworten: Das Einchecken von "rot-nicht bestanden-Test" ist schädlicher als der Wert, aber das Einchecken von "gelb-ignoriert-Test" oder "grau-nicht implementiert-Test" kann als ToDo-Liste nützlich sein.

k3b
quelle
Das Problem, das ich bei diesem Ansatz sehe, ist, dass die ignorierten Tests wahrscheinlich nie behoben werden. Sie könnten auch einfach den gesamten Testcode entfernen, was wäre der Unterschied (ich bin hier ein bisschen übermütig)
Lovis
4
will probably never be fixedist eine politische Entscheidung, ob Sie für automatisierte Tests Geld ausgeben möchten oder nicht. Mit "Ignorierte Tests" haben Sie die Möglichkeit, diese zu beheben. "Ignorierte Tests
wegwerfen
8

Ich werde nicht so tun, als wäre dies Industriestandard, aber ich überprüfe unterbrochene Tests, um mich oder meine anderen Projektmitglieder daran zu erinnern, dass es immer noch ein Problem mit dem Code oder dem Komponententest selbst gibt.

Ich nehme an, Sie sollten berücksichtigen, ob Ihre Entwicklungsrichtlinien fehlgeschlagene Tests ohne Nachteile zulassen. Ich habe einen Freund, der in einem Geschäft arbeitet, das testgetriebene Entwicklung betreibt, daher beginnen sie immer mit nicht bestandenen Tests ...

Tieson T.
quelle
5
Sie sollten jedoch niemals einen fehlgeschlagenen Test einchecken, da Ihr Build-Server kein Projekt mit einem fehlerhaften Test erstellen sollte.
CaffGeek
@Chad: Erstellen und Testen sind zwei separate Teile eines automatisierten Schritts. Bauen sorgt dafür, dass alles kompiliert wird. Test stellt sicher, dass das Ergebnis des Builds gültig ist. Meine Interpretation der Frage lautete nicht: "Soll ich Code einchecken, der nicht kompiliert werden kann?" Stattdessen lautete es: "Soll ich einen Test einchecken, von dem ich weiß, dass er fehlschlägt?"
Unholysampler
1
Ich habe nur einen Punkt hinzugefügt, den ich berücksichtigen sollte: Einige Continuous Integration Build-Server führen die Tests aus, und wenn sie fehlschlagen, werden sie nicht bereitgestellt. Zu Recht schlägt der Code fehl, als ob der Build fehlschlagen würde, und es macht keinen Sinn, ein Produkt bereitzustellen, von dem bekannt ist, dass es fehlerhaft ist.
CaffGeek
@Chad: Richtig, ich habe CI-Server total vergessen. Das wäre auf jeden Fall ein Punkt zu prüfen. Es lohnt sich auch zu klären, was wir unter "kaputten" Tests verstehen. handelt es sich lediglich um "schlechte" Tests, oder schlägt der Test fehl, weil sich die API auf irgendeine Weise geändert hat?
Tieson T.
Die Frage hätte klarer sein sollen. Es sollte das sein. Der Test wird kompiliert, aber das erwartete Ergebnis wird fehlschlagen.
6

Fehlgeschlagene Komponententests geben dem Entwicklungsteam Einblick in die Maßnahmen, die zur Einhaltung der vereinbarten Spezifikationen erforderlich sind.

Kurz gesagt, die fehlgeschlagenen Unit Tests geben dem Team eine "TODO" -Liste.

Aus diesem Grund sind nicht bestandene Komponententests weitaus besser als gar keine Komponententests. *
Das Fehlen von Komponententests lässt das Entwicklerteam im Dunkeln. Spezifikationen müssen wiederholt manuell bestätigt werden .

[* Vorausgesetzt, die Unit-Tests testen tatsächlich etwas Nützliches.]

Jim G.
quelle
2
Es gibt bessere Möglichkeiten, eine Aufgabenliste zu verwalten, z. B. ein Whiteboard, eine Aufgabenlisten-App oder ein Problemverfolgungssystem. Es ist viel einfacher, eine Testsuite zu verwenden, wenn Sie davon ausgehen, dass sie immer vollständig bestanden wird, und jeder aufgetretene Testfehler ist ein neues Problem, das sofort behoben werden muss.
BDSL
6

Der Zweck von Unit-Tests besteht darin, das erwartete Verhalten eines Systems zu bestätigen und keine Mängel zu dokumentieren. Wenn wir Unit-Tests verwenden, um Fehler zu dokumentieren, wird deren Nützlichkeit für die Behauptung des erwarteten Verhaltens verringert. Die Antwort auf die Frage "Warum ist dieser Test fehlgeschlagen?" ist kein einfaches "Oh, etwas ist kaputt, was ich nicht erwartet hätte kaputt zu sein." Es ist nicht bekannt, ob der Testfehler erwartet oder unerwartet ist.

Hier ist ein Absatz vom Anfang von Kapitel 13 von Effektiv mit Legacy-Code arbeiten :

Automatisierte Komponententests sind ein sehr wichtiges Werkzeug, aber nicht für die Fehlersuche - zumindest nicht direkt. Im Allgemeinen sollten automatisierte Tests ein Ziel festlegen, das wir erreichen möchten, oder versuchen, das bereits vorhandene Verhalten beizubehalten. Im natürlichen Fluss der Entwicklung werden Tests, die spezifizieren, zu Tests, die erhalten bleiben . Sie werden Fehler finden, aber normalerweise nicht beim ersten Ausführen eines Tests. Sie finden Fehler in späteren Läufen, wenn Sie das Verhalten ändern, mit dem Sie nicht gerechnet haben.

Matthew Rodatus
quelle
3

Aber die defekten, die Fehler in einem neuen Projekt identifizieren, werden als solche bezeichnet. Auf diese Weise können Sie sehen, dass sie brechen MÜSSEN ... Während sie repariert werden, werden sie grün und in die normale Testsuite verschoben.

ANMERKUNG: Dieses Projekt muss so eingestellt werden, dass es nicht auf dem Build-Server erstellt wird, wenn Ihr Build-Server das Einchecken verhindert, das den Build unterbricht (vorausgesetzt, Sie definieren einen fehlerhaften Build als einen, bei dem nicht alle Tests bestanden werden).

CaffGeek
quelle
+1 obwohl es keine Antwort gibt, ob man einchecken soll oder nicht, gibt es ein wichtiges Argument: build server
k3b
Ich würde lieber ein Attribut verwenden, um einen solchen Test zu markieren, anstatt ihn in ein separates Projekt zu verschieben.
CodesInChaos
2

Unit-Tests sollten zusätzlich zu Erfolgsfällen einer Funktion auf Fehlerfälle testen. Eine Funktion sollte falsche Eingaben explizit ablehnen oder über eine Dokumentation verfügen, in der erläutert wird, welche Eingaben als gültig angesehen werden.

Wenn Sie eine Funktion haben, die keine dieser Funktionen ausführt, handelt es sich um einen Fehler, und Sie sollten eine Möglichkeit haben, die Existenz dieser Funktion aufzuzeichnen. Das Erstellen eines Komponententests, der dieses Problem demonstriert, ist eine Möglichkeit, dies zu tun. Das Einreichen eines Bug-Tickets ist eine weitere Option.

Der Punkt des Unit-Tests ist, nicht zu 100% erfolgreich zu sein, sondern Fehler im Code zu finden und zu beheben. Keine Tests durchzuführen ist ein einfacher Weg, um 100% Erfolg zu haben, aber das ist für das Projekt nicht sehr vorteilhaft.

unholysampler
quelle
Woah ... "Der Sinn von Unit-Tests ist es, nicht zu 100% erfolgreich zu sein", sagen Sie, dass sie nicht alle bestehen müssen?
CaffGeek
2
@Chad: Der Punkt ist, dass es besser ist, Tests zu haben, von denen Sie wissen, dass sie fehlschlagen, aber ein echtes Problem aufzeigen, anstatt den Test nicht zu haben, nur damit Sie das grüne Häkchen am Ende des nächtlichen Builds / Tests haben können.
Unholysampler
8
@unholysampler, habe niemals unterbrochene Tests, es sei denn, sie sind CLEARLY als "Sollte" gekennzeichnet (da sie in einem anderen Projekt sind). Andernfalls werden sie zu Geräuschen, und Sie wissen nicht, wann ein Test, der bestanden werden soll, unterbrochen wurde. Es hat den Zweck der kontinuierlichen Integration und der Durchführung von UnitTests
CaffGeek
2
@Chad: Ich denke, dies führt zur Semantik von Definitionen. Basierend auf dem OP hörte es sich an, als würde er über die Erstellung eines gültigen Tests sprechen, der einen Fehler auslöst. Der Fehler hat jedoch eine niedrige Priorität und wird wahrscheinlich nicht sofort behoben. Sie haben Continuous Integration ins Leben gerufen, was den automatisierten Prozess erheblich strenger einschränkt.
Unholysampler
4
@unholysampler, CI oder kein CI: Wenn Sie die Tests ausführen und daran gewöhnt sind, einige rote Ampeln zu sehen, gewöhnen Sie sich daran. Also, wenn etwas, das grün war, rot wird ... woher weißt du das?!? Es ist eine schreckliche Praxis und einer der Gründe, warum Tests in so vielen Organisationen nicht akzeptiert werden.
CaffGeek
1

Reichen Sie für jeden Fehler einen Fehler ein und notieren Sie dies im Testergebnis. Wenn Sie sich dann jemals zusammensetzen und den Fehler beheben, besteht Ihr Test und Sie löschen ihn aus dem Testergebnis. Ignoriere niemals nur Probleme.

SnoopDougieDoug
quelle
-3

Wie ich TDD beim Implementieren von Tests für einen unfertigen Code sehe, schreiben Sie zuerst Tests mit dem Attribut [ExpectedException] oder ähnlichem. Dies sollte zunächst passieren, da der unvollständige Code keine Logik enthält und einen neuen Exception () - Code enthält. Obwohl eine durchgehende Ausnahme falsch ist, würde dies zumindest dazu führen, dass die Tests anfänglich bestanden und für das Einchecken geeignet sind. Wir können einen ignorierten Test vergessen, aber den unvollständigen Code definitiv aufräumen oder ausfüllen. Wenn wir dies tun, schlägt der entsprechende Test, der eine Aufforderung erwartete, automatisch fehl und Sie werden alarmiert, dies zu beheben. Dies kann eine geringfügige Änderung des Tests beinhalten, um ExpectException zu entfernen und stattdessen echte Asserts durchzuführen. CI, Dev, Tester und Kunden alle glücklich und eine Win-Win-Situation?

user211764
quelle
1
Dies beantwortet keine Frage. Es wird nicht gefragt, was TDD ist und warum auf erwartete Ausnahmen geprüft wird.
Andy Wiesendanger