___ qstnhdr ___ Verwendung von Zufälligkeit und / oder Iterationen in Unit-Tests?
___ answer786678 ___
Ich habe Zufälligkeit in meinen Testfällen verwendet. Es fand mich einige Fehler im SUT und es gab mir einige Fehler in meinem Testfall.
Beachten Sie, dass der Testfall durch Verwendung von Zufallszahlen komplexer wird.
- Sie benötigen eine Methode, um Ihren Testfall mit den zufälligen Werten auszuführen, die auf
fehlgeschlagen sind
- Sie müssen die Zufallswerte für jeden Test protokollieren.
- ...
Alles in allem schwimme ich wieder mit der Zufälligkeit, aber nicht enthaltsam. Wie bei jeder Technik hat es seine Werte.
Um besser zu verstehen, wonach Sie suchen, schlagen Sie den Begriff fuzzing
nach
___ qstntxt ___
In Komponententests habe ich mich daran gewöhnt, Methoden zu testen, die einige reguläre Werte verwenden, einige Werte, die den Methodenvertrag verletzen, und alle Grenzfälle, die mir einfließen.
Aber ist es sehr schlecht zu
üben
- Test auf zufällige Werte, dies ist ein Wert in einem Bereich, von dem Sie denken, dass er niemals Probleme bereiten sollte, so dass jedes Mal, wenn der Test ausgeführt wird, ein anderer Wert übergeben wird? Als eine Art ausgiebiges Testen der regulären Werte?
- Test auf ganze Bereiche, mit Iteration?
Ich habe das Gefühl, dass beide Ansätze nicht gut sind. Mit Range-Testing kann ich mir vorstellen, dass es einfach nicht praktikabel ist, da es Zeit braucht, aber mit Zufälligkeit?
UPDATE:
Ich benutze diese Technik nicht selbst, habe mich nur gefragt. Zufälligkeit kann ein gutes Werkzeug sein, ich weiß jetzt, ob du es reproduzierbar machen kannst, wenn du es brauchst.
Die interessanteste Antwort war der 'fuzzing' Tipp von Lieven:
Ссылка
tx
___ answer781111 ___
Unit Tests müssen schnell sein. Wenn sie nicht sind, werden sie nicht regelmäßig laufen. Manchmal habe ich Code für die Überprüfung des gesamten Bereichs programmiert, aber @ Ignore hat es am Ende auskommentiert, weil es die Tests zu langsam gemacht hat. Wenn ich zufällige Werte verwenden würde, würde ich für einen PRNG mit festen Seeds gehen, so dass jeder Lauf tatsächlich die gleichen Zahlen überprüft.
___ answer782107 ___
Was testen Sie? Der Zufallsgenerator? Oder dein Code?
Wenn Ihr Code, wenn es einen Fehler im Code gibt, der Zufallszahlen erzeugt?
Was ist, wenn Sie ein Problem reproduzieren müssen? Starten Sie den Test immer wieder in der Hoffnung, dass er die gleiche Sequenz wie bei der Entdeckung des Problems verwendet?
Wenn Sie sich entscheiden, einen Zufallszahlengenerator zu verwenden, um Daten zu erzeugen, müssen Sie ihn zumindest mit einem bekannten konstanten Wert säen, damit er leicht reproduziert werden kann.
Mit anderen Worten, Ihre "Zufallszahlen" sind nur eine "Folge von Zahlen, um die es mir wirklich nicht so geht".
___ answer781112 ___
Solange es Ihnen auf irgendeine Weise sagen wird, welchen zufälligen Wert es scheiterte, nehme ich nicht an, dass es so schlimm ist. Sie sind jedoch fast auf Glück angewiesen, um dann ein Problem in Ihrer Anwendung zu finden.
Wenn Sie den gesamten Bereich testen, wird sichergestellt, dass Sie alle Möglichkeiten abdecken, aber es scheint übertrieben zu sein, wenn Sie die Kanten abgedeckt haben und, wie ich annehme, ein paar akzeptable Mittelwerte.
___ answer781838 ___
Ich habe Zufälligkeit für das Debuggen eines Feldproblems mit einer Zustandsmaschine verwendet, die eine Ressource leckt. Wir haben den Code geprüft, die Unit-Tests durchgeführt und konnten das Leck nicht reproduzieren.
Wir haben zufällige Ereignisse aus dem gesamten möglichen Ereignisraum in die Testumgebung der State-Machine-Unit eingespeist. Wir haben nach jedem Ereignis die Invarianten betrachtet und bei Verstößen gestoppt.
Die zufälligen Ereignisse enthüllten schließlich eine Folge von Ereignissen, die ein Leck hervorriefen.
Die Zustandsmaschine hat eine Ressource freigegeben, als ein 2. Fehler während der Wiederherstellung nach einem ersten Fehler auftrat.
Wir waren dann in der Lage, das Leck im Feld zu reproduzieren.
Zufälligkeit fand also ein Problem, das sonst schwer zu finden war. Ein wenig rohe Gewalt, aber der Computer hatte nichts dagegen, am Wochenende zu arbeiten.
___ answer781258 ___
Das Ziel von Unit-Testing ist es, Vertrauen in Ihren Code zu bekommen. Wenn Sie also fühlen , dass die Verwendung zufälliger Werte Ihnen helfen könnte, weitere Fehler zu finden, benötigen Sie offensichtlich mehr Tests, um Ihr Konfidenzniveau zu erhöhen.
In dieser Situation könnten Sie sich auf iterationsbasiertes Testen verlassen, um diese Probleme zu identifizieren.
Ich würde empfehlen, neue spezifische Tests für die Fälle zu erstellen, die beim Loop-Test entdeckt wurden, und dann die iterationsbasierten Tests zu entfernen. damit sie Ihre Tests nicht verlangsamen.
___ antwort787882 ___
Siehe David Saffs Arbeit zu Theorie-basiertem Testen .
Im Allgemeinen würde ich Zufälligkeit in Unit Tests vermeiden, aber die Theorie ist faszinierend.
___ answer815148 ___
Der "Schlüssel" -Punkt ist hier der Komponententest. Eine Anzahl zufälliger Werte im erwarteten Bereich sowie die Kanten für den guten Fall und den äußeren Bereich / Grenze für den schlechten Fall sind in einem Regressionstest wertvoll, vorausgesetzt, der Keim ist konstant.
Ein Komponententest kann zufällige Werte im erwarteten Bereich verwenden, wenn es möglich ist, die Ein- / Ausgänge (falls vorhanden) vorher und nachher zu speichern.
___ answer781252 ___
Ich würde nicht völlig zufällige Werte befürworten, da es Ihnen ein falsches Gefühl der Sicherheit gibt. Wenn Sie nicht den gesamten Bereich durchgehen können (was oft der Fall ist), ist es viel effizienter, eine Untermenge von Hand auszuwählen. Auf diese Weise müssen Sie auch an mögliche "ungerade" Werte denken, Werte, die bewirken, dass der Code anders läuft (und nicht in der Nähe von Kanten ist).
Sie könnten einen Zufallsgenerator verwenden, um die Testwerte zu generieren, prüfen, ob sie eine gute Probe darstellen und sie dann verwenden. Dies ist eine gute Idee, besonders wenn die manuelle Auswahl zu zeitaufwändig wäre.
Ich habe zufällige Testwerte verwendet, als ich einen Semaphor-Treiber für einen hw-Block von zwei verschiedenen Chips geschrieben habe. In diesem Fall konnte ich nicht herausfinden, wie man aussagekräftige Werte für die Timings auswählt, also habe ich randomisiert, wie oft die Chips (unabhängig) versuchen würden, auf den Block zuzugreifen. Im Nachhinein wäre es immer noch besser gewesen, sie per Hand zu wählen, weil es nicht so einfach war, die Testumgebung so zu gestalten, dass sich die beiden Chips nicht aneinander anschmiegen konnten. Dies war ein sehr gutes Beispiel dafür, dass zufällige Werte keine zufällige Stichprobe bilden.
Das Problem wurde durch die Tatsache verursacht, dass, wann immer der andere Chip den Block reserviert hatte, der andere wartete und einem Semaphor folgte, nachdem der andere ihn freigegeben hatte. Als ich festlegte, wie lange die Chips auf den Zugriff warten mussten, waren die Werte tatsächlich nicht zufällig. Am schlimmsten war es, wenn ich den gleichen Wertebereich für beide zufälligen Werte hatte, es wurde etwas besser, nachdem ich sie geändert hatte, um verschiedene Bereiche zu haben, aber es war immer noch nicht sehr zufällig. Ich fing an, etwas von einem zufälligen Test zu bekommen, nachdem ich beide Wartezeiten zwischen Zugriffen und wie lange der Block reserviert war und die vier Sätze sorgfältig auswählte.
Am Ende habe ich wahrscheinlich mehr Zeit damit verbracht, den Code zu schreiben, um "zufällige" Werte zu verwenden, als ich ursprünglich verwendet hätte, um aussagekräftige Werte von Hand auszuwählen.
___ answer781254 ___
Was Sie beschreiben, wird normalerweise als spezifikationsbasiertes Testen bezeichnet und wurde von Frameworks wie QuickCheck implementiert (Haskell), scalacheck (Scala) und Quviq QuickCheck (Erlang).
Datenbasierte Test-Tools (z. B. %code% in TestNG ) können ähnliche Ergebnisse erzielen Ergebnisse.
Das zugrunde liegende Prinzip besteht darin, Eingabedaten für das zu testende Objekt auf der Grundlage einer bestimmten Spezifikation zu erstellen und ist weit davon entfernt, "schlecht zu praktizieren".
___ answer781249 ___
- Zufällige Eingabe - Die Tests sind nicht wiederholbar (produzieren bei jeder Ausführung konsistente Ergebnisse und werden daher nicht als gute Komponententests betrachtet. Tests sollten ihre Meinung nicht ändern.
- Range-Tests / RowTests - sind gut, solange sie den Test-Suite-Lauf nicht verlangsamen. Jeder Test sollte so schnell wie möglich laufen. (Eine Done-in-30sec-Testsuite wird häufiger als eine 10-minütige Testsuite ausgeführt) - vorzugsweise 100 ms oder weniger. Das heißt, jede Eingabe (Testdaten) sollte "repräsentative" Eingabe sein. Wenn alle Eingabewerte gleich sind, fügt das Testen jedes einzelnen Wertes keinen Wert hinzu und ist nur Routine-Zahlenverarbeitung. Sie brauchen nur einen Vertreter aus dieser Menge von Werten. Sie benötigen auch Vertreter für Randbedingungen und 'spezielle' Werte.
Weitere Informationen zu Richtlinien oder Thumbrülen finden Sie unter "Was macht einen guten Unit Test?"
Das heißt ... die Techniken, die Sie erwähnten, könnten großartig sein, repräsentative Eingaben zu finden. Verwenden Sie sie also, um scenarioX zu finden, wo Code fehlschlägt oder falsch funktioniert - dann schreiben Sie einen wiederholbaren, schnellen Test -on-those-only unit test für dieses scenarioX und füge es zu deiner Testsuite hinzu. Wenn Sie feststellen, dass diese Tools Ihnen weiterhin dabei helfen, weitere gute Testfälle zu finden, behalten Sie sie bei.
Antwort auf die Klarstellung von OP:
- Wenn Sie bei jedem Testlauf den gleichen Startwert (Testeingabe) für Ihren Zufallsgenerator verwenden, ist Ihr Test nicht zufällig - Werte können vorher festgelegt werden. Ein Komponententest sollte idealerweise keine Eingabe / Ausgabe benötigen - deshalb haben xUnit Testfälle die void TC () Signatur.
- Wenn Sie bei jedem Lauf andere Startwerte verwenden, sind Ihre Tests nun zufällig und nicht wiederholbar. Natürlich können Sie den speziellen Startwert in Ihren Protokolldateien ausfindig machen, um zu wissen, was fehlgeschlagen ist (und den Fehler reproduzieren), aber ich mag meine Tests, um mich sofort wissen zu lassen, was fehlgeschlagen ist - z. Ein roter TestConversionForEnums () lässt mich wissen, dass der Enum Conversion-Code ohne Inspektion unterbrochen ist.
Wiederholbar - Impliziert, dass jedes Mal, wenn der Test auf dem SUT ausgeführt wird, das gleiche Ergebnis (bestanden / nicht bestanden) erzeugt wird. Nicht "Kann ich einen Testfehler erneut reproduzieren?" ( Wiederholbar! = Reproduzierbar ). Um es noch einmal zu wiederholen: Diese Art von explorativem Testen ist zwar gut, um mehr Testfälle zu identifizieren, aber ich würde dies nicht zu meiner Testsuite hinzufügen, die ich jedes Mal ausfühle, wenn ich tagsüber einen Code ändere. Ich würde empfehlen, explorative Tests manuell durchzuführen, finde einige gute (einige können sadistische verwenden) Tester, die Hammer und Zangen an Ihrem Code gehen .. finden Sie mehr Testfälle als ein zufälliger Input-Generator.
___