Tests basés sur les propriétés en Java : casser le code plus vite qu'avec JUnit

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Tests basés sur les propriétés en Java : quand un test en remplace mille

\n\n

Avez-vous déjà écrit un test unitaire qui passait au vert, puis une semaine plus tard échouait en production avec une erreur sur « une valeur étrange » ? Ça vous dit quelque chose. Les tests classiques (basés sur des exemples), c'est comme vérifier qu'une bouilloire bout uniquement à 100°C. Mais que se passe-t-il si la pression est différente ? Et si l'altitude change ? Les tests basés sur les propriétés en Java résolvent précisément ce problème : au lieu d'énumérer manuellement des exemples, vous décrivez les propriétés auxquelles votre code doit satisfaire, et le framework génère des centaines de données d'entrée aléatoires pour vérifier que tout est en ordre.

\n\n

Cette approche est particulièrement utile pour les développeurs Java qui écrivent des algorithmes complexes, travaillent avec des collections, des analyseurs syntaxiques ou des fonctions mathématiques. Dans cet article, nous verrons comment intégrer les tests basés sur les propriétés dans votre projet avec la bibliothèque jqwik, et nous montrerons des exemples de code concrets.

\n\n

Qu'est-ce que le test basé sur les propriétés et en quoi diffère-t-il du test classique ?

\n\n

Dans l'approche classique, vous écrivez :

\n\n
@Test\nvoid testAddition() {\n    assertEquals(4, Calculator.add(2, 2));\n    assertEquals(0, Calculator.add(-1, 1));\n}
\n\n

Tout va bien, jusqu'à ce que quelqu'un passe Integer.MAX_VALUE. Ou null. Ou un très grand nombre négatif. Les tests basés sur les propriétés inversent la logique : vous ne dites pas « je m'attends à tel résultat », mais « pour toutes les données d'entrée valides, le résultat satisfait la propriété X ».

\n\n

Par exemple, une propriété pour l'addition : add(a, b) == add(b, a) (commutativité). Ou add(a, 0) == a (élément neutre). Le framework génère des milliers de paires aléatoires a et b et vérifie que la propriété n'est pas violée.

\n\n

Les principaux avantages des tests basés sur les propriétés :

\n
    \n
  • Génération automatique de données de test — vous trouvez des bugs auxquels vous n'aviez même pas pensé.
  • \n
  • Réduction du nombre de tests — un test basé sur les propriétés remplace des dizaines de tests basés sur des exemples.
  • \n
  • Vérification des cas limites — les générateurs savent créer des valeurs « dangereuses » (0, null, chaînes vides, grands nombres).
  • \n
  • Shrinking — si un test échoue, le framework réduit les données d'entrée à l'exemple le plus simple qui reproduit l'erreur.
  • \n
\n\n

Bibliothèques pour les tests basés sur les propriétés en Java

\n\n

Il existe plusieurs solutions matures sur le marché :

\n
    \n
  • jqwik — moderne, légère, s'intègre parfaitement avec JUnit 5. Je la recommande pour commencer.
  • \n
  • QuickTheories — rapide, mais moins populaire.
  • \n
  • JUnit QuickCheck — un fork d'un ancien outil Scala, mais le support est limité.
  • \n
\n\n

Nous utiliserons jqwik, car il possède l'API la plus pratique et une excellente documentation. Ajoutez la dépendance dans pom.xml :

\n\n
<dependency>\n    <groupId>net.jqwik</groupId>\n    <artifactId>jqwik</artifactId>\n    <version>1.8.4</version>\n    <scope>test</scope>\n</dependency>
\n\n

Ou pour Gradle :

\n\n
testImplementation 'net.jqwik:jqwik:1.8.4'
\n\n

Écrire notre premier test basé sur les propriétés en Java

\n\n

Supposons que nous ayons une méthode qui inverse une chaîne de caractères :

\n\n
public static String reverse(String s) {\n    if (s == null) return null;\n    return new StringBuilder(s).reverse().toString();\n}
\n\n

Quelle propriété pouvons-nous vérifier ? Si on inverse une chaîne deux fois, on obtient la chaîne originale. C'est une propriété idéale pour les tests basés sur les propriétés.

\n\n
import net.jqwik.api.*;\nimport static org.assertj.core.api.Assertions.assertThat;\n\nclass StringProperties {\n                

Blogs

Book Recommendations