Aller au contenu

Vitest : configuration et intégration continue

vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
include: ['src/**/*.{test,spec}.{ts,tsx}', 'tests/**/*.{test,spec}.ts'],
exclude: ['node_modules', 'dist', 'e2e/**'],
environment: 'node',
setupFiles: ['./tests/setup.ts'],
testTimeout: 10_000,
hookTimeout: 10_000,
allowOnly: !process.env.CI,
clearMocks: true,
restoreMocks: true,
reporters: process.env.CI ? ['default', 'junit'] : ['default'],
outputFile: { junit: './rapport-tests.xml' },
},
});
Option Rôle
include, exclude Fichiers de test
environment node, jsdom, happy-dom
setupFiles Fichiers exécutés avant chaque fichier de test
globalSetup Exécuté une fois avant tous les tests (démarrer une base, un serveur)
testTimeout, hookTimeout Délais maximaux
allowOnly false : refuse it.only laissé dans le code
retry Relance les tests instables (à éviter : corriger la cause)
reporters Format de sortie
alias Chemins d’import (sinon hérités de la configuration Vite)
pool forks (processus, défaut selon la version), threads, vmThreads

Vitest partage la configuration de Vite : pour étendre une configuration existante :

import { defineConfig, mergeConfig } from 'vitest/config';
import viteConfig from './vite.config';
export default mergeConfig(
viteConfig,
defineConfig({
test: { environment: 'jsdom' },
}),
);

Un même dépôt peut mélanger tests Node.js (serveur) et tests DOM (interface) :

export default defineConfig({
test: {
projects: [
{
test: {
name: 'serveur',
include: ['src/server/**/*.test.ts'],
environment: 'node',
},
},
{
test: {
name: 'interface',
include: ['src/ui/**/*.test.tsx'],
environment: 'jsdom',
},
},
],
},
});
Fenêtre de terminal
npx vitest run --project serveur

La propriété s’appelait workspace dans les versions précédentes de Vitest : lire la documentation de la version installée.

import { fileURLToPath } from 'node:url';
export default defineConfig({
resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } },
test: {/* ... */},
});
test: {
env: { NODE_ENV: 'test', API_URL: 'https://api.test' },
},

Ne jamais pointer les tests vers une base de production : utiliser une base dédiée aux tests (SQLite en mémoire ou un conteneur jetable).

tests/global-setup.ts
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
export default function setup() {
const dossier = mkdtempSync(join(tmpdir(), 'tests-'));
process.env.DATA_DIR = dossier;
return () => rmSync(dossier, { recursive: true, force: true }); // nettoyage final
}

globalSetup: ['./tests/global-setup.ts'] ; la fonction renvoyée est le nettoyage exécuté à la fin.

Exemple de workflow Gitea Actions (voir Gitea Actions : écrire un workflow) :

name: Tests
on:
push:
branches: [main]
pull_request:
jobs:
tests:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run lint
- run: npx vitest run --coverage
- uses: actions/upload-artifact@v3
if: always()
with:
name: rapports
path: |
coverage/
rapport-tests.xml

Points d’attention :

  • vitest run (pas le mode watch).
  • npm ci : versions exactes du fichier de verrouillage.
  • upload-artifact@v3 : la version 4 n’est pas prise en charge par Gitea.
  • Variable CI : définie par la plupart des plateformes ; Vitest s’en sert pour désactiver le mode watch.
Levier Effet
vitest related / --changed Teste seulement ce qui est touché par les modifications
--shard=1/3 Répartit les tests sur plusieurs machines
pool: 'threads' Plus rapide pour de nombreux petits fichiers (selon les cas)
isolate: false Évite de recréer l’environnement par fichier (tests indépendants de l’état global uniquement)
environment: 'node' par défaut jsdom seulement où nécessaire
Limiter setupFiles Chaque fichier est exécuté avant chaque fichier de test
Fenêtre de terminal
npx vitest run --changed origin/main # fichiers modifiés par rapport à la branche principale
npx vitest run --shard=1/3

Lancer les tests concernés avant de pousser (voir Husky : installation et Hooks de commit) :

.husky/pre-push
npx vitest run --changed origin/main

Garder le pre-commit rapide (formatage, analyse) : les tests complets appartiennent plutôt au pre-push et à l’intégration continue.

Pour de vrais navigateurs, Vitest propose un mode navigateur (avec Playwright) ; pour des parcours complets de l’application, Playwright Test est l’outil dédié. Les tests unitaires (Vitest) et de bout en bout se complètent : beaucoup de premiers, quelques seconds sur les parcours critiques.

Symptôme Piste
Les tests passent en local, échouent en CI Dépendance de l’ordre, de la date, du fuseau horaire, de variables d’environnement absentes en CI
Error: Failed to load url Alias ou extension non résolus : resolve.alias, même configuration que Vite
Timeouts en CI seulement Machine plus lente : augmenter testTimeout, réduire le parallélisme
ENOSPC: System limit for number of file watchers reached Limite de surveillance de fichiers de Linux : echo fs.inotify.max_user_watches=524288 | sudo tee /etc/sysctl.d/99-inotify.conf && sudo sysctl --system
it.only oublié allowOnly: false en CI
projects ignoré Version plus ancienne : workspace ; lire la documentation de la version installée
Fuite de mémoire entre fichiers isolate désactivé avec des tests qui partagent l’état global

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 à Vitest. Sous Ubuntu, la limite fs.inotify.max_user_watches (voir ci-dessus) peut gêner le mode watch sur de gros projets.