Les tests de logiciels sont essentiels pour garantir que vos applications fonctionnent comme prévu, en particulier lorsque vous introduisez des changements. La détection et la correction des erreurs dès le début du développement sont cruciales pour maintenir un code résistant et de haute qualité.
Parmi les nombreux outils et frameworks disponibles pour les tests JavaScript, Jest est l’un des plus populaires. Produit par Meta, Jest offre des capacités de test étendues pour les applications JavaScript et celles construites avec des frameworks JavaScript.
Nous allons explorer le framework Jest, ses fonctionnalités et la meilleure façon de l’intégrer dans votre flux de développement.
Qu’est-ce que Jest ?
Jest est un framework flexible et simple à utiliser. En plus de ses fonctionnalités principales de test JavaScript, il offre des configurations et des extensions pour tester les applications Babel, webpack, Vite, Parcel ou TypeScript.
Jest a été largement adopté par les développeurs et dispose d’un large éventail d’extensions développées et maintenues par la communauté. Il se distingue par sa facilité d’utilisation : Les tests JavaScript ne nécessitent aucune configuration ou extension supplémentaire. Mais vous pouvez également effectuer des tests plus avancés – comme les tests de frameworks JavaScript – en utilisant quelques options de configuration supplémentaires.
Comment configurer Jest pour votre projet JavaScript
Voyons comment configurer Jest dans un projet JavaScript existant.
Pré-requis
Pour suivre ce tutoriel, assurez-vous d’avoir les éléments suivants :
- Node.js est installé.
- npm (qui fait déjà partie de Node.js) ou Yarn installé.
- Le paquet Jest npm est installé.
Installer le paquet Jest
- Si vous n’avez pas encore de projet pour suivre ce tutoriel, utilisez ce dépôt comme point de départ.
La branche starter-files
vous donne une base pour construire l’application au fur et à mesure que vous suivez le tutoriel. Référencez la branche main
pour voir le code de ce tutoriel et vérifier votre code.
- Pour installer Jest avec npm, allez dans le répertoire du projet dans votre terminal et exécutez la commande suivante :
npm install --save-dev jest
L’option --save-dev
indique à npm d’installer le paquet sous devDependencies
, qui contient les dépendances dont vous avez besoin pour le développement.
Configurer Jest
Bien que Jest fonctionne généralement sans configuration supplémentaire, il existe deux façons d’étendre sa puissance : dans le fichier package.json et via un fichier de configuration Jest.
Configurer Jest dans package.json
Dans votre fichier package.json, ajoutez un objet nommé jest
avec les propriétés indiquées ci-dessous :
{
…
"jest": {
"displayName": "Ecommerce",
"globals": {
"PROJECT_NAME": "Ecommerce TD"
},
"bail": 20,
"verbose": true
},
}
Pendant le test, Jest recherche cet objet et applique ces configurations. Vous pouvez voir des options supplémentaires sur la page de configuration de Jest, mais les propriétés de cet objet sont les suivantes :
displayName
– Jest ajoute la valeur de cette propriété en tant qu’étiquette à vos résultats de test.globals
– Détient une valeur d’objet pour définir les variables globales disponibles dans vos environnements de test.bail
– Par défaut, Jest exécute tous les tests et affiche les erreurs dans les résultats.bail
indique à Jest d’arrêter l’exécution après un certain nombre d’échecs.verbose
– Lorsqu’il est défini surtrue
, il affiche les rapports de test individuels pendant l’exécution du test.
Configurer Jest dans un fichier de configuration
Vous pouvez également configurer Jest dans un fichier jest.config.js. Jest supporte également les extensions .ts, .mjs, .cjs et .json. Lors de l’exécution des tests, Jest recherche ces fichiers et applique les paramètres du fichier qu’il trouve.
Par exemple, considérez ce fichier jest.config.js:
const config = {
displayName: "Ecommerce",
globals: {
"PROJECT_NAME": "Ecommerce TD"
},
bail: 20,
verbose: true
}
module.exports = config;
Le code exporte un objet de configuration Jest avec les mêmes propriétés que dans l’exemple précédent.
Vous pouvez également utiliser un fichier personnalisé qui contient un objet de configuration sérialisable en JSON et transmettre le chemin du fichier à l’option --config
lors de l’exécution de vos tests.
Créer un fichier de test de base
Une fois Jest configuré, créez vos fichiers de test. Jest examine les fichiers de test de votre projet, les exécute et fournit les résultats. Les fichiers de test suivent généralement un format tel que [nom].test.js ou [nom]-test.js. Ce modèle permet à Jest et à votre équipe d’identifier facilement vos fichiers de test.
Considérez un fichier string-format.js qui contient le code suivant :
function truncate(
str,
count,
withEllipsis = true
) {
if (str.length < = count)
return str
const substring = str.substr(0, count)
if (!withEllipsis)
return substring
return substring + '...'
}
module.exports = { truncate }
La fonction truncate()
tronque les chaînes de caractères à une longueur particulière avec la possibilité d’ajouter une ellipse.
Écrire le test
- Créez un fichier de test nommé string-format.test.js.
- Pour garder vos fichiers organisés, placez string-format.test.js dans le même répertoire que le fichier string-format.js ou dans un répertoire de test spécifique. Quel que soit l’emplacement de votre fichier de test dans le projet, Jest le trouve et l’exécute. Avec Jest, vous pouvez tester vos applications dans différents scénarios.
- Écrivez un test de base dans string-format.test.js comme suit :
const { truncate } = require('./string-format')
test('truncates a string correctly', () = > {
expect(truncate("I am going home", 6)).toBe('I am g...')
})
Le cas de test a la description suivante : truncates a string correctly
. Ce code utilise la fonction expect
fournie par Jest, qui teste si une valeur correspond au résultat attendu.
Le code passe truncate("I am going home", 6)
comme argument à expect
. Ce code teste la valeur renvoyée par l’appel à truncate
avec les arguments "I am going home"
et 6
. L’appel à expect
renvoie un objet expectation, qui permet d’accéder aux correspondances de Jest.
Il contient également le matcheur toBe
, qui a pour argument "I am g…"
. Le matcheur toBe
teste l’égalité entre les valeurs attendues et les valeurs réelles.
Exécuter le test
Pour exécuter vos tests, définissez la commande jest
.
- Dans le fichier package.json de votre projet, ajoutez ce script
test
:
"scripts": {
"test": "jest"
}
- Exécutez maintenant
npm run test
,npm test
, ounpm t
dans votre terminal. Il exécute Jest pour le projet.
Lorsque vous exécutez les tests, voici le résultat :
- Dans string-format.js, si vous ajoutez un point supplémentaire pour casser le code et exécuter le test, celui-ci échoue :
Ce résultat suggère que vous avez cassé la fonction truncate
ou que vous avez fait des mises à jour qui nécessitent une mise à jour des tests.
Comment écrire des tests avec Jest
Syntaxe des tests Jest
La syntaxe propriétaire de Jest est simple à utiliser. Jest expose des méthodes et des objets globaux à votre projet pour écrire des tests. Certains de ses termes fondamentaux sont describe
, test
, expect
, et matchers.
describe
: Cette fonction regroupe les tests apparentés dans un fichier.test
: Cette fonction exécute le test. C’est un alias deit
. Elle contient des assertions pour les valeurs que vous souhaitez tester.expect
: Cette fonction déclare les assertions pour diverses valeurs. Elle permet d’accéder à des outils d’appariement pour différentes formes d’assertions.- Correspondants : Ils vous permettent d’affirmer une valeur de différentes manières. Vous pouvez affirmer l’égalité des valeurs, l’égalité booléenne et l’égalité contextuelle (par exemple, si un tableau contient la valeur).
Pour les utiliser, considérez l’exemple suivant :
- Remplacez le test du fichier string-format.test.js par le code suivant :
describe("all string formats work as expected", () = > {
test("truncates a string correctly", () = > {
expect(
truncate("I am going home", 6)
).toBe("I am g...")
})
})
- Exécutez le code.
Le résultat ressemble à ce qui suit :
La capture d’écran montre que la chaîne de la fonction describe
crée un bloc. Bien que describe
soit facultatif, il est utile de regrouper les tests dans un fichier avec plus de contexte.
Organiser les tests en suites de tests
Dans Jest, un scénario de test se compose de la fonction test
, de la fonction expect
et d’un matcher. Une collection de cas de test apparentés constitue une suite de tests. Dans l’exemple précédent, string-format.test.js est une suite de tests comprenant un scénario de test pour tester le fichier string-format.js.
Supposons que vous ayez d’autres fichiers dans votre projet, comme file-operations.js, api-logger.js et number-format.js. Vous pouvez créer des suites de tests pour ces fichiers, comme file-operations.test.js, api-logger.test.js, et number-format.test.js.
Écrire des assertions simples avec Jest Matchers
Nous avons exploré un exemple d’utilisation du matcher toBe
. Les assertions avec d ‘autres matchers Jest incluent :
toEqual
– Pour tester l’égalité « profonde » dans les instances d’objets.toBeTruthy
– Pour tester si une valeur est true dans un contexte booléen.toBeFalsy
– Pour tester si une valeur est false dans un contexte booléen.toContain
– Pour tester qu’un tableau contient une valeur.toThrow
– Pour tester qu’une fonction invoquée provoque une erreur.stringContaining
– Pour tester qu’une chaîne de caractères contient une sous-chaîne.
Explorons des exemples utilisant certains de ces outils d’appariement.
Vous pouvez, par exemple, vous attendre à ce qu’une fonction ou un code renvoie un objet avec des propriétés et des valeurs spécifiques.
- Utilisez l’extrait de code ci-dessous pour tester cette fonctionnalité. Dans ce cas, vous souhaitez affirmer que l’objet retourné est égal à l’objet attendu.
expect({
name: "Joe",
age: 40
}).toBe({
name: "Joe",
age: 40
})
Cet exemple utilise toBe
. Le test échoue car ce matcheur ne vérifie pas l’égalité en profondeur – il vérifie la valeur, et non toutes les propriétés.
- Utilisez l’outil de recherche
toEqual
pour vérifier l’égalité profonde :
expect({
name: "Joe",
age: 40
}).toEqual({
name: "Joe",
age: 40
})
Ce test est réussi car les deux objets sont « profondément égaux », ce qui signifie que toutes leurs propriétés sont égales.
- Essayez un autre exemple de matcher qui teste si le tableau défini contient un élément spécifique.
expect(["orange", "pear", "apple"]).toContain("mango")
Ce test échoue parce que toContain
affirme que le tableau ["orange", "pear", "apple"]
contient une valeur attendue "mango"
, mais le tableau n’en contient pas.
- Utilisez des variables pour le même test qu’avec le code ci-dessous :
const fruits = ["orange", "pear", "apple"];
const expectedFruit = "mango";
expect(fruits).toContain(expectedFruit)
Tester le code asynchrone
Jusqu’à présent, nous avons testé du code synchrone – des expressions qui renvoient une valeur avant que le code n’exécute la ligne suivante. Vous pouvez également utiliser Jest pour du code asynchrone avec async
, await
, ou Promises.
Par exemple, le fichier apis.js contient une fonction permettant d’effectuer une demande d’API:
function getTodos() {
return fetch('https://jsonplaceholder.typicode.com/todos/1')
}
La fonction getTodos
envoie une requête GET
à https://jsonplaceholder.typicode.com/todos/1
.
- Créez un fichier nommé apis.test.js avec le code suivant pour tester la fausse API:
const { getTodos } = require('./apis')
test("gets a todo object with the right properties", () = > {
return getTodos()
.then((response) = > {
return response.json()
})
.then((data) = > {
expect(data).toHaveProperty('userId')
expect(data).toHaveProperty('id')
expect(data).toHaveProperty('title')
expect(data).toHaveProperty('completed')
expect(data).toHaveProperty('description')
})
})
Ce scénario de test invoque la fonction getTodos
qui récupère un objet todo
. Lorsqu’il résout la promesse, il utilise la méthode .then
pour obtenir la valeur résolue.
Dans cette valeur, le code renvoie response.json()
, qui est une autre promesse qui convertit la réponse au format JSON. Une autre méthode .then
permet d’obtenir l’objet JSON contenant les expect
et les matchers. Le code affirme que l’objet JSON comprend cinq propriétés : userId
, id
, title
, completed
, et description
.
- Exécuter les tests :
Comme le montre la capture d’écran, le test pour getTodos()
échoue. Il attend la propriété description
, mais l’API ne la renvoie pas. Grâce à ces informations, vous pouvez maintenant demander à l’équipe de gestion de l’API de votre entreprise d’inclure cette propriété si l’application en a besoin ou de mettre à jour les tests pour qu’ils correspondent à la réponse de l’API.
- Supprimez l’assertion pour la propriété
description
et réexécutez les tests :
La capture d’écran montre que tout a passé le test.
- Essayez maintenant d’utiliser
async/await
au lieu de la gestion traditionnelle des promesses :
test("gets a todo object with the right properties", async () = > {
const response = await getTodos()
const data = await response.json()
expect(data).toHaveProperty("userId")
expect(data).toHaveProperty("id")
expect(data).toHaveProperty("title")
expect(data).toHaveProperty("completed")
})
Le mot-clé async
est maintenant placé avant la fonction. Le code utilise await
avant getTodos()
et await
avant response.json()
.
Fonctionnalités avancées de Jest
Fonctions et modules fictifs
Vous pouvez vouloir tester une expression avec des dépendances externes lorsque vous écrivez des tests. Dans certains cas, en particulier les tests unitaires, vos tests unitaires doivent être isolés des effets externes. Dans ce cas, vous pouvez simuler vos fonctions ou modules avec Jest pour mieux contrôler vos tests.
- Par exemple, considérez un fichier functions.js qui contient le code suivant :
function multipleCalls(count, callback) {
if (count < 0) return;
for (let counter = 1; counter <= count; counter++) {
callback()
}
}
La fonction multipleCalls
est exécutée en fonction de la valeur de count
. Elle dépend de la fonction de rappel – la dépendance externe. Son but est de savoir si multipleCalls
exécute correctement la dépendance externe.
- Pour simuler la dépendance externe et suivre son état dans votre fichier de test, functions.test.js, utilisez ce code :
const { multipleCalls } = require('./functions')
test("functions are called multiple times correctly", () => {
const mockFunction = jest.fn()
multipleCalls(5, mockFunction)
expect(
mockFunction.mock.calls.length
).toBe(5)
})
Ici, la méthode fn
de l’objet jest
crée une fonction fictive. Ensuite, le code exécute multipleCalls
en passant 5
et la fonction fictive comme arguments. Il affirme ensuite que la méthode mockFunction
est appelée cinq fois. La propriété mock
contient des informations sur la façon dont le code appelle la fonction et les valeurs renvoyées.
- Lorsque vous exécutez le test, le résultat attendu est le suivant :
Comme vous pouvez le constater, le code appelle le site mockFunction
cinq fois.
Dans le code, la fonction fictive imite une dépendance externe. La nature de la dépendance externe importe peu lorsque l’application utilise multipleCalls
en production. Votre test unitaire ne se préoccupe pas de la façon dont la dépendance externe fonctionne. Il vérifie simplement que multipleCalls
fonctionne comme prévu.
- Pour simuler des modules, utilisez la méthode
mock
et passez un chemin de fichier, qui est le module :
const {
truncate,
} = require("./string-format")
jest.mock("./string-format.js")
Ce code imite toutes les fonctions exportées par string-format.js et vérifie combien de fois il les appelle. L’adresse truncate
du module devient une fonction fictive, ce qui fait perdre à la fonction sa logique d’origine. Vous pouvez savoir combien de fois truncate
s’exécute dans vos tests dans la propriété truncate.mock.calls.length
.
Si vous avez une erreur ou si votre code ne fonctionne pas, comparez votre code avec l’implémentation complète.
Tester les composants React avec Jest et la bibliothèque de test React
Si vous n’avez pas encore de projet pour suivre ce tutoriel, vous pouvez utiliser ce projet d’exemple React comme point de départ. La branche starter-files
vous permet de commencer à composer le code au fur et à mesure que vous suivez le tutoriel. Utilisez la branche main
comme référence pour vérifier votre code par rapport au code complet de ce tutoriel.
Vous pouvez utiliser Jest pour tester des frameworks JavaScript tels que React. Lorsque vous créez des projets React à l’aide de Create React App, ils prennent en charge la React Testing Library et Jest dès le départ. Si vous créez un projet React sans Create React App, installez Jest pour tester React avec Babel et la bibliothèque de test React. Si vous clonez la branche starter-app
, vous n’avez pas besoin d’installer des dépendances ou d’appliquer des configurations.
- Si vous utilisez le projet d’exemple, utilisez cette commande pour installer les dépendances nécessaires :
npm install --save-dev babel-jest @babel/preset-env @babel/preset-react react-testing-library
Vous pouvez également utiliser Enzyme à la place de React Testing Library.
- Mettez à jour vos configurations Babel dans babel.config.js ou créez ce fichier s’il n’existe pas :
module.exports = {
presets: [
'@babel/preset-env',
['@babel/preset-react', {runtime: 'automatic'}],
],
};
- Considérez le fichier src/SubmitButton.js qui contient le code suivant :
import React, { useState } from 'react'
export default function SubmitButton(props) {
const {id, label, onSubmit} = props
const [isLoading, setisLoading] = useState(false)
const submit = () => {
setisLoading(true)
onSubmit()
}
return
Ce composant SubmitButton
reçoit trois accessoires :
id
– L’identifiant du bouton.label
– Le texte à afficher dans le bouton.onSubmit
– La fonction à déclencher lorsque quelqu’un clique sur le bouton.
Le code attribue la propriété id
à l’attribut data-testid
, qui identifie un élément à tester.
Le composant suit également l’état isLoading
et le met à jour à true
lorsque quelqu’un clique sur le bouton.
- Créez le test pour ce composant. Placez le code suivant dans un fichier SubmitButton.test.js:
import {fireEvent, render, screen} from "@testing-library/react"
import "@testing-library/jest-dom"
import SubmitButton from "./SubmitButton"
test("SubmitButton becomes disabled after click", () => {
const submitMock = jest.fn()
render(
<SubmitButton
id="submit-details"
label="Submit"
onSubmit={submitMock}
/ >
)
expect(screen.getByTestId("submit-details")).not.toBeDisabled()
fireEvent.submit(screen.getByTestId("submit-details"))
expect(screen.getByTestId("submit-details")).toBeDisabled()
})
Le code ci-dessus rend le composant SubmitButton
et utilise la méthode de requête screen.getByTestId
pour obtenir le nœud du DOM par l’attribut data-testid
.
Le premier expect
est getByTestId("submit-details")
et utilise le modificateur not
et le comparateur toBeDisabled
(exposé à partir de react-testing-library
) pour affirmer que le bouton n’est pas désactivé. Utilisez le modificateur not
avec tous les matcheurs pour affirmer l’opposé du matcheur.
Ensuite, le code déclenche l’événement submit
sur le composant et vérifie que le bouton est désactivé. Vous pouvez trouver d’autres adaptateurs personnalisés dans la documentation de la bibliothèque de tests.
- Maintenant, exécutez les tests. Si vous avez cloné la branche
starter-files
, assurez-vous que toutes les dépendances du projet sont installées en exécutantnpm install
avant de lancer vos tests.
Exécuter des rapports de couverture de code
Jest propose également des rapports de couverture de code pour montrer la part de votre projet que vous testez.
- Passez l’option
--coverage
à Jest. Dans votre script Jest dans package.json (dans le projet JavaScript), mettez à jour la commande Jest avec cette option de couverture :
"scripts": {
"test": "jest --coverage"
}
- Exécutez
npm run test
pour tester votre code. Vous obtenez un rapport comme le suivant :
Ce rapport montre que Jest a testé 100% des fonctions dans
SubmitButton.j s et string-format.js. Il indique également que Jest n’a pas testé de déclarations et de lignes dans string-format.js. La couverture des tests montre que les lignes non couvertes dans string-format.js sont 7 et 12.
À la ligne 7, return str
dans la fonction truncate
ne s’exécute pas parce que la condition if (str.length <= count)
renvoie false
.
À la ligne 12, toujours dans la fonction truncate
, return substring
ne s’exécute pas car la condition if (!withEllipsis)
renvoie false.
Intégrer Jest à votre flux de développement
Voyons comment vous pouvez intégrer ces tests pour améliorer votre flux de développement.
Exécutez les tests en mode veille
Au lieu d’exécuter les tests manuellement, vous pouvez les exécuter automatiquement lorsque vous modifiez votre code en utilisant le mode de surveillance.
- Pour activer le mode veille, mettez à jour votre script de commande Jest dans package.json (dans le projet JavaScript) en ajoutant l’option
--watchAll
:
"scripts": {
"test": "jest --coverage --watchAll"
}
- Exécutez
npm run test
. Il déclenche Jest en mode veille :
Les tests s’exécutent à chaque fois que vous modifiez votre projet. Cette approche favorise un retour d’information continu au fur et à mesure que vous construisez votre application.
Mettre en place des hooks de pré-commit
Dans les environnements Git, les hooks exécutent des scripts à chaque fois qu’un événement particulier se produit (comme pull, push ou commit). Les hooks de pré-commit définissent les scripts à exécuter pour l’évènement de pré-commit (que le code déclenche avant d’effectuer une validation).
La validation ne réussit que si le script ne génère pas d’erreur.
L’exécution de Jest avant le pre-commit garantit qu’aucun de vos tests n’échoue avant la validation.
Vous pouvez utiliser diverses bibliothèques pour mettre en place des hooks git dans votre projet, comme ghooks.
- Installez
ghooks
sousdevDependencies
:
npm install ghooks --save-dev
- Ajoutez un objet
configs
au niveau supérieur de votre fichier package.json (dans le projet JavaScript). - Ajoutez un objet
ghooks
sousconfigs
.
- Ajoutez une propriété dont la clé est
pre-commit
et la valeurjest
.
{
…
"config": {
"ghooks": {
"pre-commit": "jest"
}
},
}
- Validez le code. Le code déclenche le hook pre-commit, qui exécute Jest :
Résumé
Vous savez maintenant comment intégrer Jest dans votre flux de développement pour qu’il s’exécute automatiquement chaque fois que vous effectuez une modification. Cette approche permet un retour d’information continu afin que vous puissiez corriger rapidement tout problème de code avant de mettre vos modifications en production.
En hébergeant votre application chez Kinsta, vous bénéficiez d’une infrastructure rapide et sécurisée, déployant vos projets sur une infrastructure construite sur le réseau Premium Tier et les machines C2 de Google Cloud Platform. Choisissez entre les 37 centres de données et un CDN compatible HTTP/3 avec 260+ PoP.
Restez en sécurité grâce à la technologie des conteneurs isolés, à deux pare-feu puissants et à une protection DDoS avancée alimentée par Cloudflare. Et vous pouvez intégrer des applications ou automatiser des flux de travail avec l’API Kinsta.
Configurez Jest et parcourez les ressources de Kinsta dès aujourd’hui pour améliorer vos applications JavaScript.
Laisser un commentaire