Eigenschaftstestbeispiel mit Vavr

Eigenschaftstestbeispiel mit Vavr

1. Überblick

In diesem Artikel werden wir uns mit dem Konzept vonProperty Testing und seiner Implementierung in dervavr-test-Bibliothek. befassen

MitProperty based testing (PBT) können wir das allgemeine Verhalten eines Programms in Bezug auf Invarianten angeben, an die es sich halten sollte.

2. Was ist Eigenschaftstest?

Eine Eigenschaft ist die Kombination einer Invariante mit eineminput values generator. Für jeden generierten Wert wird die Invariante als Prädikat behandelt und geprüft, ob sie für diesen Wert wahr oder falsch ergibt.

Sobald es einen Wert gibt, der false ergibt, wird die Eigenschaft als gefälscht bezeichnet und die Prüfung abgebrochen. Wenn eine Eigenschaft nach einer bestimmten Menge von Beispieldaten nicht ungültig gemacht werden kann, wird davon ausgegangen, dass die Eigenschaft erfüllt ist.

Dank dieses Verhaltens schlägt unser Test fehl, wenn eine Bedingung nicht erfüllt ist, ohne unnötige Arbeit zu leisten.

3. Maven-Abhängigkeit

Zuerst müssen wir dervavr-test-Bibliothek eine Maven-Abhängigkeit hinzufügen:


    io.vavr
    jvavr-test
    ${vavr.test.version}



    2.0.5

4. Eigenschaftsbasierte Tests schreiben

Betrachten wir eine Funktion, die einen Strom von Zeichenfolgen zurückgibt. Es ist ein unendlicher Strom von 0 aufwärts, der Zahlen auf der Basis der einfachen Regel den Zeichenfolgen zuordnet. Wir verwenden hier eine interessante Vavr-Funktion namensPattern Matching:

private static Predicate divisibleByTwo = i -> i % 2 == 0;
private static Predicate divisibleByFive = i -> i % 5 == 0;

private Stream stringsSupplier() {
    return Stream.from(0).map(i -> Match(i).of(
      Case($(divisibleByFive.and(divisibleByTwo)), "DividedByTwoAndFiveWithoutRemainder"),
      Case($(divisibleByFive), "DividedByFiveWithoutRemainder"),
      Case($(divisibleByTwo), "DividedByTwoWithoutRemainder"),
      Case($(), "")));
}

Das Schreiben des Komponententests für eine solche Methode ist fehleranfällig, da mit hoher Wahrscheinlichkeit ein Randfall vergessen wird und im Grunde nicht alle möglichen Szenarien abgedeckt werden.

Glücklicherweise können wir einen eigenschaftsbasierten Test schreiben, der alle Randfälle für uns abdeckt. Zuerst müssen wir definieren, welche Art von Zahlen eine Eingabe für unseren Test sein soll:

Arbitrary multiplesOf2 = Arbitrary.integer()
  .filter(i -> i > 0)
  .filter(i -> i % 2 == 0 && i % 5 != 0);

Wir haben festgelegt, dass die eingegebene Zahl zwei Bedingungen erfüllen muss - sie muss größer als Null sein und durch zwei ohne Rest, aber nicht durch fünf teilbar sein.

Als nächstes müssen wir eine Bedingung definieren, die prüft, ob eine getestete Funktion den richtigen Wert für ein gegebenes Argument zurückgibt:

CheckedFunction1 mustEquals
  = i -> stringsSupplier().get(i).equals("DividedByTwoWithoutRemainder");

Um einen eigenschaftsbasierten Test zu starten, müssen wir die KlassePropertyverwenden:

CheckResult result = Property
  .def("Every second element must equal to DividedByTwoWithoutRemainder")
  .forAll(multiplesOf2)
  .suchThat(mustEquals)
  .check(10_000, 100);

result.assertIsSatisfied();

Wir geben an, dass für alle beliebigen Ganzzahlen, die ein Vielfaches von 2 sind, das PrädikatmustEqualserfüllt sein muss. Diecheck()-Methode verwendet die Größe einer generierten Eingabe und die Häufigkeit, mit der dieser Test ausgeführt wird.

Wir können schnell einen weiteren Test schreiben, der überprüft, ob die FunktionstringsSupplier() für jede eingegebene Zahl, die ohne den Rest durch zwei und fünf teilbar ist, einDividedByTwoAndFiveWithoutRemainder string zurückgibt.

Der Lieferant vonArbitraryundCheckedFunctionmüssen geändert werden:

Arbitrary multiplesOf5 = Arbitrary.integer()
  .filter(i -> i > 0)
  .filter(i -> i % 5 == 0 && i % 2 == 0);

CheckedFunction1 mustEquals
  = i -> stringsSupplier().get(i).endsWith("DividedByTwoAndFiveWithoutRemainder");

Dann können wir den eigenschaftsbasierten Test für eintausend Iterationen ausführen:

Property.def("Every fifth element must equal to DividedByTwoAndFiveWithoutRemainder")
  .forAll(multiplesOf5)
  .suchThat(mustEquals)
  .check(10_000, 1_000)
  .assertIsSatisfied();

5. Fazit

In diesem kurzen Artikel haben wir uns mit dem Konzept des eigenschaftsbasierten Testens befasst.

Wir haben Tests mit der Bibliothek von vavr-testerstellt. Wir haben die KlassenArbitrary, CheckedFunction, undProperty verwendet, um den eigenschaftsbasierten Test mitvavr-test. zu definieren

Die Implementierung all dieser Beispiele und Codefragmente finden Sie inover on GitHub - dies ist ein Maven-Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.