Tests en TypeScript : Unit, Intégration, E2E — guide complet

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi tester le code TypeScript ?

TypeScript est un outil puissant qui ajoute le typage statique à JavaScript, permettant de détecter les erreurs lors de la compilation. Cependant, même le système de typage le plus strict ne garantit pas que votre code fonctionnera correctement dans des conditions réelles. Les erreurs logiques, le traitement incorrect des cas limites et les problèmes d'intégration des modules restent en dehors du compilateur. C'est là que les tests entrent en jeu.

Les tests en TypeScript ne se limitent pas à la vérification de fonctions. Il s'agit d'un processus complet qui comprend trois niveaux clés : Unit (tests unitaires), Integration (tests d'intégration) et E2E (tests de bout en bout). Chacun répond à un objectif spécifique et ensemble, ils forment la "pyramide des tests", garantissant la fiabilité de l'application.

Dans cet article, nous allons voir comment écrire des tests pour TypeScript à ces trois niveaux, en utilisant des outils modernes : Jest, Supertest et Playwright. Vous découvrirez quelles erreurs ces tests aident à prévenir et comment les intégrer dans votre projet.

Tests unitaires : Vérification des modules isolés

Les tests unitaires sont la base de la pyramide. Ils testent des fonctions, classes ou méthodes individuelles en isolation des dépendances externes (base de données, API, système de fichiers). L'objectif principal est de s'assurer que chaque "brique" de votre application fonctionne correctement.

Outils et configuration

Le framework le plus populaire pour les tests unitaires en TypeScript est Jest. Il offre un support intégré pour TypeScript via ts-jest ou @swc/jest.

Installation de Jest dans un projet :

npm install --save-dev jest @types/jest ts-jest
npx ts-jest config:init

Exemple de test unitaire

Considérons une fonction simple pour calculer une réduction :

// discount.ts
export function applyDiscount(price: number, discountPercent: number): number {
  if (discountPercent < 0 || discountPercent > 100) {
    throw new Error('Le pourcentage de réduction doit être compris entre 0 et 100');
  }
  return price - (price * discountPercent) / 100;
}

Écrivons des tests unitaires couvrant les scénarios principaux :

// discount.test.ts
import { applyDiscount } from './discount';

describe('applyDiscount', () => {
  it('doit appliquer correctement une réduction de 20%', () => {
    expect(applyDiscount(100, 20)).toBe(80);
  });

  it('doit retourner le prix d\'origine avec une réduction de 0%', () => {
    expect(applyDiscount(50, 0)).toBe(50);
  });

  it('doit retourner 0 avec une réduction de 100%', () => {
    expect(applyDiscount(200, 100)).toBe(0);
  });

  it('doit lever une erreur pour une réduction négative', () => {
    expect(() => applyDiscount(100, -10)).toThrow('Le pourcentage de réduction doit être compris entre 0 et 100');
  });

  it('doit lever une erreur pour une réduction supérieure à 100%', () => {
    expect(() => applyDiscount(100, 150)).toThrow('Le pourcentage de réduction doit être compris entre 0 et 100');
  });
});

Important : Les tests unitaires ne doivent pas accéder aux ressources externes. Utilisez plutôt des mocks pour simuler les dépendances, par exemple avec jest.mock().

Tests d'intégration : Interaction entre les modules

Les tests d'intégration vérifient comment différentes parties du système fonctionnent ensemble. Il peut s'agir de l'interaction entre un service et une base de données, un contrôleur et un repository, ou entre des microservices. Contrairement aux tests unitaires, nous n'isolons pas complètement les composants ici.

Exemple : test d'une API REST

Supposons que nous ayons une application Express avec un endpoint. Pour tester les requêtes HTTP, nous utilisons Supertest.

// userController.ts
import { Router, Request, Response } from 'express';

interface User {
  id: number;
  name: string;
}

const users: User[] = [{ id: 1, name: 'Alice' }];                

Blogs

Book Recommendations