Accueil / Articles / Notes pratiques : le générateur de tests natif de Node contre Jest et Vitest : une suite, trois solutions

Notes pratiques : le générateur de tests natif de Node contre Jest et Vitest : une suite, trois solutions

Guide pratique détaillé : l’exécuteur de tests natif de Node contre Jest et Vitest – une seule suite, trois outils : contrats, vérifications et emplacements de code intégrables pour les équipes utilisant ce modèle.

2126 mots

Utilisez ceci comme une version révisée destinée aux opérateurs des idées présentées dans « Node’s Native Test Runner vs Jest vs Vitest: One Suite, Three Runners, Real Timings » : étapes claires, emplacements de code ordonnés et notes de récupération qui survivent au transfert de responsabilités. L’étape « Aperçu » fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définez des vérifications de succès et refusez toute complétion partielle silencieuse.

Les trois exécuteurs, honnêtement

Pour les trois étapes de l’exécution, il convient d’identifier clairement les entrées, le responsable de chaque étape ainsi que les critères d’arrêt avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu, sans avoir à deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts permet d’éviter des factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés. Placez toujours l’état en même temps que le composant responsable des modifications ; placer tout dans un stockage global rend plus difficile la détection des erreurs liées aux temps d’exécution.

1. node:test, le choix peu attrayant mais efficace

Pour le test à 1 nœud, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Placez l’état avec le composant qui gère la mutation. Mettre tout dans un stockage global rend les erreurs de synchronisation plus difficiles à détecter.

// node-test/test/string-utils.test.js
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { slugify } from '../../src/string-utils.js';

describe('slugify', () => {
  it('converts a basic sentence', () => {
    assert.equal(slugify('Hello World'), 'hello-world');
  });

  it('strips diacritics', () => {
    assert.equal(slugify('Café résumé'), 'cafe-resume');
  });

  it('throws TypeError on non-string input', () => {
    assert.throws(() => slugify(123), TypeError);
  });
});
# Run it, no install step
node --test node-test/test/*.test.js

# Watch mode
node --test --watch node-test/test/*.test.js
# Coverage (still experimental, but the numbers are real V8 counts)
node --test --experimental-test-coverage \
  --test-coverage-include='src/**/*.js' \
  node-test/test/*.test.js

2. Jest, le choix par défaut que vous utilisez déjà

Pour la phase par défaut de 2 Jest, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez ensemble le parcours normal et les scénarios de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations ultérieures. Placez l’état au même endroit que le composant responsable de la mutation. Mettre tout dans un stockage global rend les erreurs liées aux délais plus difficiles à détecter. Pour la phase par défaut de 2 Jest, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier du code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette phase comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définites des vérifications de succès et refusez les terminations partielles silencieuses.

// jest/test/string-utils.test.js
import { slugify } from '../../src/string-utils.js';

describe('slugify', () => {
  it('converts a basic sentence', () => {
    expect(slugify('Hello World')).toBe('hello-world');
  });

  it('strips diacritics', () => {
    expect(slugify('Café résumé')).toBe('cafe-resume');
  });

  it('throws TypeError on non-string input', () => {
    expect(() => slugify(123)).toThrow(TypeError);
  });
});
// jest/jest.config.js, minimal. Run it with NODE_OPTIONS=--experimental-vm-modules
export default {
  rootDir: '.',
  testMatch: ['<rootDir>/test/**/*.test.js'],
  testEnvironment: 'node',
  verbose: true,
};
# Run (the flag is required for native ESM)
NODE_OPTIONS=--experimental-vm-modules npx jest --config jest/jest.config.js
# Watch
NODE_OPTIONS=--experimental-vm-modules npx jest --config jest/jest.config.js --watch

3. Vitest, le nouveau paramètre par défaut, avec un compromis

Lorsque vous travaillez avec la nouvelle étape 3 Vitest, notez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de l’environnement de démonstration à des environnements partagés. Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.

// vitest/test/string-utils.test.js
import { describe, it, expect } from 'vitest';
import { slugify } from '../../src/string-utils.js';

describe('slugify', () => {
  it('converts a basic sentence', () => {
    expect(slugify('Hello World')).toBe('hello-world');
  });

  it('strips diacritics', () => {
    expect(slugify('Café résumé')).toBe('cafe-resume');
  });

  it('throws TypeError on non-string input', () => {
    expect(() => slugify(123)).toThrow(TypeError);
  });
});
// vitest/vitest.config.mjs
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    include: ['test/**/*.test.js'],
    environment: 'node',
    coverage: { provider: 'v8', include: ['../src/**/*.js'] },
  },
});
# Run
cd vitest && npx vitest run
# Watch (this is the killer feature)
cd vitest && npx vitest
# Coverage
cd vitest && npx vitest run --coverage

La méthodologie, pour que vous puissiez la critiquer

Lorsque vous travaillez selon cette méthodologie, écrivez d’abord le contrat : les entrées requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de rester honnête lors des modifications ultérieures du code. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les administrateurs peuvent auditer sans devoir lire l’ensemble du système. Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.

# Reproduce on your own machine
git clone https://github.com/manisuec/techinsights-tutorials
cd techinsights-tutorials/nodejs-test-runner
npm install
bash shared/bench.sh 5      # cold runs
WARM=1 bash shared/bench.sh 5   # warm runs

Les chiffres réels

Lors du travail sur l’étape des nombres réels, écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications ultérieures du code. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’améliorations apportées ultérieurement. Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu. Lors du travail sur l’étape des nombres réels, écrivez d’abord le contrat : les entrées requises, le signal de succès et ce qui se passe en cas d’échec partiel. Cette liste de contrôle permet de garantir l’honnêteté des modifications ultérieures du code. Traitez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des contrôles de succès et refusez les terminations partielles silencieuses.

=== node:test  (Node v24.14.0) [cold] ===
  run 1: 91 ms
  run 2: 93 ms
  run 3: 89 ms
  run 4: 90 ms
  run 5: 90 ms
  median: 90 ms

=== Jest  (30.4.1) [cold] ===
  run 1: 817 ms
  run 2: 689 ms
  run 3: 718 ms
  run 4: 711 ms
  run 5: 685 ms
  median: 711 ms

=== Vitest  (4.1.11) [cold] ===
  run 1: 548 ms
  run 2: 648 ms
  run 3: 534 ms
  run 4: 531 ms
  run 5: 535 ms
  median: 535 ms

Matrice des fonctionnalités, 2026, dernière vérification

La matrice de fonctionnalités 2026, en dernière étape, fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un transcript idéal, un cas d’échec et la note de réversion avant d’élargir le périmètre. Enregistrez les temps d’exécution ainsi que le coût des tokens ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le processus passe de la démonstration aux environnements partagés. Gardez les tâches de rendu peu coûteuses et reportez les calculs onéreux à l’après-mémorisation, uniquement après avoir effectué des mesures. Une mémorisation prématurée peut cacher des bugs liés à des données obsolètes.

Quand choisir l’un ou l’autre

Déterminer quel stade choisir est plus simple si l’on le considère comme une surface mesurable. Capturez un transcript parfait, un cas d’échec et la note de réversion avant d’élargir le périmètre. Gardez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les indicateurs fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans devoir lire l’ensemble du système. Maintenez le processus de rendu peu coûteux et reportez les calculs coûteux à la mise en mémoire uniquement après avoir effectué des mesures. Une mise en mémoire prématurée peut cacher des erreurs liées à des données obsolètes.

Migrer de Jest à Vitest en 30 minutes

La migration de Jest vers le stage fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Documentez ensemble le parcours réussi et celui de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie intégrante du produit, et non d’une mise en forme ultérieure. Maintenez les opérations de rendu peu coûteuses et reportez les calculs onéreux à l’après-mémorisation, uniquement après avoir effectué des mesures. Une mémorisation prématurée peut cacher des bugs liés à des propriétés obsolètes. La migration de Jest vers le stage fonctionne le mieux lorsqu’elle est considérée comme une surface mesurable. Capturez un enregistrement idéal, un cas d’échec et une note de réversion avant d’élargir le périmètre. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définites des vérifications de succès et refusez toute complétion partielle silencieuse.

# 1. Install
npm install -D vitest

# 2. Add a config (or piggyback on vite.config.ts if you have one)
# vitest.config.ts

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,                 // makes describe/it/expect global
    environment: 'jsdom',          // or 'node' for backend
    setupFiles: ['./tests/setup.ts'],
  },
});

# 3. Swap imports, find/replace in your editor
#    jest.mock  → vi.mock
#    jest.fn    → vi.fn
#    jest.spyOn → vi.spyOn
#    require('@jest/globals') → require('vitest')
#    jest.useFakeTimers()      → vi.useFakeTimers()

# 4. Swap npm scripts
#    "test": "jest"  →  "test": "vitest run"
#    "test:watch": "jest --watch"  →  "test:watch": "vitest"

# 5. If you used babel-jest, delete it and babel.config.js

# 6. Run. Fix the 3-5 things that fail. Drink coffee.

Ce que vous ne feriez pas

Pour ce qui ne doit pas être exécuté en direct, définissez les entrées, le responsable de l’étape et les critères de fin avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Enregistrez les temps d’exécution ainsi que le coût des jetons ou des requêtes à côté des résultats fonctionnels. Une visibilité précoce des coûts évite les factures inattendues lorsque le parcours passe d’un environnement de démonstration à des environnements partagés. Placez l’état au même endroit que le composant responsable de la mutation. Mettre tout dans un stockage global rend les erreurs liées aux temps d’exécution plus difficiles à détecter.

Le verdict

Pour l’étape du verdict, définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Conservez la configuration en dehors du code de l’application. Les fichiers d’environnement, les bases de données secrètes et les flags fonctionnels doivent être regroupés en un seul endroit que les opérateurs peuvent auditer sans avoir à lire l’ensemble du système. Placez l’état au même endroit que le composant responsable de la mutation. Mettre tout dans un stockage global rend les erreurs liées aux délais plus difficiles à détecter.

Appendice : comment interpréter les chiffres dans cet article

Pour l’Appendice « Comment lire l’étape », définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Documentez ensemble le parcours normal et le parcours de récupération. Les tentatives répétées, les contrôles humains et la gestion des messages non livrés font partie du produit, et non d’une mise en forme ultérieure. Colocalisez l’état avec le composant qui gère la mutation. Mettre tout en un stockage global rend les erreurs de synchronisation plus difficiles à détecter. Pour l’Appendice « Comment lire l’étape », définissez les entrées, le responsable de l’étape et les critères de sortie avant de modifier le code. Les opérateurs doivent pouvoir relancer l’étape à partir d’un point de contrôle connu sans deviner l’état caché. Considérez cette étape comme un contrat entre les entrées et les sorties validées. Nommez les artefacts, définissez des vérifications de succès et refusez toute complétion partielle silencieuse.

Liste de contrôle opérationnelle

Lors de l’étape de la liste de contrôle opérationnelle, notez d’abord les exigences du contrat : les données requises, le signal de succès, ainsi que ce qui se passe en cas d’échec partiel. Cette liste garantit l’honnêteté des modifications ultérieures du code.

Préférez des unités petites et testables aux scripts complexes. Lorsqu’une étape échoue, l’échec doit indiquer une seule responsabilité et non un processus embrouillé.

Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.

Fixez les versions des dépendances et enregistrez le digest de l’image utilisée pour la démonstration. La reproductibilité vaut mieux que les connaissances internes au groupe.

Considérez cette étape comme un contrat entre les entrées et les sorties validées. Donnez des noms aux artefacts, définez des vérifications de succès, et refusez les terminations partielles silencieuses.

Considérez les effets comme une synchronisation avec le monde extérieur, et non comme un substitut aux valeurs dérivées lors du rendu.

Au préalable de promouvoir la pile, figez les versions, capturez une transcription d’ référence pour le chemin critique, et confirmez les étapes de rollback. Les environnements partagés nécessitent des limites de débit, des vérifications de location, ainsi qu’un responsable clair pour la rotation des secrets. Préférez une fiabilité banale à des démonstrations ingénieuses ponctuelles.

Note de lot pour b78b143fb7a9 : gardez les clés du fournisseur hors du dépôt, fixez un plafond pour les tokens par session, et stockez les transcriptions à côté des fichiers d’évaluation afin que les remplacements ultérieurs de modèles restent comparables.