Découvrez la base des tests dans React avec Vitest

Utilisez les tests automatisés dans React

Les tests font partie intégrante du métier de développeur, même en frontend. Ils permettent de s'assurer de la fiabilité de votre code et d'éviter les régressions.

Comprenez l'utilité des tests

Imaginez que vous travaillez sur une application avec plusieurs fonctionnalités. Vous modifiez du code pour ajouter une nouvelle fonctionnalité, et sans vous en rendre compte, vous cassez quelque chose qui fonctionnait parfaitement. C'est ce qu'on appelle une régression.

Les tests automatisés vous alertent immédiatement quand quelque chose ne va plus. Vous gagnez en confiance et en rapidité de développement.

Faites la différence entre les types de tests

Il existe trois types principaux de tests :

  1. Tests unitaires : Testent une petite partie isolée du code (une fonction, par exemple). Rapides à écrire, mais ne garantissent pas que tout fonctionne ensemble.

  2. Tests d'intégration : Testent une fonctionnalité complète en simulant des interactions utilisateur. Bon compromis entre sécurité et temps d'écriture.

  3. Tests end-to-end (E2E) : Testent l'application de bout en bout, comme un véritable utilisateur. Très sécurisants mais longs à écrire et maintenir.

Dans ce cours, nous nous concentrerons sur les tests unitaires et d'intégration avec Vitest et React Testing Library.

Créez votre premier test avec Vitest

Pourquoi Vitest plutôt que Jest d'ailleurs ?

Vitest est l'outil de test recommandé pour les projets Vite. Il est extrêmement rapide, compatible avec l'écosystème Jest, et nécessite très peu de configuration.

Installez Vitest

Dans votre projet React créé avec Vite, installez Vitest :

npm install -D vitest

Puis ajoutez un script de test dans votre package.json :

{
  "scripts": {
    "test": "vitest",
    "test:ui": "vitest --ui",
    "test:coverage": "vitest --coverage"
  }
}

Créez une fonction simple à tester

Créons un fichier src/utils/formatters.js avec une fonction simple :

/**
 * Formate un prix en euros
 * @param {number} price - Le prix à formater
 * @returns {string} Le prix formaté (ex: "19,99 €")
 */
export function formatPrice(price) {
  return `${price.toFixed(2).replace('.', ',')} €`
}

/**
 * Formate une liste d'éléments avec des virgules
 * @param {string} item - L'élément à formater
 * @param {number} index - L'index de l'élément
 * @param {number} totalLength - La longueur totale du tableau
 * @returns {string} L'élément avec ou sans virgule
 */
export function formatListItem(item, index, totalLength) {
  if (index === totalLength - 1) {
    return item
  }
  return `${item},`
}

Créez votre fichier de test

Vitest cherche automatiquement les fichiers qui se terminent par :

  • .test.js

  • .test.jsx

  • .spec.js

  • .spec.jsx

Créez le fichier  src/utils/formatters.test.js  :

import { describe, it, expect } from 'vitest'
import { formatPrice, formatListItem } from './formatters'

describe('formatPrice', () => {
  it('should format a price correctly', () => {
    const result = formatPrice(19.99)
    expect(result).toBe('19,99 €')
  })

  it('should add two decimals if needed', () => {
    const result = formatPrice(20)
    expect(result).toBe('20,00 €')
  })

  it('should handle decimals correctly', () => {
    const result = formatPrice(9.5)
    expect(result).toBe('9,50 €')
  })
})

describe('formatListItem', () => {
  it('should add a comma to an item that is not the last', () => {
    const result = formatListItem('React', 0, 3)
    expect(result).toBe('React,')
  })

  it('should not add a comma to the last item', () => {
    const result = formatListItem('TypeScript', 2, 3)
    expect(result).toBe('TypeScript')
  })
})

Comprenez la structure d'un test

Un test avec Vitest suit cette structure :

  1. describe(): Groupe plusieurs tests liés entre eux

  2. it()outest(): Définit un test individuel (ce sont des alias, vous pouvez utiliser l'un ou l'autre)

  3. expect(): Définit ce qu'on s'attend à obtenir

  4. Matchers :.toBe(),.toEqual(),.toContain(), etc. qui viennent vérifier les valeurs

describe('Nom du groupe de tests', () => {
  it('should do something', () => {
    // 1. Préparer les données (Arrange)
    const input = 'test'
    
    // 2. Exécuter la fonction (Act)
    const result = maFonction(input)
    
    // 3. Vérifier le résultat (Assert)
    expect(result).toBe('expected')
  })
})

Lancez vos tests

npm run test

Vous devriez voir tous vos tests passer en vert ! 

Découvrez les matchers les plus courants

Vitest (comme Jest) offre de nombreux matchers pour vos assertions :

// Égalité stricte
expect(value).toBe(5)
expect(value).not.toBe(10)

// Égalité profonde (pour objets/tableaux)
expect(object).toEqual({ name: 'React' })

// Valeurs truthful/falsy
expect(value).toBeTruthy()
expect(value).toBeFalsy()
expect(value).toBeNull()
expect(value).toBeUndefined()
expect(value).toBeDefined()

// Nombres
expect(value).toBeGreaterThan(10)
expect(value).toBeLessThan(20)
expect(value).toBeCloseTo(0.3) // Pour les décimaux

// Chaînes
expect(string).toMatch(/pattern/)
expect(string).toContain('substring')

// Tableaux
expect(array).toContain('item')
expect(array).toHaveLength(3)

// Fonctions
expect(fn).toThrow()
expect(fn).toThrow('error message')

Assurez-vous d'avoir une bonne couverture de tests

La couverture de tests (code coverage) mesure le pourcentage de votre code qui est exécuté par vos tests.

Installez le plugin de coverage

npm install -D @vitest/coverage-v8

Lancez le coverage

npm run test:coverage

Vous verrez un tableau détaillé dans votre terminal :

% Coverage report from v8
-------------|---------|----------|---------|---------|-------------------
File         | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------|---------|----------|---------|---------|-------------------
All files    |      35 |       60 |      50 |      35 |                   
 src         |       0 |        0 |       0 |       0 |                   
  App.jsx    |       0 |        0 |       0 |       0 | 1-35              
  main.jsx   |       0 |        0 |       0 |       0 | 1-10              
 src/utils   |     100 |      100 |     100 |     100 |                   
  ...ters.js |     100 |      100 |     100 |     100 |                   
-------------|---------|----------|---------|---------|-------------------
 PASS  Waiting for file changes...

Analisons ce que nous trouvons dans ce tableau : 

File : Indique le fichier testé 

% stmts: Indique le pourcentage d'instructions (Statements) qui ont été testées

% branch: Mesure le pourcentage de branches conditionnelle (if/else, switch etc..) qui ont été testé. 

% func: Mesure le pourcentage des fonctions qui ont été appelées au moins une fois dans vos tests

% Lines: Mesure le pourcentage de lignes de code qui ont été exécutées. C'est similaire à statements mais compte les lignes physiques plus que les instructions logiques. 

Uncovered Line #s: Ce sont le numero des lignes qui n'on pas été testés.

Un fichier HTML détaillé est également généré dans  

coverage/index.html  .

À vous de jouer !

Dans la branche P1C2-Begin vous trouverez un fichiersrc/utils/validators.js  avec les fonctions suivantes :

export function isEmailValid(email) {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
}

export function isPasswordStrong(password) {
  // Au moins 8 caractères, une majuscule, une minuscule, un chiffre
  return password.length >= 8 && 
         /[A-Z]/.test(password) && 
         /[a-z]/.test(password) && 
         /[0-9]/.test(password)
}

Créez le fichier  validators.test.js  et écrivez au moins 5 tests :

  • 2 tests pourisEmailValid(un email valide et un invalide)

  • 3 tests pourisPasswordStrong(fort, faible, cas limites)

En résumé

  • Les tests permettent d'éviter les régressions et de gagner en confiance

  • Les tests d'intégration sont un bon compromis entre temps et sécurité

  • Vitest est l'outil moderne pour tester les applications React avec Vite

  • describe()groupe les tests,it()définit un test,expect()vérifie le résultat

  • Le coverage mesure le pourcentage de code testé, mais la qualité prime sur la quantité

Dans le prochain chapitre, nous allons découvrir React Testing Library pour tester nos composants React.

Ever considered an OpenClassrooms diploma?
  • Up to 100% of your training program funded
  • Flexible start date
  • Career-focused projects
  • Individual mentoring
Find the training program and funding option that suits you best