Aller au contenu

Tests natifs de Node.js : dépannage

Fenêtre de terminal
node --version
node --test --test-reporter=spec # sortie détaillée
node --test src/panier.test.js # un seul fichier
node --test --test-name-pattern="ajoute" # un seul test
node --test --test-concurrency=1 # exécution séquentielle
node --test --test-timeout=10000 # délai global
node --inspect-brk --test src/panier.test.js # débogueur (chrome://inspect)

Lire le premier échec : la trace indique le fichier, la ligne et un diff pour deepEqual.

Symptôme Piste
ℹ tests 0 Nom de fichier hors des motifs (*.test.js, dossier test…), mauvais dossier courant
Un fichier précis n’est pas exécuté Motif trop restrictif, fichier dans node_modules ou exclu
Could not find '…' Chemin ou motif invalide : entourer le motif de guillemets
La commande se termine sans rien afficher Rapporteur par défaut selon le terminal : --test-reporter=spec
Ancienne version qui ignore les options node --help | grep -i test, installer une version LTS récente
Message Cause et solution
SyntaxError: Cannot use import statement outside a module "type": "module" dans package.json, ou extension .mjs
ERR_MODULE_NOT_FOUND Extension manquante dans un import relatif (./somme.js), ou casse du nom de fichier (Linux est sensible à la casse)
ReferenceError: require is not defined Code CommonJS dans un module ES : utiliser import
ERR_UNKNOWN_FILE_EXTENSION ".ts" Version de Node.js sans exécution de TypeScript : version plus récente, ou compiler
ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX Syntaxe TypeScript qui génère du code (enum, namespace) : la remplacer
Import d’un paquet ES en require Passer à import
Symptôme Piste
assert.equal accepte des types différents Importer node:assert/strict
deepEqual échoue sur des objets identiques à l’œil Types (1 / '1'), prototypes, propriétés undefined
AssertionError [ERR_ASSERTION] sans détail Ajouter un message en dernier argument, comparer de plus petites valeurs
assert.throws ne détecte rien Appel non enveloppé dans une fonction
assert.rejects ne détecte rien await manquant

node --test attend la fin de tous les travaux. Un serveur, une connexion, un minuteur ou un flux resté ouvert l’empêche de terminer :

// à fermer dans after / t.after
serveur.close();
await base.fermer();
clearInterval(minuteur);

Pour identifier la cause :

Fenêtre de terminal
node --test --test-timeout=15000 # le test fautif échoue avec un message
Cause Solution
Serveur HTTP non fermé t.after(() => serveur.close())
Connexion à une base ouverte await pool.end() dans after
setInterval actif clearInterval, ou .unref()
Promesse jamais résolue Rappel jamais appelé, await oublié
Symptôme Piste
Promise resolution is still pending but the event loop has already resolved Promesse qui ne se résout jamais
test did not finish before its parent and was cancelled Sous-test non attendu : await t.test(…)
Test qui passe alors que l’assertion devrait échouer Promesse non attendue
ERR_TEST_FAILURE: test timed out after … ms Opération trop lente ou bloquée : augmenter timeout, vérifier les minuteurs simulés
EADDRINUSE Port fixe partagé entre fichiers parallèles : port 0

Les fichiers de test s’exécutent en parallèle, chacun dans son processus. Un état commun (port, fichier, base de données, variable d’environnement partagée par un service) provoque des échecs aléatoires.

Fenêtre de terminal
node --test --test-concurrency=1 # diagnostic : si ça passe, il y a un état partagé

Corriger la cause (ressources dédiées par fichier : dossier temporaire, base distincte, port 0) plutôt que de désactiver durablement le parallélisme.

  • Version de Node.js différente : aligner (.nvmrc, engines, matrice).
  • Fuseau horaire et langue : TZ=UTC dans tests/setup.js.
  • Variables d’environnement absentes en CI.
  • Casse des noms de fichiers (Linux sensible).
  • Machine plus lente : délais.
Fenêtre de terminal
TZ=UTC LANG=fr_FR.UTF-8 node --test
Symptôme Piste
Format TAP brut dans le journal Rapporteur par défaut hors terminal : --test-reporter=spec
Pas de rapport JUnit --test-reporter=junit --test-reporter-destination=rapport-tests.xml
Sorties de console.log mélangées Chaque fichier a son flux ; utiliser diagnostics du test (t.diagnostic('…'))
Couleurs absentes en CI Normal (pas de terminal) ; FORCE_COLOR=1 si l’outil de CI les affiche

Passer à Vitest quand le projet a besoin de : TypeScript riche avec alias de Vite, simulation de modules, tests de composants et du DOM, snapshots nombreux, rapport de couverture HTML intégré, ou configuration partagée avec Vite. Le lanceur natif reste le bon choix pour des scripts, des bibliothèques et de petits services.

Fenêtre de terminal
node --version
nvm install 24 && nvm use 24 # avec nvm (voir la rubrique Node.js)
npm ci
npm test

Certaines options du lanceur sont encore expérimentales : lire les notes de version avant une montée de version majeure de Node.js, et relancer toute la suite.

Ubuntu 24.04 et 26.04 : différences à connaître

Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »

Aucune propre à Ubuntu. Le paquet nodejs d’Ubuntu peut être trop ancien pour certaines options (couverture, TypeScript, mock.module) : privilégier NodeSource ou nvm (voir Node.js : installation).