Comment démarrer avec Jest pour les tests unitaires JavaScript
Jest est un framework pour exécuter des «tests unitaires», un moyen pour vous de tester les fonctions et les composants individuels de votre base de code pour vous assurer que les commits futurs ne cassent pas quelque chose d'inattendu. Nous allons vous montrer comment le configurer et l'utiliser avec un framework frontal tel que React.
Sommaire
Qu'est-ce que le test unitaire?
Les tests sont très importants lorsque vous travaillez avec une équipe de programmeurs. Tous les commits envoyés à votre contrôle de code source doivent être automatiquement créés et testés pour vous assurer de ne rien casser accidentellement. Pour que tout le monde reste sain d'esprit, l'ensemble du pipeline peut être automatisé avec un logiciel comme Jenkins, mais pour exécuter les tests réels, vous devrez utiliser un cadre de test unitaire comme Jest.
Jest est un framework pour exécuter des «tests unitaires». Une «unité» peut être n'importe quel nombre de choses – une fonction, une classe ou un composant – elle représente simplement la plus petite unité de code que vous devriez tester, pour vous assurer que les futures mises à jour de code ne cassent rien. Si vous écrivez une fonction qui récupère des données d'un point de terminaison et renvoie une sortie, vous allez écrire un test unitaire correspondant qui prendra cette fonction, l'appellera et enregistrera la sortie. Ensuite, vous pouvez faire des affirmations en fonction de ce qu'il a renvoyé. Est-il formaté correctement? Certaines valeurs ne sont-elles pas définies? Fonctionne-t-il comme prévu? Si l'un de ces tests échoue, c'est qu'il y a un problème dans votre code.
Jest peut également être utilisé pour exécuter des tests sur des applications Web. Il est couramment utilisé avec des frameworks basés sur les données comme React pour garantir que les composants ont l'état et les accessoires appropriés pour une entrée donnée.
Bien que les tests unitaires puissent sembler fastidieux à écrire, et que cela représente certainement plus de travail, cela conduit généralement à de meilleures bases de code à la fin. Traiter du code hérité est un problème pour cette raison exactement: laisser des commentaires appropriés aide, mais écrire un test unitaire revient à écrire de la documentation pour vos fonctions. Vous définissez quelle entrée entre, comment l'utiliser et quelle entrée doit être attendue.
Premiers pas avec Jest
Pour configurer un environnement de test simple, créez un nouveau projet avec npm init -y
et installez Jest en tant que dépendance de développement à partir de npm
:
npm install --save-dev jest
Pour exécuter des tests à partir de la ligne de commande, vous devez ajouter un script simple dans package.json
qui appelle Jest:
"scripts": { "test": "jest" }
Vous aurez besoin d'une fonction à tester, alors créez un nouveau fichier sous src/doSomeMath.js
et définissez-le pour exporter une fonction:
function doSomeMath(a, b) { return a + b; } module.exports = doSomeMath;
Enregistrez ce fichier et ouvrez tests/doSomeMath.test.js
. Jest cherchera automatiquement dans le test/
répertoire pour trouver les tests à exécuter. Ce fichier agit comme un fichier compagnon pour doSomeMath.js
, et définit une suite de tests pour vérifier que toutes les fonctions fonctionnent correctement. Un test Jest de base ressemble à ceci:
test('Description', () => { expect(functionName(args)).toBe(result); });
Fondamentalement, un test()
La fonction encapsule tout le code du test. Chaque expect()
block appelle une fonction (c'est-à-dire une unité), puis transmet la valeur au «matcher». Dans ce cas, c'est le toBe()
fonction, qui vérifie l'égalité simple.
Jest a un lot de différents correspondants, que vous pouvez tout lire dans leurs documents. Pour n'en nommer que quelques-uns:
.not.matcher()
gère l'inversion de n'importe quel matcher.toBe()
vérifie l'égalité exacte (Object.is) mais ne gère notamment pas les objets.toEqual()
vérifie l'égalité profonde des objets.toStrictEqual()
est le même quetoEqual
mais s'assure également qu'aucun objet n'a de propriétés supplémentaires non définies.toBeTruthy()
ettoBeFalsy()
vérifier tout ce qui évaluetrue
oufalse
dans unif
déclaration.-
toBeNull()
,toBeUndefined()
, ettoBeDefined()
tous vérifient les différents états des objets. toContain()
vérifie le contenu du tableau.toMatch()
fait correspondre une expression régulière à une chaîne.toThrow()
s'assure que le code générera une erreur (généralement pour tester une entrée incorrecte).
Pour cette suite de tests, vous devrez importer votre fonction et transmettre certains arguments et résultats. Vous pouvez et devez généralement inclure plusieurs expect
blocs dans un seul test pour couvrir plusieurs scénarios.
const doSomeMath = require('../src/doSomeMath'); test('adds 2 + 2 to equal 4', () => { expect(doSomeMath(1, 1)).toBe(2); expect(doSomeMath(2, 2)).toBe(4); });
Enregistrez ce fichier, puis exécutez:
npm run test
Cela exécutera toutes vos suites de tests et affichera les résultats pour chacune d'elles.
Tout devrait passer, à condition que les maths fonctionnent correctement. En cas d'échec, Jest vous donnera une description détaillée de ce qui n'a pas fonctionné, vous aidant à localiser le problème.
Comme le code Jest n'est que du JavaScript, vous pouvez créer un script de vos tests assez facilement. Par exemple, vous pouvez utiliser une boucle for et appeler expect
plusieurs fois avec entrée itérative. Si une exécution de expect
échoue, le test lui-même échouera.
test('adds 2 + 2 to equal 4', () => { for (let a = 1; a < 10; a++) { expect(doSomeMath(a, 5)).toBe(a + 5) } });
Vous pouvez utiliser cette fonctionnalité pour beaucoup de choses, mais la plupart des tests feront généralement trois choses principales:
- Organiser, où les données sont préparées pour l'unité
- Act, où l'unité est appelée, a transmis les données arrangées et la sortie est enregistrée
- Assert, où vous exécutez tous vos matchers pour vous assurer que tout fonctionne comme prévu
Tester avec React
S'assurer que les mathématiques fonctionnent est cool et tout, mais vous n'avez probablement pas l'intention d'utiliser Jest pour quelque chose d'aussi simple que cela. Vous êtes probablement intéressé par l'utilisation de Jest pour automatiser les tests d'une application JavaScript, peut-être construite avec un framework tel que React. Bien que vous devriez toujours faire des tests complets de l'interface utilisateur avec une révision manuelle, Jest peut toujours être utilisé pour tester les composants React de manière isolée. Après tout, les composants React ne sont en réalité que des fonctions qui renvoient une sortie JSX - cela peut être comparé et testé.
Pour commencer, configurez un nouveau projet React avec create-react-app
:
npx create-react-app jest-react
Create React App installe Jest par défaut, ainsi que React Testing Library, qui contient des gestionnaires utiles pour travailler avec React dans Jest.
Modifier la valeur par défaut App.js
composant à ce qui suit:
import React, {useState} from 'react'; import './App.css'; function App() { const (disabled, setDisabled) = useState(false); function handleClick() { setDisabled(!disabled); } return ( ); } export default App;
Ce morceau de code absolument inutile définit un bouton qui, une fois cliqué, définit une variable d'état qui est utilisée pour désactiver tous les autres clics de ce bouton.
S'ouvrir App.test.js
, qui est déjà créé par Create React App pour contenir un test du logo React par défaut. Au lieu de cela, modifiez le test par défaut comme suit:
import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import App from './App'; test('disabled button on click', () => { const button = render().getByTestId('useless-button'); expect(button.disabled).toBeFalsy(); fireEvent.click(button, {button: 1}); expect(button.disabled).toBeTruthy(); });
Ce test rend le composant à l'aide des rendus de React Testing Library et trouve le bouton en fonction de l'ID de test que nous lui avons donné (cependant, il existe de nombreux sélecteurs différents qui n'encombreront pas le code de votre composant). Il s'assure que le bouton n'est pas désactivé dès le départ, puis déclenche un événement de clic. (Notez que {button: 1}
est simplement le code du clic gauche.) L'état se met à jour, ce qui déclenche un rendu, et nous vérifions à nouveau que le bouton est maintenant désactivé.
Il est important de toujours tester la sortie des fonctions. La plupart du temps, vous ne vous souciez pas exactement de la façon dont la fonction est implémentée sous le capot, mais simplement du fait qu'elle renvoie la sortie correcte. Ce composant est simplement une fonction qui renvoie un bouton qui peut ou non être désactivé. Nous ne nous soucions pas que le bouton utilise l'API d'état de React sous le capot, nous testons donc si le code HTML renvoyé contient ou non un bouton désactivé. Cela ne veut pas dire que vous ne pouvez pas tester l’état, mais vous devez vous demander si cela est nécessaire ou non.