Claude Codeでアクセシビリティテストを自動化する——WCAG準拠をコミット前に検知する

はじめに

「このボタン、スクリーンリーダーで読み上げられない」——E2Eテストでも、パフォーマンステストでもない。そういう問題が、コミット前に自動で検知されてWCAG準拠に修正される仕組みをClaude Codeで作る話だ。

機能開発・パフォーマンス・セキュリティが優先される中、アクセシビリティは「後でやる」扱いになりがちだ。しかし毎年数千件のADA関連訴訟が米国で提起されているという現実(UsablenetやEcomBack等の業界調査)を見ると、「できれば対応」では済まない局面も増えている。さらに欧州でもEAA(European Accessibility Act)が2025年に施行され、グローバル展開するプロダクトにとってWCAG準拠はリーガルリスクの問題でもある。

問題の本質は「後から直す」コストにある。設計段階で検知すれば30分の修正が、リリース後では数日のリファクタリングになる。axe-core・eslint-plugin-jsx-a11y・Playwrightを組み合わせたa11yの自動化により、「後から監査」から「実装と同時に準拠」へのシフトが可能になる。


CLAUDE.mdでa11yポリシーを定義する——「最初から準拠」の設計

アクセシビリティ品質を底上げする最初のステップは、CLAUDE.mdにWCAGルールを定義することだ。Claude Codeがコンポーネントを生成するとき、CLAUDE.mdに書かれたルールが判断基準になる。「alt属性を忘れないでください」と毎回プロンプトに書くのではなく、一度ポリシーを定義すれば以降は自動的に従う。

# CLAUDE.md(アクセシビリティポリシー)
## Accessibility Requirements

### WCAG準拠レベル
- 目標: WCAG 2.1 Level AA準拠
- 全UIコンポーネントに適用
- 新規コンポーネントはリリース前にaxe-coreスキャンを必須とする

### 必須ルール
- 全img要素にalt属性(装飾画像はalt="")
- インタラクティブ要素にaria-labelまたはテキストラベル
- フォームの全入力にラベル関連付け(<label>またはaria-labelledby)
- 見出しは飛び番禁止(h1→h2→h3の順序を守る)
- キーボードフォーカスは全インタラクティブ要素に届くこと
- 色コントラスト比: 通常テキスト4.5:1以上、大テキスト3:1以上

### 禁止パターン
- aria-hidden="true" をフォーカス可能な要素に付与
- tabindexに正の値を使う(tabindex="-1"は可)
- role="button" を<div>に付与(<button>を使うこと)
- カラーのみで状態を表現(色盲ユーザーへの配慮)

CLAUDE.mdにこれを定義しておくと、Claude Codeが新しいフォームコンポーネントを実装するとき、labelの関連付けやaria属性を自動で付与するようになる。「準拠を覚えさせる」ではなく「準拠がデフォルト状態になる」という違いが重要だ。

興味深いのは、axe-core自体がCLAUDE.mdを持っていることだ(dequelabs/axe-core)。accessibility testingの主要OSSライブラリが、Claude Codeでの開発にCLAUDE.mdを活用している。テストパターンやAPIの使い方がCLAUDE.mdに定義されており、「ライブラリ開発者がClaude Codeをどう使うか」の実例として参考になる。


3層のa11y自動化——静的解析・ブラウザテスト・E2E統合

アクセシビリティの自動テストは、速度と検知精度のトレードオフで設計する必要がある。全テストを全PRで実行するとCIが重くなり、何も実行しないと問題が積み重なる。実用的な解は「3層アーキテクチャ」だ。

ツールタイミング速度
**静的解析層**eslint-plugin-jsx-a11yビルド時・エディタ高速(ミリ秒)
**ブラウザ実行層**axe-core(レンダリング済みDOM)ランタイムテスト中速(秒)
**E2E統合層**Playwright + axe-coreCIパイプライン低速(分)

静的解析層では、eslint-plugin-jsx-a11yがJSXコードを構文解析してa11y違反を検知する。エディタ上でリアルタイムに赤線が引かれるため、書いた瞬間に問題がわかる。とタイプした直後に「alt属性がない」と警告が出る体験は、レビューサイクルを待つことなく問題を解消できる。

ブラウザ実行層では、axe-coreが実際にレンダリングされたDOMを解析する。静的解析では検知できない問題——コントラスト比の実際値・動的に追加されるARIAラベルの正確さ・フォーカス順序——がここで明らかになる。

E2E統合層では、PlaywrightとaxeをCIで組み合わせる。

// playwright.config.ts でのaxe統合
import { checkA11y } from 'axe-playwright';

test('チェックアウトページのアクセシビリティ', async ({ page }) => {
  await page.goto('/checkout');
  await checkA11y(page, null, {
    axeOptions: {
      runOnly: {
        type: 'tag',
        values: ['wcag2a', 'wcag2aa', 'wcag21aa'],
      },
    },
  });
});

Playwright MCPのa11yツリー活用はさらに踏み込んだアプローチだ。Playwright MCPは通常のDOMではなく、アクセシビリティツリーをベースにUIと対話する(builder.io)。これはスクリーンリーダーが実際に読み取るツリーと同じ構造であり、Claude Codeがスクリーンリーダーの視点でUIを評価できることを意味する。

通常のテスト: DOM要素 → CSSセレクタ → クリック
Playwright MCP: a11y tree → role/name → インタラクション

「button[data-cy='submit']をクリック」ではなく「role=button name='注文を確定する'をクリック」という操作になる。テストコードが視覚的な実装ではなく意味的な構造に依存するため、コンポーネントのCSSクラスやHTMLの構造が変わってもテストが壊れにくい。

ARIAラベルの自動生成はClaude Codeが得意とする領域だ。コンポーネントの用途からaria-labelの内容を推測し、デザインシステム全体に一貫したARIA命名を適用できる。

コメント

タイトルとURLをコピーしました