Les tests sont essentiels pour garantir la qualité et la fiabilité du code. Ils permettent de détecter les régressions, de vérifier le comportement attendu et d'assurer une meilleure maintenabilité du projet. Dans cette séance, nous allons explorer les différents types de tests et les outils associés.
Les tests viennent s'intégrer dans le cycle de développement, souvent via l'intégration continue (CI), pour automatiser la vérification du code à chaque modification et avant chaque déploiement.
Il existe plusieurs types de tests :
Tests unitaires (Unit tests)
Tests d’intégration (Integration tests)
Tests de bout en bout (E2E - End to End)
Tests unitaires (Unit tests) avec Vitest
Qu'est-ce que Vitest ?
Vitest est un framework de test unitaire ultra-rapide conçu spécifiquement pour les projets Vite. Il est compatible avec l'API de Jest, mais offre des performances bien supérieures grâce à son intégration native avec Vite et son utilisation des ESM (ECMAScript Modules).
Avantages de Vitest :
Exécution ultra-rapide grâce à Vite
API compatible avec Jest (migration facile)
Support natif de TypeScript et JSX
Watch mode intelligent (re-test uniquement ce qui a changé)
Interface UI pour visualiser les tests
Support du parallélisme et de l'isolation des tests
Intégration native avec Vue Test Utils
Cas d'usage typiques :
Tests de composants Vue (rendu, props, events)
Tests de composables et hooks réutilisables
Tests de fonctions utilitaires et helpers
Tests de stores Pinia
Validation de la logique métier
Installation de Vitest
Configuration de base (vitest.config.js) :
Ajout de scripts dans package.json :
Exemple 1 : Test d'un composant simple
Exemple 2 : Test d'un composant avec props et slots
Exemple 3 : Test d'un composable
Exemple 4 : Test de fonctions utilitaires
Exemple 5 : Test d'un store Pinia
Mocking et Spy avec Vitest
Bonnes pratiques Vitest
Organiser les tests par fonctionnalité (un fichier de test par composant/fonction)
Utiliser describe pour grouper les tests liés
Nommer les tests de manière descriptive (it('should do something'))
Tester un comportement à la fois par test
Utiliser beforeEach / afterEach pour setup/cleanup
Préférer les sélecteurs par data-testid pour les composants
Tester les cas limites et les erreurs
Viser une couverture de code > 80% sur la logique critique
Tests d’intégration (Integration tests) avec Vitest
Tests des interactions entre plusieurs composants.
Vérification du comportement global d’une fonctionnalité.
E2E avec Cypress
Qu'est-ce que Cypress ?
Cypress est un framework moderne de tests end-to-end (E2E) pour applications web. Contrairement aux outils traditionnels comme Selenium, Cypress s'exécute dans le même contexte que l'application testée, ce qui le rend plus rapide, plus fiable et plus facile à déboguer.
Avantages de Cypress :
Syntaxe simple et lisible
Feedback visuel en temps réel avec l'interface graphique
Automatisation des attentes et des retry automatiques
# Installation de Vitest et des utilitaires pour Vue
npm install -D vitest @vue/test-utils jsdom
# Ou avec pnpm
pnpm add -D vitest @vue/test-utils jsdom
# Pour le coverage (optionnel)
npm install -D @vitest/coverage-v8
// Exemple de mock d'une fonction
import { describe, it, expect, vi } from 'vitest'
describe('Mocking', () => {
it('mock une fonction de callback', () => {
const callback = vi.fn()
callback('test')
callback('test2')
expect(callback).toHaveBeenCalledTimes(2)
expect(callback).toHaveBeenCalledWith('test')
expect(callback).toHaveBeenLastCalledWith('test2')
})
it('mock une API externe', async () => {
// Mock de fetch
global.fetch = vi.fn(() =>
Promise.resolve({
ok: true,
json: () => Promise.resolve({ data: 'mock data' })
})
)
const response = await fetch('/api/data')
const data = await response.json()
expect(data).toEqual({ data: 'mock data' })
expect(fetch).toHaveBeenCalledWith('/api/data')
})
})
# Installation en dev dependency
npm install -D cypress
# Ou avec pnpm
pnpm add -D cypress
# Initialiser Cypress (crée la structure de dossiers)
npx cypress open
import { defineConfig } from 'cypress'
export default defineConfig({
e2e: {
baseUrl: 'http://localhost:5173', // URL de votre app en dev
viewportWidth: 1280,
viewportHeight: 720,
video: true, // Enregistrer vidéos des tests
screenshotOnRunFailure: true
}
})