Exemple de test de propriété avec Vavr

Exemple de test de propriété avec Vavr

1. Vue d'ensemble

Dans cet article, nous allons examiner le concept deProperty Testing et son implémentation dans la bibliothèquevavr-test.

LeProperty based testing (PBT) nous permet de spécifier le comportement de haut niveau d'un programme concernant les invariants auxquels il doit adhérer.

2. Qu'est-ce que le test de propriété?

Une propriété est la combinaison d'un invariant avec uninput values generator. Pour chaque valeur générée, l'invariant est traité comme un prédicat et il est vérifié s'il renvoie true ou false pour cette valeur.

Dès qu'il y a une valeur qui produit false, la propriété est dite falsifiée et la vérification est abandonnée. Si une propriété ne peut pas être invalidée après une quantité spécifique de données exemple, la propriété est supposée satisfaite.

Grâce à ce comportement, notre test échoue si une condition n'est pas satisfaite sans travail inutile.

3. Dépendance Maven

Tout d'abord, nous devons ajouter une dépendance Maven à la bibliothèquevavr-test:


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



    2.0.5

4. Ecrire des tests basés sur les propriétés

Prenons une fonction qui renvoie un flux de chaînes. C'est un flux infini de 0 et plus qui mappe les nombres aux chaînes en fonction de la règle simple. Nous utilisons ici une fonctionnalité intéressante de Vavr appelée lesPattern 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($(), "")));
}

L’écriture du test unitaire pour une telle méthode sera sujette aux erreurs car il y a une forte probabilité que nous oublions certains cas extrêmes et que nous ne couvrons pas tous les scénarios possibles.

Heureusement, nous pouvons écrire un test basé sur les propriétés qui couvrira tous les cas extrêmes pour nous. Premièrement, nous devons définir quel type de nombres devrait être une entrée pour notre test:

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

Nous avons précisé que le nombre d'entrées doit remplir deux conditions: il doit être supérieur à zéro et doit pouvoir être divisé par deux sans reste, mais pas par cinq.

Ensuite, nous devons définir une condition qui vérifie si une fonction testée renvoie la valeur appropriée pour l'argument donné:

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

Pour démarrer un test basé sur les propriétés, nous devons utiliser la classeProperty:

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

result.assertIsSatisfied();

Nous spécifions que, pour tous les nombres entiers arbitraires multiples de 2, le prédicatmustEquals doit être satisfait. La méthodecheck() prend la taille d'une entrée générée et le nombre de fois que ce test sera exécuté.

Nous pouvons rapidement écrire un autre test qui vérifiera si la fonctionstringsSupplier() renvoie unDividedByTwoAndFiveWithoutRemainder string pour chaque nombre d'entrée qui est divisible par deux et cinq sans le reste.

Le fournisseur deArbitrary etCheckedFunction doivent être modifiés:

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

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

Ensuite, nous pouvons exécuter le test basé sur les propriétés pour mille itérations:

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

5. Conclusion

Dans cet article rapide, nous avons examiné le concept de test basé sur les propriétés.

Nous avons créé des tests en utilisant la bibliothèque vavr-test; nous avons utilisé les classesArbitrary, CheckedFunction, etProperty pour définir le test basé sur les propriétés en utilisantvavr-test.

L'implémentation de tous ces exemples et extraits de code peut être trouvéeover on GitHub - c'est un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.