Test basé sur les propriétés en JavaScript : Attrapez les bugs que vous ne cherchiez pas

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

Et si les tests s'écrivaient tout seuls ? Découverte du property-based testing

\n\n

Avez-vous déjà écrit un test unitaire, l'avoir exécuté, obtenu un feu vert, puis un mois plus tard trouvé un bug dans la même fonction ? Cela vous dit quelque chose ? Les tests unitaires classiques, c'est comme vérifier que votre portefeuille n'est pas vide en ne regardant qu'un seul billet. Vous vérifiez un scénario spécifique, un seul ensemble de données d'entrée. Et si je vous disais qu'il existe un moyen de faire en sorte que l'ordinateur invente lui-même des milliers de scénarios différents et vérifie si votre code ne se casse pas ?

\n\n

Ce n'est pas de la science-fiction. C'est le test basé sur les propriétés en JavaScript (ou property-based testing). Au lieu d'écrire « si on passe 2 et 3, on obtient 5 », vous décrivez une propriété de votre fonction : « pour deux nombres quelconques, le résultat de l'addition sera un nombre toujours supérieur ou égal à chacun des termes ». Et l'environnement de test génère des centaines de paires de nombres aléatoires, vérifiant cette assertion.

\n\n

Dans cet article, nous verrons comment fonctionne le property-based testing, en quoi il diffère des tests classiques, et comment l'intégrer à votre projet avec l'excellente bibliothèque fast-check. Vous verrez à quel point il est facile de trouver des bugs « limites » que vous n'auriez même pas pensé à chercher.

\n\n

Pourquoi les tests unitaires classiques ne suffisent pas toujours ?

\n\n

Allons droit au but. Supposons que vous ayez une fonction qui trie un tableau de nombres par ordre croissant :

\n\n
function sortNumbers(arr) {\n  return arr.slice().sort((a, b) => a - b);\n}
\n\n

Vous écrivez un test unitaire :

\n\n
test('trie le tableau [3, 1, 2]', () => {\n  expect(sortNumbers([3, 1, 2])).toEqual([1, 2, 3]);\n});
\n\n

Le test est vert. Vous êtes heureux. Mais que se passe-t-il si le tableau contient null ? Ou undefined ? Ou de très grands nombres ? Ou un tableau de 10 000 éléments ? Vous n'allez pas écrire un test pour chacun de ces cas. Alors que le test basé sur les propriétés en JavaScript, lui, le fera.

\n\n

Au lieu d'énumérer des exemples, vous décrivez des invariants (propriétés) qui doivent toujours être vrais :

\n
    \n
  1. La longueur du tableau trié est égale à la longueur du tableau d'origine.
  2. \n
  3. Chaque élément du tableau d'origine est présent dans le tableau trié.
  4. \n
  5. Pour tout indice i, on a arr[i] <= arr[i+1].
  6. \n
\n\n

Ce sont précisément ces propriétés que le test de propriétés va vérifier.

\n\n

La bibliothèque fast-check : votre assistant pour les tests aléatoires

\n\n

Dans le monde JavaScript, l'outil principal pour le property-based testing est fast-check. Elle sait générer des données aléatoires de tous types : nombres, chaînes de caractères, tableaux, objets, dates — et même des structures complexes.

\n\n

L'installation est simple :

\n
npm install fast-check --save-dev
\n\n

Écrivons maintenant notre premier test basé sur les propriétés pour la fonction sortNumbers. Nous utilisons le framework Jest, mais fast-check fonctionne avec n'importe quel exécuteur de tests.

\n\n
const fc = require('fast-check');\n\ntest('le tri conserve la longueur du tableau', () => {\n  fc.assert(\n    fc.property(fc.array(fc.integer()), (arr) => {\n      const sorted = sortNumbers(arr);\n      return sorted.length === arr.length;\n    })\n  );\n});
\n\n

Que se passe-t-il ici ? fc.array(fc.integer()) est un générateur qui crée des tableaux aléatoires d'entiers aléatoires. fc.property prend ce générateur et vérifie l'assertion (notre fonction fléchée) sur 100 (par défaut) ensembles de données différents. Si au moins un test échoue, fc.assert lèvera une erreur et affichera un contre-exemple.

\n\n

Ajoutons plus de propriétés

\n\n

Une propriété, c'est bien, mais trois, c'est mieux. Vérifions qu'après le tri, le tableau est effectivement ordonné :

\n\n
test('le tri retourne un tableau ordonné', () =>                

Blogs

Book Recommendations