Skip to Content
AccessibilitéPartie 14 — Tester l'accessibilité14.5 — Tests en CI & anti-régression

Chapitre 14.5 — Tests en CI & anti-régression

⏱️ TL;DR — Ce qui n’est pas automatisé finit par régresser. On ne peut pas automatiser toute l’accessibilité (rappel : ~30-40 %), mais on peut mettre un filet : eslint-plugin-jsx-a11y pour le statique, jest-axe/vitest-axe pour les composants, @axe-core/playwright ou cypress-axe pour l’E2E, l’addon a11y de Storybook pour le catalogue. En CI, ces contrôles bloquent les régressions détectables automatiquement — laissant tes tests manuels se concentrer sur le reste.

🎯 Objectifs

  • Mettre en place un linting a11y statique.
  • Écrire des tests axe unitaires et E2E.
  • Intégrer ces contrôles en CI comme garde-fou.
  • Comprendre la frontière entre ce qui s’automatise et ce qui reste manuel.

Pourquoi automatiser (et jusqu’où)

Une page peut être rendue accessible aujourd’hui puis régresser demain : un dev remplace un <button> par une <div>, retire un alt, casse un contraste. Sans filet automatique, personne ne le voit avant l’audit suivant. L’automatisation en CI attrape immédiatement les régressions détectables — c’est son rôle : pas remplacer les tests manuels (14.3, 14.4), mais empêcher de reculer sur ce qui était acquis.

Garde en tête le plafond : l’automatique ne juge ni la pertinence d’un alt, ni l’ordre logique, ni l’utilisabilité réelle. Il complète, il ne certifie pas.

Couche 1 — Le linting statique

eslint-plugin-jsx-a11y analyse ton JSX sans exécuter le code et signale les erreurs courantes : alt manquant, <div onClick> sans rôle/clavier, mauvais usage de aria-*, label non associé. C’est le filet le moins cher et le plus précoce (dans l’éditeur et en CI).

npm i -D eslint-plugin-jsx-a11y
// eslint.config.js (extrait) import jsxA11y from 'eslint-plugin-jsx-a11y' export default [ jsxA11y.flatConfigs.recommended, // ... ta config ]

Couche 2 — Les tests de composants avec axe

jest-axe (ou vitest-axe) fait tourner le moteur axe-core sur le rendu d’un composant et échoue s’il détecte des violations :

import { render } from '@testing-library/react' import { axe } from 'jest-axe' import { Inscription } from './Inscription' test("le formulaire d'inscription n'a pas de violation a11y détectable", async () => { const { container } = render(<Inscription />) const results = await axe(container) expect(results).toHaveNoViolations() })

Couche 3 — Les tests E2E avec axe

Pour vérifier des pages entières dans un vrai navigateur, on lance axe via Playwright ou Cypress :

// Playwright + @axe-core/playwright import { test, expect } from '@playwright/test' import AxeBuilder from '@axe-core/playwright' test('la page cours est sans violation détectable', async ({ page }) => { await page.goto('/cours/react') const results = await new AxeBuilder({ page }).analyze() expect(results.violations).toEqual([]) })

Avec Cypress, cypress-axe offre cy.injectAxe() puis cy.checkA11y().

Couche 4 — Storybook

Si tu as un catalogue de composants, l’addon a11y de Storybook fait tourner axe sur chaque story et affiche les violations directement dans l’UI — un excellent endroit pour attraper les problèmes au niveau du design system (15.2).

Assembler le pipeline

⚠️ Piège — Croire que « la CI est verte donc c’est accessible ». Ce filet attrape uniquement le détectable automatiquement. Un formulaire peut passer axe et rester inutilisable au clavier ou incompréhensible au lecteur d’écran. La CI empêche de régresser ; elle ne certifie pas la conformité. Les tests manuels restent indispensables.

💡 Réflexe — Ajoute le filet a11y le plus tôt possible dans un projet, même minimal (jsx-a11y + un jest-axe sur les composants clés). Plus tu l’installes tard, plus tu accumules de dette à rattraper. Et branche-le en gate de CI : un contrôle qui n’échoue jamais la build est un contrôle qu’on finit par ignorer.

🧭 Sur A11yLearn — La CI d’A11yLearn fait tourner eslint-plugin-jsx-a11y, un jest-axe sur les composants du design system, et un test Playwright + axe sur trois parcours (accueil, inscription, page cours). Toute PR qui introduit une <div onClick> ou retire un alt est bloquée. Les revues clavier et lecteur d’écran, elles, restent dans la définition de « fini » — le filet ne les remplace pas.

✏️ Exercices

Exercice 1 — Choisis l’outil. Pour chaque besoin, dis quel outil tu emploierais : (a) empêcher un <div onClick> d’être mergé, (b) vérifier qu’un composant <Modal> n’a pas de violation axe, (c) auditer une page entière en navigateur en CI.

✅ Solution

(a) eslint-plugin-jsx-a11y (statique, dès l’éditeur et en CI). (b) jest-axe/vitest-axe sur le rendu du composant. (c) @axe-core/playwright (ou cypress-axe) sur la page réelle. Les trois couches se complètent : lint → composant → page.

Exercice 2 — La limite du vert. Ta CI a11y est verte à 100 %, mais un utilisateur signale que le formulaire est inutilisable au clavier. Comment est-ce possible ?

✅ Solution

Parce que les tests automatiques (axe, lint) ne couvrent que le détectable automatiquement (~30-40 %) : ils ne vérifient pas l’ordre de focus réel, les pièges clavier, ou l’utilisabilité au lecteur d’écran. Un formulaire peut passer axe et rester inaccessible au clavier. La CI empêche les régressions détectables ; elle ne remplace pas les tests manuels clavier et lecteur d’écran.

🧠 Quiz de révision

1. Quel est le rôle des tests a11y automatisés en CI ?

Empêcher les régressions détectables automatiquement (alt retiré, faux bouton, contraste cassé) d’être fusionnées. C’est un filet de sécurité, pas une certification de conformité.

2. Quel outil pour le linting statique du JSX ?

eslint-plugin-jsx-a11y : il signale, sans exécuter le code, les erreurs courantes (alt manquant, <div onClick> sans rôle/clavier, aria mal utilisé). C’est le filet le plus précoce.

3. Quelle est la différence entre jest-axe et axe + Playwright ?

jest-axe/vitest-axe teste le rendu d’un composant isolé ; @axe-core/playwright (ou cypress-axe) teste une page entière dans un vrai navigateur. Les deux utilisent le moteur axe-core, à des échelles différentes.

4. Une CI a11y verte prouve-t-elle la conformité ?

Non. Elle ne couvre que ~30-40 % des critères (le détectable automatiquement). Une page peut être verte et inutilisable au clavier ou au lecteur d’écran. Les tests manuels restent indispensables.

5. Quand mettre en place le filet automatique ?

Le plus tôt possible, même minimal (jsx-a11y + jest-axe sur les composants clés), et branché en gate de CI qui bloque réellement. Installé tard, il laisse s’accumuler une dette d’accessibilité à rattraper.


Partie suivante : Design accessible & industrialiser — concevoir en amont, porter l’a11y par le design system, et l’ancrer dans l’organisation.

Last updated on