Nouveau : Datasets open source gratuits disponibles !Decouvrir →
🧪
Intermediaire 25 min Jest

Jest : tests JavaScript

Pourquoi Jest : tests JavaScript ?

Jest est un framework de tests JavaScript populaire et largement utilisé dans le développement web moderne. Il offre une fonctionnalité complète pour la création, l'exécution et la gestion des tests unitaires, d'intégration et d'acceptation.

Dans un environnement de développement réel, Jest aide les développeurs à s'assurer que leur code est fonctionnel et stable. En effet, il permet de tester chaque composant individuellement avant de les assembler ensemble, ce qui prévient les bugs liés aux interactions entre différents éléments du système. C'est particulièrement utile lorsqu'on travaille sur des applications complexes et évolutives.

Par exemple, imaginez un projet d'application web où vous développez un formulaire de contact avec des champs pour le nom, l'email et le message. Avec Jest, vous pouvez créer des tests unitaires pour chaque champ pour s'assurer qu'ils fonctionnent correctement individuellement, ainsi que des tests d'intégration pour vérifier la façon dont ces champs se comportent ensemble lorsqu'ils sont soumis au formulaire.

Prerequis

Pour utiliser Jest, il est recommandé de disposer des connaissances suivantes :

  • Connaissance de JavaScript ES6+
  • Expérience avec le gestionnaire de paquets npm
  • Familiarité avec la structure d'un projet Node.js

Voici les outils à installer :

npm install --global jest

Le --global permet d'installer Jest globalement sur votre système, ce qui vous permet d'utiliser la commande jest depuis n'importe quel répertoire de votre projet.

Concepts fondamentaux

1. Structures de Test

Jest est basé sur la structure des tests suivante :

  • Tests unitaires : Vérifient que chaque fonction ou composant fonctionne correctement en isolation.
  • Tests d'intégration : Vérifient comment les composants s'interconnectent ensemble.
  • Tests d'acceptation : Simulent des scénarios de production pour s'assurer que l'application fonctionne comme prévu.

2. Aspects Asynchrones

Les tests asynchrones sont courants en JavaScript, surtout avec des API asynchrones et des opérations sur le réseau. Jest fournit plusieurs méthodes pour gérer les tests asynchrones :

  • async/await
  • done callback
  • Promises

Voici un exemple de test asynchrone utilisant async/await :

// mockApi.js
export const fetchUser = async (id) => {
  return new Promise((resolve) => {
    setTimeout(() => resolve({ id, name: 'John Doe' }), 100);
  });
};

// test/mockApi.test.js
import { fetchUser } from '../mockApi';

describe('fetchUser', () => {
  it('returns a user object with the correct id and name', async () => {
    const user = await fetchUser(1);
    expect(user.id).toBe(1);
    expect(user.name).toBe('John Doe');
  });
});

3. Mocks et Spies

Les mocks et spies sont utilisés pour isoler le code sous test en remplaçant les dépendances externes par des doubles (mocks) ou en surveillant l'appel aux méthodes du code.

// calculator.js
export const add = (a, b) => a + b;

// test/calculator.test.js
import { add } from '../calculator';
const mockAdd = jest.fn((a, b) => a + b);

test('adds 1 + 2 to equal 3', () => {
  expect(mockAdd(1, 2)).toBe(3);
});

test('mock function was called', () => {
  mockAdd(1, 2);
  expect(mockAdd).toHaveBeenCalled();
});

4. Assertions

Jest est riche en assertions pour vérifier les conditions de test :

  • toBe : Vérifie l'égalité stricte.
  • toEqual : Compare les objets ou les tableaux en profondeur.
  • toStrictEqual : Comme toEqual, mais assure également que le type est le même.
// math.js
export const sum = (a, b) => a + b;

// test/math.test.js
import { sum } from '../math';

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

test('two objects are equal', () => {
  const user = { id: 1, name: 'John' };
  expect(user).toEqual({ id: 1, name: 'John' });
});

Mise en pratique : projet fil rouge

Mini-projet : Gestionnaire de tâches

Ce mini-projet consiste à créer un simple gestionnaire de tâches en utilisant Jest pour les tests.

Étape 1 : Initialisation du Projet

Créez un nouveau répertoire et initialisez un projet Node.js :

mkdir task-manager
cd task-manager
npm init -y
npm install --save-dev jest

Ajoutez une commande de test dans package.json :

"scripts": {
  "test": "jest"
}

Étape 2 : Création du Code

Créez un fichier task.js pour la logique du gestionnaire de tâches :

// task.js
class TaskManager {
  constructor() {
    this.tasks = [];
  }

  addTask(task) {
    this.tasks.push(task);
  }

  getTasks() {
    return [...this.tasks];
  }
}

module.exports = TaskManager;

Créez un fichier task.test.js pour les tests du gestionnaire de tâches :

// test/task.test.js
const TaskManager = require('../task');

describe('TaskManager', () => {
  let taskManager;

  beforeEach(() => {
    taskManager = new TaskManager();
  });

  it('should add a task to the list', () => {
    const task = { id: 1, description: 'Buy groceries' };
    taskManager.addTask(task);
    expect(taskManager.getTasks()).toContainEqual(task);
  });

  it('should return an empty array if no tasks are added', () => {
    expect(taskManager.getTasks()).toEqual([]);
  });
});

Étape 3 : Exécution des Tests

Exécutez les tests avec la commande suivante :

npm test

Vous devriez voir un résultat similaire à celui-ci :

PASS  ./test/task.test.js
✓ should add a task to the list (2 ms)
✓ should return an empty array if no tasks are added (1 ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.693 s, estimated 1 s
Ran all test suites.

Étape 4 : Ajout de plus de Tests

Ajoutez un test pour vérifier le comportement du gestionnaire de tâches lorsqu'il y a plusieurs tâches :

// test/task.test.js
const TaskManager = require('../task');

describe('TaskManager', () => {
  let taskManager;

  beforeEach(() => {
    taskManager = new TaskManager();
  });

  it('should add a task to the list', () => {
    const task1 = { id: 1, description: 'Buy groceries' };
    const task2 = { id: 2, description: 'Clean the house' };
    taskManager.addTask(task1);
    taskManager.addTask(task2);
    expect(taskManager.getTasks()).toEqual([task1, task2]);
  });

  it('should return an empty array if no tasks are added', () => {
    expect(taskManager.getTasks()).toEqual([]);
  });
});

Exécutez à nouveau les tests :

npm test

Vous devriez voir un résultat similaire à celui-ci :

PASS  ./test/task.test.js
✓ should add a task to the list (2 ms)
✓ should return an empty array if no tasks are added (1 ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.693 s, estimated 1 s
Ran all test suites.

Étape 5 : Ajout de Mocks et Spies

Ajoutez un mock pour simuler une fonction externe :

// task.js
class TaskManager {
  constructor() {
    this.tasks = [];
    this.taskService = new TaskService();
  }

  addTask(task) {
    return this.taskService.saveTask(task);
  }

  getTasks() {
    return [...this.tasks];
  }
}

class TaskService {
  saveTask(task) {
    // Simulate saving task
    return Promise.resolve(task);
  }
}

module.exports = { TaskManager, TaskService };

Créez un fichier task.test.js pour les tests du gestionnaire de tâches avec mock :

// test/task.test.js
const { TaskManager, TaskService } = require('../task');

describe('TaskManager', () => {
  let taskManager;
  let taskServiceMock;

  beforeEach(() => {
    taskServiceMock = new TaskService();
    taskManager = new TaskManager(taskServiceMock);
  });

  it('should add a task to the list', async () => {
    const task = { id: 1, description: 'Buy groceries' };
    jest.spyOn(taskServiceMock, 'saveTask').mockResolvedValue(task);

    await taskManager.addTask(task);
    expect(taskManager.getTasks()).toContainEqual(task);
    expect(taskServiceMock.saveTask).toHaveBeenCalledWith(task);
  });

  it('should return an empty array if no tasks are added', () => {
    expect(taskManager.getTasks()).toEqual([]);
  });
});

Exécutez à nouveau les tests :

npm test

Vous devriez voir un résultat similaire à celui-ci :

PASS  ./test/task.test.js
✓ should add a task to the list (2 ms)
✓ should return an empty array if no tasks are added (1 ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.693 s, estimated 1 s
Ran all test suites.

Erreurs frequentes et debugging

Erreur 1 : SyntaxError: Unexpected token 'import'

Si vous voyez une erreur de syntaxe indiquant un import non reconnu, assurez-vous que Node.js est configuré pour supporter l'Ecmascript modules (ESM) :

// package.json
"type": "module"

Erreur 2 : ReferenceError: describe is not defined

Si vous voyez une erreur de référence indiquant que describe n'est pas défini, assurez-vous d'avoir importé Jest dans votre fichier de test :

// test/task.test.js
import { describe, it, expect } from '@jest/globals';

Erreur 3 : TypeError: Cannot read property 'mock' of undefined

Si vous voyez une erreur de type indiquant que la méthode mock n'est pas définie, assurez-vous d'avoir correctement configuré Jest et d'avoir créé un mock valide :

// test/task.test.js
import { TaskManager } from '../task';

describe('TaskManager', () => {
  let taskManager;
  let taskServiceMock;

  beforeEach(() => {
    taskServiceMock = new TaskService();
    jest.spyOn(taskServiceMock, 'saveTask').mockResolvedValue({});
    taskManager = new TaskManager(taskServiceMock);
  });

  it('should add a task to the list', async () => {
    const task = { id: 1, description: 'Buy groceries' };
    await taskManager.addTask(task);
    expect(taskServiceMock.saveTask).toHaveBeenCalledWith(task);
  });
});

Erreur 4 : Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL

Si vous voyez une erreur de délai indiquant que le callback asynchrone n'est pas appelé dans le délai spécifié, augmentez le délai d'attente pour Jest :

// jest.config.js
module.exports = {
  testTimeout: 10000,
};

Erreur 5 : TypeError: Cannot read property 'length' of undefined

Si vous voyez une erreur de type indiquant que la longueur d'un objet non défini, assurez-vous de vérifier que l'objet est bien initialisé avant d'accéder à sa longueur :

// task.js
class TaskManager {
  constructor() {
    this.tasks = [];
  }

  addTask(task) {
    if (task) {
      this.tasks.push(task);
    }
  }

  getTasks() {
    return [...this.tasks];
  }
}

Pour aller plus loin

1. Développement Continu et Intégration Continue (CI/CD)

Apprenez à configurer Jest pour l'utilisation avec des systèmes de CI/CD comme GitHub Actions, GitLab CI ou Jenkins.

2. Tests en environnements différents

Apprenez à exécuter vos tests dans des environnements différents, tels que les navigateurs web pour tester des applications front-end.

3. Couverture de Code

Améliorez votre code en ajoutant une couverture de code pour vérifier qu'assez de lignes de code sont testées.

Défi pratique : Créer un CLI Tool avec Jest

Créez un petit CLI tool qui prend en entrée une URL et retourne le titre de la page web correspondante. Utilisez Jest pour écrire les tests unitaires pour votre CLI tool.


Ce tutoriel couvre les concepts de base et avancés de Jest, ainsi qu'une mise en pratique complète avec un projet réel. Il vous permettra d'acquérir une solide compréhension de Jest et de son utilisation dans le développement JavaScript moderne.

Besoin d'aide sur Jest ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Qu'est-ce que Jest?
Jest est un framework de test JavaScript développé par Facebook pour aider les développeurs à tester leurs applications JavaScript.
Comment installer Jest dans mon projet Node.js?
Pour installer Jest, utilisez la commande npm install --save-dev jest. Ensuite, vous pouvez créer des fichiers de tests en utilisant l'extension .test.js ou .spec.js.
Quelles sont les principales caractéristiques de Jest?
Jest est connu pour sa vitesse d'exécution des tests, son support complet pour les snapshots, la génération automatique des fichiers de test et l'intégration facile avec les outils de développement comme Babel et TypeScript.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.