Parametrisierte Tests - Wann und warum verwenden Sie sie?

15

Vor kurzem hatten wir bei der Arbeit einige Meinungsverschiedenheiten in Bezug auf das parametrisierte Testen . Normalerweise verwenden wir einen TDD-Stil (oder versuchen es zumindest), damit ich die Vorteile dieses Ansatzes verstehe. Ich kämpfe jedoch darum, zu sehen, welchen Gewinn parametrisierte Tests bringen. Als Referenz arbeiten wir an einem Service und seinen Bibliotheken, die über eine REST-Schnittstelle verfügbar gemacht werden.

Was ich bisher gesehen habe, sind Tests, die zumindest JUnit in Eclipse verwenden:

  • Mangel an Details - Wenn ein Test fehlschlägt, ist es sehr schwierig, die Parameter zu erkennen, die zum Fehlschlagen geführt haben
  • Oft kompliziert zu erstellen
  • Neigen dazu, erstellt zu werden, nachdem der Code geschrieben wurde - streng genommen kein Nachteil an sich, aber denken die Leute beim Starten eines Codeteils an parametrisierte Tests?

Wenn jemand Beispiele dafür hat, wo sie wirklich nützlich sind, oder sogar gute Tipps für ihre Verwendung, dann wäre das fantastisch. Ich möchte sicherstellen, dass ich nicht nur hartnäckig bin, weil ich mich persönlich nicht dafür entscheide, sie zu verwenden und zu prüfen, ob sie Teil unseres Testarsenals sind.

Neilprosser
quelle
1
Das Problem liegt nicht bei der Idee, sondern bei der klobigen Bibliothek. In C # ist die Syntax wesentlich benutzerfreundlicher, wenn Sie beispielsweise MbUnit verwenden. Ja, das ist eine gute Idee. Fügen Sie Ihren eigenen Code hinzu, um diesen Prozess zu vereinfachen - lesen Sie Inhalte aus Dateien - was auch immer funktioniert. Schauen Sie sich auch an, wie MsTest damit umgeht.
Job
Wir (Square) haben Burst geschrieben , um einige dieser Probleme zu lösen Parameterized. Im Allgemeinen wird weniger Boilerplate hinzugefügt, und es wird ziemlich deutlich, wo ein Test fehlgeschlagen ist.
Daniel Lubarov

Antworten:

4

Das Problem beim Testen von Software besteht darin, dass die Komplexität ziemlich schnell zunimmt. Tatsache ist, dass Sie nicht alle möglichen Kombinationen von Parametern testen können, die an Ihre Methoden übergeben werden. Phadke befürwortet einen DOE-Ansatz (Design of Experiments), mit dem die wahrscheinliche Liste der zu testenden Parameterwerte erstellt werden kann.

Die Idee ist, dass die meisten Fehler, auch wenn Sie nicht ausführlich testen, eher einen "Fehlerbereich" als einen isolierten Punktfehler verursachen. Der DOE-Ansatz Phadke empfiehlt, orthogonale Arrays zu verwenden, die den Parameterraum fein genug abtasten, um alle möglichen Fehlerbereiche zu treffen.

Isolierte Fehler werden wahrscheinlich nicht identifiziert, aber dies sind im Allgemeinen weniger als Fehlerregionen.

Mit dem DOE-Ansatz können Sie die zu variierenden Parameterwerte systematisch auswählen.

Peter K.
quelle
Der angegebene Link ist fehlerhaft.
Josh Gust
1
@JoshGust Mit Google einfach zu beheben. Danke für die Warnung.
Peter K.
4

Sie können hilfreich sein, um sicherzustellen, dass Ihr Code nicht nur den fehlerfreien Pfad, sondern auch die Randfälle verarbeitet. Nachdem Sie wissen, dass Ihr Code mit normalen Variablen funktioniert, parametrisieren Sie den Testfall und stellen Sie sicher, dass auch Nullen und Nullen, leere Zeichenfolgen, große Zahlen, lange Zeichenfolgen, seltsame Unicode-Zeichen usw. einwandfrei funktionieren.

Ethel Evans
quelle
2

Es gibt mindestens zwei Arten von parametrisierten Tests, mindestens in JUnit 4.8. Dies sind: Parametrisierte Tests ( @RunWith(Parameterized.class)), die eine Datenquelle erfordern, die vordefinierte Parameterkonfigurationen generiert / liest, und Theorien ( @RunWith(Theories.class)), die bei einer oder mehreren möglichen Eingaben pro Argumenttyp die Spezifikation bestimmter Methoden ausführen können. Es sieht ungefähr so ​​aus:

  • Geben Sie einige mögliche Werte ( @DataPoints) für Zeichenfolgenargumente an (z. B. nullleere Zeichenfolge, nicht leere Zeichenfolge, sehr lange Zeichenfolge).
  • Geben Sie einige mögliche Werte ( @DataPoints) für Animal-Klassenargumente an (wie null, DogInstanz, CatInstanz, BirdInstanz).
  • vorbereiten, @Theorydie einen StringParameter und einen AnimalParameter akzeptiert . es wird mit jeder möglichen Kombination der möglichen Parameterwerte ausgeführt (im gegebenen Beispiel wären das 4x4 = 16 Kombinationen, einschließlich ( null, null))
  • Wenn die getestete Methode keine Kombination akzeptieren kann, verwenden Sie Assume.assumeThatstatische Importe, um ungültige Kombinationen herauszufiltern (z. B. wenn Sie das Verhalten der Methode für nicht leere Zeichenfolgen überprüfen möchten, lautet eine der ersten Zeilen "davon ausgehen, dass nicht null".

Wie bereits erwähnt, ist es nicht sinnvoll, jede mögliche Kombination jeder Methode zu testen (es werden Testmengen aufgelöst). Stellen Sie sich vor, Sie testen eine Methode mit 5 Parametern mit jeweils nur 5 möglichen Werten: 5 ** 5 -> über 3000 Testläufe !), aber für missionskritische Methoden (wie API-Methoden) würde ich es empfehlen, nur um auf der sicheren Seite zu sein ...

Adam Hepner
quelle
1

Allgemeines Beispiel:

  • Methoden mit String-Argumenten. Verwenden Sie parametrisierte Tests, um verschiedene Eingänge und ihre erwarteten Ausgänge zu testen. Es ist viel praktischer, eine Liste von Paaren (Eingabe, erwartet) zu haben, als für jedes Paar einen TC zu schreiben.

  • Wenden Sie dasselbe Szenario auf verschiedene Argumente an. Wir haben ein Szenario , das mit dem Werk - AnimalObjekt und das hat viele Unterklassen wie Dog, Cat, Bird. Erstellen Sie eine Liste der verfügbaren Tiere und testen Sie das Szenario an ihnen.

Beton für Webservice:

  • Aus dem obigen Beispiel mit den Zeichenfolgenargumenten. Testen Sie, was mit unterschiedlichen Argumenten desselben Typs, aber unterschiedlichen Werten passiert.
Victor Hurdugaci
quelle
0

Parametrisierte Tests eignen sich gut zum Testen von Funktionen / Merkmalen mit einfacher Eingabe, wenn Sie eine Vielzahl von Eingaben testen möchten.

Sie eignen sich nicht gut zum Testen verschiedener Funktionen und komplexer Eingaben. Sie sollten nicht als praktische Struktur verwendet werden, um weniger Code zu schreiben.

Cirem
quelle
1
Warum sollten Parameter nicht verwendet werden, um weniger Code zu schreiben? Es ist keine große Tugend, eine vollständige Auflistung einer großen (ish) Menge von Testfällen bereitzustellen.
Jonathan Eunice
1
Wie liefert Ihre Antwort mehr Informationen als die anderen 5 Antworten?
Adam Zuckerman
-2

Ein Fall, in dem ich viele parametrisierte Tests auf TDD-artige Weise verwende, ist das Schreiben von Parsern. Ich kann mit einer Liste der eingegebenen und erwarteten Werte beginnen und dann den Code schreiben, damit alle Testfälle bestanden werden.

Aber ich habe ein paar Schrecken von parametrisierten Tests gesehen. Nein, Virginia, Ihre Testsuite sollte keine eigenen Komponententests benötigen.

Wyatt Barnett
quelle
1
Idealerweise sollten parametrisierte Tests die Form haben, dass "Tut Punkt (n) in der tatsächlichen Ausgabe mit Punkt (n) in der erwarteten Ausgabe übereinstimmt", und in diesem Fall sind keine Tests erforderlich. Aber für etwas komplexeres würde ich es vorziehen, einen sauberen parametrisierten Test oder zwei mit ihren eigenen Testfällen zu sehen, als die übliche Handbewegung "Mein (Test-) Code ist offensichtlich korrekt". Wenn das wahr wäre, würden Sie überhaupt keine Testfälle schreiben. Natürlich ist es möglich, mit der Komplexität über Bord zu gehen, und ich behaupte nicht, dass es keine Linie gibt, aber ich denke, dass es Fälle gibt, in denen das Testen von Tests eine gute Idee ist.