Tests natifs de Node.js : dépannage
Procédure de diagnostic
Section intitulée « Procédure de diagnostic »node --versionnode --test --test-reporter=spec # sortie détailléenode --test src/panier.test.js # un seul fichiernode --test --test-name-pattern="ajoute" # un seul testnode --test --test-concurrency=1 # exécution séquentiellenode --test --test-timeout=10000 # délai globalnode --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.
Tests introuvables ou non lancés
Section intitulée « Tests introuvables ou non lancés »| 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 |
Modules et imports
Section intitulée « Modules et imports »| 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 |
Assertions
Section intitulée « Assertions »| 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 |
Le processus ne se termine pas
Section intitulée « Le processus ne se termine pas »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.afterserveur.close();await base.fermer();clearInterval(minuteur);Pour identifier la cause :
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é |
Asynchrone et sous-tests
Section intitulée « Asynchrone et sous-tests »| 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 |
Concurrence et isolation
Section intitulée « Concurrence et isolation »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.
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.
Différences entre local et CI
Section intitulée « Différences entre local et CI »- Version de Node.js différente : aligner (
.nvmrc,engines, matrice). - Fuseau horaire et langue :
TZ=UTCdanstests/setup.js. - Variables d’environnement absentes en CI.
- Casse des noms de fichiers (Linux sensible).
- Machine plus lente : délais.
TZ=UTC LANG=fr_FR.UTF-8 node --testSortie illisible ou absente
Section intitulée « Sortie illisible ou absente »| 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 |
Quand passer à Vitest
Section intitulée « Quand passer à Vitest »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.
Mettre à jour Node.js
Section intitulée « Mettre à jour Node.js »node --versionnvm install 24 && nvm use 24 # avec nvm (voir la rubrique Node.js)npm cinpm testCertaines 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).