Beim Korrigieren von Fehlern wird empfohlen, zunächst einen Test zu schreiben, der mit dem angegebenen Fehler fehlschlägt, und dann den Code zu korrigieren, bis der Test bestanden ist. Dies folgt TDD-Praktiken und soll eine gute Praxis sein, aber ich habe festgestellt, dass es dazu neigt, kryptische Tests zu erstellen, die der Implementierung sehr nahe kommen.
Zum Beispiel hatten wir ein Problem, als ein Auftrag gesendet wurde, einen bestimmten Status erreichte, abgebrochen und erneut versucht wurde. Um diesen Fehler zu reproduzieren, wurde ein umfangreicher Test geschrieben, der Thread-Synchronisation, viele Verspottungen und ähnliches enthielt. Es hat funktioniert, aber jetzt, da ich den Code überarbeite, finde ich es sehr verlockend, dieses Mammut einfach zu entfernen es würde wirklich (wieder) viel Arbeit erfordern, um zum neuen Design zu passen. Und es wird nur eine kleine Funktion in einem bestimmten Fall getestet.
Daher meine Frage: Wie prüft man auf Bugs, die sich nur schwer reproduzieren lassen? Wie vermeiden Sie es, Dinge zu erstellen, die die Implementierung testen und Refactoring und Lesbarkeit beeinträchtigen?
Antworten:
Ja, im Allgemeinen Sie sollten . Wie bei allen Richtlinien müssen Sie nach bestem Wissen vorgehen, wenn sie gegen andere Richtlinien verstoßen. In diesem Szenario muss der Schweregrad des Fehlers gegen die für die Implementierung des Tests erforderliche Arbeit abgewogen werden, und die Qualität dieses Tests muss auf das Geschäftsproblem ausgerichtet sein und es muss eine Regression des Fehlerzustands festgestellt werden.
Ich würde eher das Schreiben von Tests als das Nichtschreiben von Tests bevorzugen, da Unterbrechungen, die zu Fehlern führen, in der Regel mehr Aufwand verursachen, als nur einen Komponententest zu entwickeln und aufrechtzuerhalten.
quelle
Ich denke, die beste Vorgehensweise - eine, der ich peinlich zugeben muss, dass ich sie nicht oft folge - besteht darin, einen System- oder Integrationstest zu erstellen, der das in der Produktion festgestellte Problem demonstriert, und dann nach den für das Problem verantwortlichen Einheiten zu suchen. und schreiben Sie dann Unit-Tests für die Units, die das Problem auf Unit-Ebene demonstrieren . Sobald Sie die Einheitentests durchgeführt haben, korrigieren Sie die Einheiten und führen Sie alle Tests durch. Zu diesem Zeitpunkt kann es ratsam sein, den ursprünglichen Test zu verwerfen, da er möglicherweise zerbrechlich und / oder langsam ist. Bewahren Sie die Komponententests jedoch aus Gründen der Regression und der Abdeckung in Ihrer automatisierten Suite auf.
quelle
Das Schreiben eines Tests zur Feststellung des Fehlers ist eine gute Idee, da Sie damit genau ermitteln können, welche Schritte erforderlich sind, um den Fehler zu reproduzieren, und überprüfen, ob er behoben wurde. Darüber hinaus können diese Tests als Teil von Rauch- oder Regressionstests durchgeführt werden, um sicherzustellen, dass spätere Änderungen keinen alten Fehler in das System zurückgeführt haben.
Das erste, was zu berücksichtigen ist, ist das Niveau des erforderlichen Tests. Möglicherweise ist der Test zur Überprüfung des Fixes auf Systemebene besser geeignet, oder es kann sogar ein manueller Abnahmetest durchgeführt werden. Ich denke, es ist wichtiger, einen Test zu haben, der dokumentiert und verwaltet wird, unabhängig davon, wie er speziell implementiert wurde.
Inwieweit sich Refactoring auf Tests auswirkt, hängt von den spezifischen Merkmalen ab. In einigen Fällen kann eine Umgestaltung (oder irgendeine Art von Arbeit, wie z. B. neue Funktionen) dazu führen, dass die Tests nicht mehr erforderlich sind. Das ursprünglich aufgetretene Problem ist möglicherweise nicht mehr möglich. In diesem Fall ist es möglicherweise ratsam, den Test aus den möglichen Tests zu entfernen, um Ihren Testprozess (automatisiert oder manuell) schlanker zu gestalten. In anderen Fällen gibt es mehrere Methoden zum Durchführen des Tests und das Überprüfen der Funktion auf einer anderen Ebene ist möglicherweise geeigneter. Wenn das Merkmal geringfügig ist, ist der Test möglicherweise überhaupt nicht mehr erforderlich.
Sie können sich auch darauf verlassen, nicht nur zu testen, sondern auch zu protokollieren. Beispiel: Erfassen von Informationen zur Laufzeit (mit je nach Umgebung unterschiedlicher Ausführlichkeit - ausführlicher während des Testens, weniger ausführlich während der Bereitstellung), Erstellen von Profilen für die Anwendung, Erfassen von Speicherauszügen des aktuellen Systemzustands. Wenn Sie gemeinsame Auslöser für das Problem finden, können Sie diese als Leitfaden für Tests auf allen Ebenen verwenden.
quelle
Ja du solltest.
Schreiben Sie Komponententests für die vorhandene Codebasis. Wenn Sie einen Fehler beheben, müssen Sie sicherstellen, dass Ihr Komponententest fehlschlägt. Dies gibt Ihnen die Gewissheit, dass Sie tatsächlich an einem Fehler arbeiten. Anschließend müssen Sie den Test neu faktorisieren und bestehen, indem Sie den Fehler beheben.
Dies ist jedoch keine TDD-Praxis. In TDD-Tests fahren Sie Ihr Design, aber in Ihrem Fall wurde das Design bereits entschieden.
quelle