Blog Arolla

Vitest, Framework de test unitaire JavaScript

Vitest, qu’est-ce que c’est ?

Vitest est un Framework de test unitaire équivalent à Jest, d'ailleurs Vitest utilise la même API que Jest (on pourra retrouver describe, it, expect, ...).
Vitest est créé avec Vite, ce qui permet d'avoir le HMR (Hot Module Reloading) pour recharger (à l'enregistrement d'une modification) le fichier modifié, il est en "watch mode" par défaut. Contrairement à Jest, il n'y a pas besoin d'avoir 2 configurations différentes pour Vite et Vitest (tout se fait dans vite.config.js).

Vitest est une librairie ESM first, donc il est recommandé d'écrire en ESM (ECMAScript Module), mais fonctionne de base avec du commonjs et ESM.
Il support aussi le TypeScript et JSX de base.

Mise en place de Vitest

Vitest (v0.28.5) nécessite Vite >= v3.0.0 et Node >= v14
(Il faut regarder la doc pour voir les compatibilités des versions)

Pour ajouter Vitest à un projet, il faut taper la commande suivante :

npm install -D vitest

Ensuite il faut ajouter la commande pour lancer les tests dans package.json :
Configuration script test dans le package.json

En créant un premier test on peut déjà voir une différence avec Jest :
Exemple de test avec Vitest

Vitest n'importe pas automatiquement les globals (contrairement à Jest), donc si on veut passer un projet de Jest à Vitest il y a 2 solutions :

  • ajouter les imports dans vos fichiers tests
  • ajouter l'option --globals à la CLI ou ajouter globals: true dans la configuration :

     CLI
     Configuration des 'globals' dans le fichier package.json

     CONFIGURATION : vite.config.ts
     Configuration des 'globals' dans le fichier vite.config.ts

En mettant en place cette configuration il faudra, pour que TypeScript fonctionne avec les API globales, ajouter les lignes suivantes dans le fichier tsconfig.ts :
Configuration des 'globals' dans le fichier tsconfig.ts

Maintenant vous pouvez avoir (ou garder) vos tests sans importer les méthodes :
Exemple d'un test sans les imports

Personnellement je préfère importer les méthodes directement dans le fichier de test.

Snapshot

Vitest fournit des tests Snapshot:
Exemple test Snapshot

On obtient un fichier .snap:
Exemple fichier '.snap'

Il est possible aussi d’ajouter des Inline Snapshot, ce qui permet d’enregistrer le résultat directement dans le fichier de test :
Exemple d'un test 'Inline Snapshot'

Une fois le test lancé, au lieu de créer un fichier Snapshot, Vitest modifiera le répertoire du fichier de test, automatiquement, pour mettre à jour le Snapshot sous forme de chaîne :
Exemple du résultat d'un test 'Inline Snapshot'

Cela permet de voir directement la sortie attendue sans naviguer entre différents fichiers.

Mock

Simuler les dates

Vitest utilise @sinonjs/fake-timers un package pour manipuler les timers, ainsi que la date système. Vous pouvez en savoir plus sur l'API spécifique en détail ici.

Exemple :

Test de simulation de dates
(tiré de la doc)

Les fonctions

Comme dans Jest les fonctions de mock ( spyOn et fn ) sont disponibles avec Vitest mais, pour les appeler, il faudra utiliser vi au lieu de jest: vi.spyOn() et vi.fn().

Exemple :

Fonctions de mock
(tiré de la doc)

Les variables globales

Il est possible de mocker des variables globales qui ne sont pas présentes avec jsdom ou node en utilisant le helper vi.stubGlobal.

Exemple :

Variables globales (vi.stubGlobal)
(tiré de la doc)

Maintenant on peut accéder à la variable IntersectionObserverMock dans nos tests.

Les modules

Voir la section api vi.mock() pour une description détaillée de l’API.

Vitest a un algorithme d'automocking, c’est-à-dire, que si votre code importe un module mocké, sans aucun fichier associé à mocks ou factory pour ce module, alors Vitest mockera le module lui-même en l’invoquant et en simulant chaque exportation.

Les principes suivants s'appliquent :

  • Tous les tableaux seront vidés
  • Toutes les primitives et collections resteront les mêmes
  • Tous les objets seront profondément clonés
  • Toutes les instances de classes et leurs prototypes seront profondément clonés

Les requêtes réseau

Étant donné que Vitest s'exécute dans Node, mocker des requêtes réseau est délicat, les API Web ne sont pas disponibles, nous avons donc besoin de quelque chose qui imitera le comportement du réseau pour nous. Vitest recommande Mock Service Worker pour y parvenir. Il permettra de mocker à la fois des APIs REST et GraphQL, et est indépendant du framework.

Mock Service Worker (MSW) fonctionne en interceptant les requêtes de vos tests, vous permettant de l'utiliser sans modifier le code de votre application. Dans le navigateur, cela utilise l'API Service Worker. Dans Node.js, et pour Vitest, il utilise node-request-interceptor. Pour en savoir plus sur MSW, voir leur introduction.

Exemple de configuration :

Requêtes réseau
(tiré de la doc)

*La configuration du serveur avec onUnhandleRequest: 'error' garantit qu'une erreur est renvoyée chaque fois qu'une requête n'a pas de gestionnaire de requêtes correspondant.

Couverture de test

La couverture de tests se fait avec la commande vitest --coverage:
Configuration script : "vitest --coverage"

Pour avoir le rapport de couverture de test on peut utiliser c8, istanbul ou une solution de couverture personnalisée (comme indiqué sur la documentation).
En lançant cette commande (sans avoir installer de lib au préalable), cela demandera si on veut installer la dépendance c8 :
Message d'erreur dans la console stipulant qu'il manque la dépendance c8

Une fois installer voici le résultat :
Rapport de couverture dans la console

On peut remarquer que cela nous a généré un dossier coverage avec plusieurs fichiers :
Dossier coverage

Dans le fichier vite.config.ts il est possible d'ajouter une configuration pour demander le rapport de la couverture de tests uniquement en text (le rapport dans la console), json ou html par exemple.
Configuration dans vite.confi.ts

Voici un exemple du rapport en html :
Rapport html

Dans le rapport en html, on peut aussi naviguer dans les fichiers pour voir le code couvert :
Code couvert rapport html

Vitest UI

Vite permet à Vitest de fournir une interface utilisateur qui s'exécute dans le navigateur (il faudra ajouter la dépendance code>@vitest/ui). Il peut afficher du code, afficher les erreurs, afficher des graphiques, ...
Pour cela, nous allons ajouter vitest --ui dans le package.json :
Configuration script : "vitest --ui"

En lançant cette commande on nous demande d'installer la dépendance code>@vitest/ui:
Erreur console : ne trouve pas la dépendance "@vitest/ui"
(Il est possible aussi d'ajouter la dépendance avec la commande npm i -D @vitest/ui)

Une fois installer on peut relancer la commande, cela nous ouvre une page web (http://localhost:51204/vitest/) :
Interface de Vitest UI

On peut naviguer dans les fichiers tests et on aura plusieurs options :
Options dans l'interface

Dans la partie "Code" on peut voir le code de test et le modifier (toujours en watch mode) :
Option "Code" dans l'interface

Si le test tombe en erreur cela l'indiquera tout de suite :
Test qui échoue dans l'interface

Conclusion

Vitest est riche en fonctionnalités, simple à mettre en place et s’accorde parfaitement avec Vite. De plus, se basant sur la même API que Jest, on a pu voir qu’il était facile de passer les tests d’une application de Jest à Vitest.

Allez-vous l’utiliser pour vos tests ?

Plus de publications

Comments are closed.