Sollte es Komponententests für komplexe reguläre Ausdrücke geben?

34

Soll ich in meiner Anwendung Komponententests für komplexe reguläre Ausdrücke schreiben?

  • Einerseits: Sie sind einfach zu testen, da das Eingabe- und Ausgabeformat oft einfach und genau definiert ist und sie oft so komplex werden können, dass Tests von ihnen besonders wertvoll sind.
  • Auf der anderen Seite: Sie selbst sind selten Teil der Schnittstelle einer Einheit. Es ist möglicherweise besser, die Schnittstelle nur zu testen und dies auf eine Weise zu tun, die implizit die regulären Ausdrücke testet.

BEARBEITEN:

Ich stimme Doc Brown zu, der in seinem Kommentar feststellt, dass dies ein Sonderfall für das Testen interner Komponenten ist .

Als interne Komponenten haben reguläre Ausdrücke jedoch einige Besonderheiten:

  1. Ein einzeiliger regulärer Ausdruck kann sehr komplex sein, ohne wirklich ein separates Modul zu sein.
  2. Wandelt die Eingabe in die Ausgabe um, ohne dass Nebenwirkungen auftreten, und ist daher sehr einfach separat zu testen.
Lii
quelle
12
"Sie selbst sind selten Teil der Schnittstelle einer Einheit." - Wenn Ihre Klassen interessanten Code haben, der tief unter der Oberfläche verborgen ist, teilen Sie Ihre Klassen auf. Dies ist ein Beispiel dafür, wie das Nachdenken über Tess das Design verbessern kann.
Nathan Cooper
3
Allgemeiner gesagt die gleiche Frage: Welche internen Komponenten sollten einem Komponententest unterzogen werden? Siehe programmers.stackexchange.com/questions/16732/…
Doc Brown
Sorta bezogen, siehe Regex101. Sie haben einen Abschnitt zum Schreiben von Komponententests für Ihren Regex. Zum Beispiel: regex101.com/r/tR3mJ2/2
David sagt Reinstate Monica
3
Haftungsausschluss - dieser Kommentar ist meiner bescheidenen Meinung nach: 1 Zunächst einmal glaube ich, dass die komplexen regulären Ausdrücke rein böse sind - siehe auch blog.codinghorror.com/… 2 Der wahre Wert des Testens solcher Ausdrücke entsteht, wenn Sie sie über eine große Datenbank von real testen data blog.codinghorror.com/testing-with-the-force 3 Ich habe das seltsame Gefühl, dass diese Tests nicht genau Unit- Tests sind
Boris Treukhov

Antworten:

101

Abgesehen von der Prüfung des Dogmatismus ist die eigentliche Frage, ob er für den Komponententest komplexer regulärer Ausdrücke von Nutzen ist. Es scheint ziemlich klar zu sein, dass es einen Wert liefert (unabhängig davon, ob der reguläre Ausdruck Teil einer öffentlichen Schnittstelle ist), wenn der reguläre Ausdruck komplex genug ist, da es Ihnen ermöglicht, Fehler zu finden und zu reproduzieren und Regressionen vorzubeugen.

JacquesB
quelle
25
1, obwohl , wenn ein regulärer Ausdruck komplex genug ist , dass dies ein Problem ist, dann ist es sinn wahrscheinlich macht es zu einer „Wrapper“ Einheit zu bewegen mit geeigneten Methoden ( isValid, parse, tryParse, oder Dingsbums, genau je nachdem , wie es verwendet wird), so dass der Client-Code nicht wissen muss, dass er aktuell mit einem regulären Ausdruck implementiert ist. Die Wrapper-Einheit hätte dann detaillierte Tests, die wiederum die aktuelle Implementierung nicht kennen müssten. Diese Tests testen de facto den regulären Ausdruck, jedoch auf implementierungsunabhängige Weise.
Ruakh
1
Ein reg ex ist ein Programm, allerdings in einer speziellen und sehr knappen Sprache. Daher ist das Testen für nicht-triviale Ausdrücke geeignet ... Und sicherlich sollte der Code, der den Ausdruck aufruft, getestet werden, was implizit das reservierte testen kann.
Keshlam
6
@ruakh Gut gesagt. Der Vorteil einer Wrapper-Klasse für einen regulären Ausdruck besteht darin, dass Sie ihn bei Bedarf problemlos durch normalen Code ersetzen können. Code mit komplexer Eingabe / Ausgabe sollte immer Unit-Tests haben, da es bemerkenswert schwierig ist, ohne zu debuggen. Wenn Sie sich auf die Dokumentation beziehen müssen, um die Auswirkungen des Codes zu verstehen, sollten Unit-Tests durchgeführt werden. Wenn es sich nur um eine schnelle 1: 1-Zuordnung wie die Typkonvertierung handelt, ist dies kein Problem. Regexes schaffen es sehr schnell, Dokumente zu benötigen.
Aaron3468
4
@Lii: Regexes verdient keine besondere Behandlung. Der reguläre Ausdruck ist in diesem Fall die Einheit, also testen wir ihn.
JacquesB
1
@ruakh Ich wollte gerade eine Antwort darauf schreiben. Ich bin damit einverstanden, dass die Verwendung von Regex ein Implementierungsdetail ist. Was zählt, ist, dass die Dinge validieren, wann sie sollen, und nicht validieren, wann sie sollen. Testen Sie die FooValidatorauf ihre Ein- und Ausgänge, dann haben Sie keine Bedenken, wie es gemacht wird. ++
RubberDuck
21

Regex kann ein mächtiges Werkzeug sein, aber es ist kein Werkzeug, dem Sie vertrauen können, wenn Sie auch nur geringfügige Änderungen an komplexen regulären Ausdrücken vornehmen.

Erstellen Sie also viele Tests, die die Fälle dokumentieren, die abgedeckt werden sollen. Und erstellen Sie viele Tests, die Fälle dokumentieren, in denen ein Fehler auftreten sollte, wenn er zur Validierung verwendet wird.

Wann immer Sie Ihre regulären Ausdrücke ändern müssen, fügen Sie die neuen Fälle als Tests hinzu, ändern Sie Ihre regulären Ausdrücke und hoffen Sie auf das Beste.

Wenn ich in einer Organisation wäre, die im Allgemeinen keine Komponententests verwendet, würde ich trotzdem ein Testprogramm schreiben, das alle von uns verwendeten regulären Ausdrücke testet. Ich würde es sogar in meiner eigenen Zeit tun, wenn ich müsste, meine Haare brauchen keine Farbe mehr zu verlieren.

Gebogen
quelle
3

Reguläre Ausdrücke sind Code zusammen mit dem Rest Ihrer Anwendung. Sie sollten testen, ob der Code insgesamt das tut, was Sie von ihm erwarten. Dies hat mehrere Zwecke:

  • Test sind ausführbare Dokumentation. Es zeigt deutlich, wozu Sie den Code benötigen. Wenn es getestet wird, ist es wichtig.
  • Zukünftige Betreuer können sicher sein, dass die Tests sicherstellen, dass das Verhalten unverändert bleibt, wenn sie es ändern.

Da es eine zusätzliche Hürde gibt, Code in einer anderen Sprache in den Rest einzubetten, sollten Sie höchstwahrscheinlich diese zusätzliche Aufmerksamkeit zum Wohle der Wartung verwenden.

Thorbjørn Ravn Andersen
quelle
1

Kurz gesagt, sollten Sie Ihre Anwendung testen. Ob Sie Ihren regulären Ausdruck mit automatisierten Tests testen, die ihn einzeln ausführen, als Teil einer größeren Blackbox oder wenn Sie nur von Hand damit herumspielen, spielt für Sie eine untergeordnete Rolle, um sicherzustellen, dass er funktioniert.

Der Hauptvorteil von Unit-Tests ist, dass sie Zeit sparen. Sie können das Ding jetzt oder zu einem späteren Zeitpunkt so oft testen, wie Sie möchten. Wenn es irgendeinen Grund gibt zu glauben, dass Ihr Regex zu irgendeinem Zeitpunkt überarbeitet, optimiert, eingeschränkt usw. wird, dann wollen Sie wahrscheinlich einige Regressionstests dafür, oder wenn Sie es ändern, müssen Sie gehen durch eine Stunde des Denkens durch alle Randfälle, damit Sie es nicht brechen. Das, oder du lernst damit zu leben, Angst vor deinem Code zu haben und änderst ihn einfach nie.

Sara
quelle
3
Eine Faustregel, die ich erkannt habe; Wenn ich Dokumente zum Schreiben und Überprüfen des Codes benötige, benötige ich einen Komponententest. Sie haben mir viele Kopfschmerzen erspart, null Zeiger, keine Typen und falsche Ausgaben abgefangen. Sie geben dem Endbenutzer auch die Möglichkeit, Ihren Code mit minimalem Aufwand nach Maß zu reparieren, wenn er unvermeidlich kaputt geht.
Aaron3468
-1

Auf der anderen Seite: Sie selbst sind selten Teil der Schnittstelle einer Einheit. Es ist möglicherweise besser, die Schnittstelle nur zu testen und dies auf eine Weise zu tun, die implizit die regulären Ausdrücke testet.

Ich denke damit hast du es selbst beantwortet. Regexes in einer Unit sind höchstwahrscheinlich ein Implementierungsdetail.

Was zum Testen Ihres SQL-Codes gehört, gilt wahrscheinlich auch für reguläre Ausdrücke. Wenn Sie ein Stück SQL ändern, führen Sie es wahrscheinlich manuell über einen SQL-Client aus, um festzustellen, ob das Ergebnis Ihren Erwartungen entspricht. Das gleiche gilt, wenn ich einen regulären Ausdruck ändere. Ich verwende ein reguläres Ausdruck-Tool mit einigen Eingabebeispielen, um festzustellen, ob es das tut, was ich erwarte.

Was ich nützlich finde, ist ein Kommentar in der Nähe des regulären Ausdrucks mit einer Textprobe, mit der er übereinstimmen sollte.

Christiaan
quelle
Wenn Sie ein Stück SQL ändern, führen Sie es wahrscheinlich von Hand durch einen SQL-Client, um zu sehen, ob es das ergibt, was Sie erwarten. “ Aber diese Art beantwortet die Frage auf die andere Weise ... Wenn ich es brauche oder für nützlich halte Testen Sie die regulären Ausdrücke von Hand, dann sollte ich stattdessen einen Einheitentest durchführen. Genau das macht es schwierig, sich zu entscheiden!
Lii
Es kommt wirklich darauf an. Was Sie für Ihre Unit-Tests wollen, ist die Fähigkeit, Änderungen vorzunehmen. Wie oft ändern Sie einen bestimmten regulären Ausdruck? Wenn die Antwort oft ist, dann erstellen Sie auf jeden Fall einen Test dafür.
Christiaan
8
Wenn alle anderen Dinge gleich sind, ist es besser, einen automatisierten Test zu haben als einen "Test von Hand".
Robert Harvey
1
Warum sollten Sie einen regulären Ausdruck nicht mithilfe von Automatisierung testen?
Tony Ennis
1
Es ist Teil einer Methode und alles, was ich sagen wollte, ist, dass es nicht notwendig ist, den regulären Ausdruck spezifisch zu testen, wenn Sie diese Methode bereits testen. In diesem Fall ist es wahrscheinlich besser, den regulären Ausdruck in eine separate Funktion zu extrahieren, die Sie isoliert testen.
Christiaan
-5

Wenn Sie fragen müssen, ist die Antwort ja.

Angenommen, es kommt etwas FNG und er glaubt, dass er Ihren regulären Ausdruck "verbessern" kann. Jetzt ist er ein FNG, also automatisch ein Idiot. Genau die Person, die unter keinen Umständen Ihren wertvollen Code berühren sollte! Aber vielleicht hat er etwas mit dem PHB zu tun, also können Sie nichts tun.

Es sei denn, Sie wissen, dass der PHB Sie dazu bringt, auf dieses Projekt zu treten und zurückzuschreien, um "dem Kerl vielleicht ein paar Hinweise zu geben, wie Sie dieses Durcheinander verursacht haben", wenn alles schlecht wird. So schreiben Sie alle Fälle auf, die Sie beim Aufbau Ihres wunderschönen Meisterwerks der Ausdruckskraft sorgfältig erwogen haben .

Und da Sie sie alle aufgeschrieben haben, sind Sie zu zwei Dritteln in der Lage, eine Reihe von Testfällen zu erstellen, denn - seien wir ehrlich - Regex-Testfälle sind nach dem Erstellen des Frameworks kinderleicht auszuführen.

Jetzt haben Sie eine Reihe von Randbedingungen, Alternativen und erwarteten Ergebnissen. Und plötzlich sind die Testfälle die Dokumentation, so wie sie in all diesen me-too Agile-Blogposts versprochen wurde. Sie weisen den FNG nur darauf hin, dass es keine große Verbesserung darstellt, wenn seine "Verbesserung" die vorhandenen Testfälle nicht besteht, oder? Und wo sind seine vorgeschlagenen neuen Testfälle, die ein Problem mit dem ursprünglichen Code aufzeigen, den er, da er funktioniert, niemals ändern muss !!!

Austin Hastings
quelle
3
Was ist FNG? Dies scheint mir keine schlechte Antwort zu sein, aber es fehlt eine Definition für FNG (googlin liefert nur Ergebnisse, die nichts damit zu tun haben, also wurde diese Antwort vielleicht nur wegen FNG
herabgestuft
1
Ich vermute, dass Google Sie an den richtigen Ort gebracht hat. ;-) ( en.wikipedia.org/wiki/FNG_syndrome )
Austin Hastings
Wenn Sie kein absolutes Programmiergenie sind, wird es mehr erfahrene Programmierer geben, die bedenken, was Sie tun, wenn Sie den Neuen anschauen. Vielleicht möchten Sie demütiger sein.
Thorbjørn Ravn Andersen