Jest est une bibliothèque pour tester le code JavaScript. C'est un projet open source maintenu par Facebook, et il est particulièrement bien adapté pour les tests de code React, bien que non limité à cela: il peut tester n'importe quel code JavaScript. Jest est très rapide et facile à utiliser
- Introduction à Jest
- Installation
- Créez le premier test Jest
- Exécuter Jest avec VS Code
- Matchers
- Installer
- Abattre
- Tests de groupe à l'aide de describe ()
- Test du code asynchrone
- Railleur
- Test de snapshot
Introduction à Jest
Jest est une bibliothèque pour tester le code JavaScript.
C'est un projet open source maintenu par Facebook, et il est particulièrement bien adapté pour les tests de code React, bien que non limité à cela: il peut tester n'importe quel code JavaScript. Ses atouts sont:
- c'est rapide
- il peut effectuertest d'instantané
- il est avisé et fournit tout ce qui est prêt à l'emploi sans vous obliger à faire des choix
Jest est un outil très similaire à Mocha, bien qu'il présente des différences:
- Mocha est moins opiniâtre, tandis que Jest a un certain ensemble de conventions
- Mocha nécessite plus de configuration, tandis que Jest fonctionne généralement hors de la boîte, grâce à son opinion
- Mocha est plus ancien et plus établi, avec plus d'intégrations d'outillage
À mon avis, la plus grande caractéristique de Jest est qu'il s'agit d'une solution prête à l'emploi qui fonctionne sans avoir à interagir avec d'autres bibliothèques de test pour effectuer son travail.
Installation
Jest est automatiquement installé danscreate-react-app
, donc si vous l'utilisez, vous n'avez pas besoin d'installer Jest.
Jest peut être installé dans n'importe quel autre projet en utilisantFil:
yarn add --dev jest
ounpm:
npm install --save-dev jest
remarquez comment nous demandons à tous les deux de mettre Jest dans ledevDependencies
partie de lapackage.json
fichier, de sorte qu'il ne sera installé que dans l'environnement de développement et non en production.
Ajoutez cette ligne aux scripts de votrepackage.json
déposer:
{
"scripts": {
"test": "jest"
}
}
afin que les tests puissent être exécutés en utilisantyarn test
ounpm run test
.
Vous pouvez également installer Jest globalement:
yarn global add jest
et exécutez tous vos tests en utilisant lejest
outil de ligne de commande.
Créez le premier test Jest
Projets créés aveccreate-react-app
avoir Jest installé et préconfiguré prêt à l'emploi, mais l'ajout de Jest à n'importe quel projet est aussi simple que de taper
yarn add --dev jest
Ajoutez à votrepackage.json
cette ligne:
{
"scripts": {
"test": "jest"
}
}
et lancez vos tests en exécutantyarn test
dans votre coquille.
Maintenant, vous n'avez aucun test ici, donc rien ne sera exécuté:
Créons le premier test. Ouvrir unmath.js
fichier et tapez quelques fonctions que nous testerons plus tard:
const sum = (a, b) => a + b
const mul = (a, b) => a * b
const sub = (a, b) => a - b
const div = (a, b) => a / b
module.exports = { sum, mul, sub, div }
Créez maintenant unmath.test.js
fichier, dans le même dossier, et là, nous utiliserons Jest pour tester les fonctions définies dansmath.js
:
const { sum, mul, sub, div } = require('./math')
test(‘Adding 1 + 1 equals 2’, () => {
expect(sum(1, 1)).toBe(2)
})
test(‘Multiplying 1 * 1 equals 1’, () => {
expect(mul(1, 1)).toBe(1)
})
test(‘Subtracting 1 - 1 equals 0’, () => {
expect(sub(1, 1)).toBe(0)
})
test(‘Dividing 1 / 1 equals 1’, () => {
expect(div(1, 1)).toBe(1)
})
Fonctionnementyarn test
entraîne l'exécution de Jest sur tous les fichiers de test qu'il trouve et nous renvoie le résultat final:
Exécuter Jest avec VS Code
Visual Studio Code est un excellent éditeur pour le développement JavaScript. LeExtension de plaisanterieoffre une intégration de premier ordre pour nos tests.
Une fois que vous l'avez installé, il détectera automatiquement si vous avez installé Jest dans vos devDependencies et exécutera les tests. Vous pouvez également appeler les tests manuellement en sélectionnant leBlague: Start Runnercommander. Il exécutera les tests et restera en mode veille pour les réexécuter chaque fois que vous modifiez l'un des fichiers qui ont un test (ou un fichier de test):
Matchers
Dans l'article précédent, j'ai utilisétoBe()
comme le seulmatcher:
test('Adding 1 + 1 equals 2', () => {
expect(sum(1, 1)).toBe(2)
})
Un matcher est une méthode qui vous permet de tester des valeurs.
Matchers les plus couramment utilisés, comparant la valeur du résultat deexpect()
avec la valeur passée en argument, sont:
toBe
compare l'égalité stricte, en utilisant===
toEqual
compare les valeurs de deux variables. S'il s'agit d'un objet ou d'un tableau, il vérifie l'égalité de toutes les propriétés ou élémentstoBeNull
est vrai lors du passage d'une valeur nulletoBeDefined
est vrai lors du passage d'une valeur définie (à l'opposé de ce qui précède)toBeUndefined
est vrai lors du passage d'une valeur indéfinietoBeCloseTo
est utilisé pour comparer des valeurs flottantes, évitant les erreurs d'arronditoBeTruthy
true si la valeur est considérée comme vraie (comme unif
Est-ce que)toBeFalsy
true si la valeur est considérée comme false (comme unif
Est-ce que)toBeGreaterThan
true si le résultat de expect () est supérieur à l'argumenttoBeGreaterThanOrEqual
true si le résultat de expect () est égal à l'argument, ou supérieur à l'argumenttoBeLessThan
true si le résultat de expect () est inférieur à l'argumenttoBeLessThanOrEqual
true si le résultat de expect () est égal à l'argument, ou inférieur à l'argumenttoMatch
est utilisé pour comparer des chaînes avecexpression régulièrecorrespondance de modèletoContain
est utilisé dans les tableaux, true si le tableau attendu contient l'argument dans son ensemble d'élémentstoHaveLength(number)
: vérifie la longueur d'un tableautoHaveProperty(key, value)
: vérifie si un objet a une propriété, et vérifie éventuellement sa valeurtoThrow
vérifie si une fonction que vous passez lève une exception (en général) ou une exception spécifiquetoBeInstanceOf()
: vérifie si un objet est une instance d'une classe
Tous ces matchers peuvent être annulés en utilisant.not.
à l'intérieur de l'instruction, par exemple:
test('Adding 1 + 1 does not equal 3', () => {
expect(sum(1, 1)).not.toBe(3)
})
Pour une utilisation avec des promesses, vous pouvez utiliser.resolves
et.rejects
:
expect(Promise.resolve('lemon')).resolves.toBe('lemon')
expect(Promise.reject(new Error(‘octopus’))).rejects.toThrow(‘octopus’)
Installer
Avant d'exécuter vos tests, vous souhaiterez effectuer une initialisation.
Pour faire quelque chose une fois avant l'exécution de tous les tests, utilisez lebeforeAll()
fonction:
beforeAll(() => {
//do something
})
Pour effectuer quelque chose avant chaque test, utilisezbeforeEach()
:
beforeEach(() => {
//do something
})
Abattre
Tout comme vous pouvez le faire avec la configuration, vous pouvez également effectuer quelque chose après chaque exécution de test:
afterEach(() => {
//do something
})
et après la fin de tous les tests:
afterAll(() => {
//do something
})
Tests de groupe à l'aide de describe ()
Vous pouvez créer des groupes de tests, dans un seul fichier, qui isolent les fonctions de configuration et de démontage:
describe('first set', () => {
beforeEach(() => {
//do something
})
afterAll(() => {
//do something
})
test(/*...*/)
test(/*...*/)
})
describe(‘second set’, () => {
beforeEach(() => {
//do something
})
beforeAll(() => {
//do something
})
test(/…/)
test(/…/)
})
Test du code asynchrone
Le code asynchrone dans JavaScript moderne peut avoir essentiellement 2 formes: les rappels et les promesses. En plus des promesses, nous pouvons utiliser async / await.
Rappels
Vous ne pouvez pas avoir de test dans un rappel, car Jest ne l'exécutera pas - l'exécution du fichier de test se termine avant l'appel du rappel. Pour résoudre ce problème, transmettez un paramètre à la fonction de test, que vous pouvez facilement appelerdone
. Jest attendra que vous appeliezdone()
avant de terminer ce test:
//uppercase.js
function uppercase(str, callback) {
callback(str.toUpperCase())
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./src/uppercase’)
test(uppercase 'test' to equal 'TEST'
, (done) => {
uppercase(‘test’, (str) => {
expect(str).toBe(‘TEST’)
done()
}
})
Promesses
Avec des fonctions qui renvoient des promesses, nousretourner une promessedu test:
//uppercase.js
const uppercase = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject('Empty string')
return
}
resolve(str.toUpperCase())
})
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./uppercase’)
test(uppercase 'test' to equal 'TEST'
, () => {
return uppercase(‘test’).then(str => {
expect(str).toBe(‘TEST’)
})
})
Les promesses rejetées peuvent être testées en utilisant.catch()
:
//uppercase.js
const uppercase = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject('Empty string')
return
}
resolve(str.toUpperCase())
})
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./uppercase’)
test(uppercase 'test' to equal 'TEST'
, () => {
return uppercase(’’).catch(e => {
expect(e).toMatch(‘Empty string’)
})
})
Asynchroniser / attendre
Pour tester les fonctions qui renvoient des promesses, nous pouvons également utiliser async / await, ce qui rend la syntaxe très directe et simple:
//uppercase.test.js
const uppercase = require('./uppercase')
test(`uppercase 'test' to equal 'TEST'`, async () => {
const str = await uppercase('test')
expect(str).toBe('TEST')
})
Railleur
En test,railleurvous permet de tester des fonctionnalités qui dépendent de:
- Base de données
- Réseaudemandes
- accès àDes dossiers
- toutExternesystème
de sorte que:
- vos tests sont exécutésplus rapide, donnant un délai d'exécution rapide pendant le développement
- vos tests sontindépendantdes conditions du réseau ou de l'état de la base de données
- vos tests nepolluertout stockage de données car ils ne touchent pas la base de données
- toute modification effectuée dans un test ne change pas l'état des tests suivants, et la réexécution de la suite de tests doit commencer à partir d'un point de départ connu et reproductible
- vous n'avez pas à vous soucier de la limitation du débit sur les appels d'API et les demandes réseau
La moquerie est utile lorsque vous voulez éviter les effets secondaires (par exemple l'écriture dans une base de données) ou que vous voulez sauter des portions de code lentes (comme l'accès au réseau), et évite également les implications avec l'exécution de vos tests plusieurs fois (par exemple, imaginez une fonction qui envoie un e-mail ou appelle une API à taux limité).
Plus important encore, si vous écrivez unTest de l'unité, vous devez tester la fonctionnalité d'une fonction de manière isolée, pas avec tout son bagage de choses qu'elle touche.
En utilisant des simulations, vous pouvez vérifier si une fonction de module a été appelée et quels paramètres ont été utilisés, avec:
expect().toHaveBeenCalled()
: vérifier si une fonction espionnée a été appeléeexpect().toHaveBeenCalledTimes()
: compte combien de fois une fonction espionnée a été appeléeexpect().toHaveBeenCalledWith()
: vérifier si la fonction a été appelée avec un jeu de paramètres spécifiqueexpect().toHaveBeenLastCalledWith()
: vérifier les paramètres de la dernière fois que la fonction a été appelée
Espionner les packages sans affecter le code des fonctions
Lorsque vous importez un package, vous pouvez dire à Jest "d'espionner" l'exécution d'une fonction particulière, en utilisantspyOn()
, sans affecter le fonctionnement de cette méthode.
Exemple:
const mathjs = require('mathjs')
test(The mathjs log function
, () => {
const spy = jest.spyOn(mathjs, ‘log’)
const result = mathjs.log(10000, 10)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
Simulez un paquet entier
Jest fournit un moyen pratique de simuler un package entier. Créer un__mocks__
à la racine du projet, et dans ce dossier, créez un fichier JavaScript pour chacun de vos packages.
Dites que vous importezmathjs
. Créer un__mocks__/mathjs.js
à la racine de votre projet et ajoutez ce contenu:
module.exports = {
log: jest.fn(() => 'test')
}
Cela simulera la fonction log () du package. Ajoutez autant de fonctions que vous voulez vous moquer:
const mathjs = require('mathjs')
test(The mathjs log function
, () => {
const result = mathjs.log(10000, 10)
expect(result).toBe(‘test’)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
Simulez une seule fonction
Vous pouvez vous moquer d'une seule fonction en utilisantjest.fn()
:
const mathjs = require('mathjs')
mathjs.log = jest.fn(() => ‘test’)
test(The mathjs log function
, () => {
const result = mathjs.log(10000, 10)
expect(result).toBe(‘test’)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
Vous pouvez aussi utiliserjest.fn().mockReturnValue('test')
pour créer un simulacre simple qui ne fait rien sauf renvoyer une valeur.
Maquettes pré-construites
Vous pouvez trouver des modèles préfabriqués pour les bibliothèques populaires. Par exemple ce packagehttps://github.com/jefflau/jest-fetch-mockvous permet de vous moquerfetch()
appels et fournissez des exemples de valeurs de retour sans interagir avec le serveur réel dans vos tests.
Test de snapshot
Le test d'instantané est une fonctionnalité assez intéressante proposée par Jest. Il peut mémoriser le rendu de vos composants d'interface utilisateur et le comparer au test actuel, ce qui génère une erreur en cas de non-concordance.
Ceci est un test simple sur le composant App d'un simplecreate-react-app
application (assurez-vous d'installerreact-test-renderer
):
import React from 'react'
import App from './App'
import renderer from 'react-test-renderer'
it(‘renders correctly’, () => {
const tree = renderer.create(<App />).toJSON()
expect(tree).toMatchSnapshot()
})
la première fois que vous exécutez ce test, Jest enregistre l'instantané dans le__snapshots__
dossier. Voici ce que contient App.test.js.snap:
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div
className="App"
>
<header
className="App-header"
>
<img
alt="logo"
className="App-logo"
src="logo.svg"
/>
<h1
className="App-title"
>
Welcome to React
</h1>
</header>
<p
className="App-intro"
>
To get started, edit
<code>
src/App.js
</code>
and save to reload.
</p>
</div>
`
Comme vous le voyez, c'est le code que le composant App rend, rien de plus.
La prochaine fois que le test compare la sortie de<App />
pour ça. Si l'application change, vous obtenez une erreur:
Lors de l'utilisationyarn test
danscreate-react-app
vous êtes dansmode montre, et à partir de là, vous pouvez appuyer surw
et afficher plus d'options:
Watch Usage
› Press u to update failing snapshots.
› Press p to filter by a filename regex pattern.
› Press t to filter by a test name regex pattern.
› Press q to quit watch mode.
› Press Enter to trigger a test run.If your change is intended, pressing u
will update the failing snapshots, and make the test pass.
You can also update the snapshot by running jest -u
(or jest --updateSnapshot
) outside of watch mode.
More devtools tutorials:
- Introduction to Yeoman
- Bower, the browser package manager
- Introduction to Frontend Testing
- Using node-webkit to create a Desktop App
- VS Code: use language-specific settings
- Introduction to Webpack
- A short and simple guide to Babel
- An introduction to Yarn
- Overview of the Browser DevTools
- Format your code with Prettier
- Keep your code clean with ESLint
- A list of cool Chrome DevTools Tips and Tricks
- Testing JavaScript with Jest
- How to use Visual Studio Code
- Introduction to Electron
- Parcel, a simpler webpack
- An Emmet reference for HTML
- The V8 JavaScript Engine
- Configuring VS Code
- Configuring the macOS command line
- How to disable an ESLint rule
- How to open VS Code from the command line
- How to set up hot reload on Electron