2026年7月3日
2026年7月3日
WordPressテーマのアクセシビリティテストをaxe-coreでCI/CDに組み込む方法(Playwright+GitHub Actions)
WordPressのテーマやプラグインのアクセシビリティを継続的に確認するには、axe-coreをPlaywrightから呼び出すテストを書き、GitHub Actions上でwp-env(Docker製のWordPress開発環境)に対して実行する構成が組みやすい方法です。この記事では、テスト環境の用意、axe-coreを使ったテストの書き方、既存の違反を抱えたまま段階的に導入するコツ、ワークフローの設定、自動テストで見つからない問題の扱いまでを説明します。
axe-coreで分かること・分からないこと
axe-coreは、Deque Systemsが開発しているオープンソースのアクセシビリティ検査エンジンです。ブラウザで表示したページのDOMを調べ、画像の代替テキストの欠落、フォーム部品とラベルの未関連付け、色のコントラスト不足、見出しやランドマークの構造の問題などを、ルールごとに違反として報告します。
ルールにはWCAGの達成基準に対応するタグが付いており、検査対象を絞り込めます。WCAG 2.2は2023年10月にW3C勧告となった現行の版で、axe-coreにもWCAG 2.2向けのタグがありますが、2.2で追加された達成基準のうち自動判定できるものは一部に限られます。
ここで押さえておきたいのは、自動テストで検出できるのはアクセシビリティの問題の一部だけだという点です。キーボードだけで操作できるか、フォーカスの移動順が自然か、代替テキストの内容が画像の意味を正しく伝えているか、といった点は人が確かめる必要があります。CIでのaxe-coreは「明らかな退行を見逃さないための網」と位置づけ、手動の確認と組み合わせて使います。
全体の構成
今回の構成は次のとおりです。
- wp-env:WordPress公式の開発ツール
@wordpress/env。Dockerで検証用のWordPressを立ち上げ、リポジトリのテーマを有効化します - Playwright:ブラウザを自動操作するテストフレームワーク
- @axe-core/playwright:Playwrightのページに対してaxe-coreを実行する公式の連携パッケージ
- GitHub Actions:プルリクエストやpushのたびに上記をまとめて実行します
リポジトリはテーマ(またはプラグイン)のルートに package.json を置く前提で進めます。各ツールのオプションや既定値はバージョンで変わることがあるため、導入時に公式ドキュメントで確認してください(2026年10月現在)。
ローカルで検証環境を用意する
パッケージのインストール
npm install --save-dev @wordpress/env @playwright/test @axe-core/playwright
npx playwright install chromium
wp-envはDockerを使うため、手元のPCにDockerが入っている必要があります。
wp-envの設定
テーマのルートに .wp-env.json を置きます。themes に . を指定すると、このリポジトリがテーマとして読み込まれます。
{
"core": null,
"themes": [ "." ]
}
起動後、テーマの有効化とパーマリンクの設定をWP-CLIで行います。
npx wp-env start
npx wp-env run cli wp theme activate your-theme-slug
npx wp-env run cli wp rewrite structure '/%postname%/'
既定では開発用サイトが http://localhost:8888 で開きます。初期状態のサンプル投稿とサンプル固定ページだけでは検査できる要素が少ないため、見出し・画像・表・フォーム・コメントなどを含むテスト用コンテンツを用意しておくと、テーマの各スタイルを広く検査できます。WordPressのテーマユニットテスト用データを取り込む方法がよく使われます(取り込みにはWordPress Importerプラグインが必要です)。
axe-coreのテストを書く
Playwrightの設定
// playwright.config.js
const { defineConfig } = require('@playwright/test');
module.exports = defineConfig({
testDir: './tests',
use: {
baseURL: 'http://localhost:8888',
},
reporter: [['list'], ['html', { open: 'never' }]],
});
検査するページとテスト本体
テーマの検査では、テンプレートの種類ごとに代表的なページを選びます。トップページ、個別投稿、固定ページ、検索結果、404ページは最低限含めておくと、ヘッダー・フッター・ナビゲーション・本文の主要な部品をひととおり通れます。
// tests/a11y.spec.js
const { test, expect } = require('@playwright/test');
const AxeBuilder = require('@axe-core/playwright').default;
const PAGES = ['/', '/hello-world/', '/sample-page/', '/?s=wordpress', '/no-such-page/'];
const TAGS = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa', 'wcag22aa'];
const BLOCKING = ['critical', 'serious'];
for (const path of PAGES) {
test(`axe: ${path}`, async ({ page }, testInfo) => {
await page.goto(path);
const results = await new AxeBuilder({ page })
.withTags(TAGS)
.exclude('#wpadminbar')
.analyze();
// 違反の詳細をレポートに添付する
await testInfo.attach('axe-violations.json', {
body: JSON.stringify(results.violations, null, 2),
contentType: 'application/json',
});
// まずは重大度の高い違反だけでテストを失敗させる
const blocking = results.violations
.filter((v) => BLOCKING.includes(v.impact))
.map((v) => `${v.id} [${v.impact}] ${v.nodes.length}箇所: ${v.helpUrl}`);
expect(blocking, blocking.join('\n')).toEqual([]);
});
}
コードの意図を補足します。
withTags()でWCAGのA・AA相当のルールに絞っています。axe-coreには、WCAGの基準ではないものの推奨される実装を調べるbest-practiceタグのルールもあり、必要に応じて追加できます- 管理バー(
#wpadminbar)はテーマの責任範囲外なので、exclude()で除外しています。ログインしない状態でテストする場合は表示されませんが、念のため入れています - 失敗時のメッセージにルールIDと影響度、該当箇所の数、解説ページのURLを出すため、ログを見ればどこを直せばよいかの見当がつきます
ローカルで npx playwright test を実行し、結果を確認します。npx playwright show-report でHTMLレポートを開くと、添付したJSONから違反した要素のセレクターやHTMLの断片を確認できます。
既存の違反を抱えたまま段階的に導入する
既存のテーマにいきなり全ルールを適用すると、多数の違反でテストが失敗し続け、CIそのものが無視されるようになりがちです。現実的には次の順で進めます。
- 最初は上のコードのように
criticalとseriousだけで失敗させ、moderate以下はレポートに残すだけにする - すぐに直せないルールがある場合は、
disableRules(['ルールID'])で一時的に外し、その理由と対応予定をコメントやIssueに残す - 重大な違反がなくなったら、
BLOCKINGにmoderateを加えるなど、少しずつ基準を上げる
ルールを外すのは「見なかったことにする」のではなく、「把握したうえで後回しにする」ための手段です。外したルールの一覧が増え続けていないか、定期的に見直してください。
色のコントラストは、ホバーやフォーカス時の色、ダークモード、背景画像の上の文字など、静的なページ表示だけでは検査しきれない状態があります。モバイル幅でメニューが折りたたまれるテーマなら、Playwrightのビューポートを変えたテストを追加し、メニューを開いた状態でも検査すると見落としを減らせます。
GitHub Actionsに組み込む
.github/workflows/a11y.yml に次の内容を置きます。GitHubが提供するUbuntuのランナーにはDockerが入っているため、wp-envをそのまま起動できます。アクションのメジャーバージョンは更新されていくので、各公式リポジトリで最新を確認してください。
name: Accessibility tests
on:
pull_request:
push:
branches: [main]
jobs:
axe:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: lts/*
cache: npm
- run: npm ci
- name: Start WordPress
run: |
npx wp-env start
npx wp-env run cli wp theme activate your-theme-slug
npx wp-env run cli wp rewrite structure '/%postname%/'
- run: npx playwright install --with-deps chromium
- run: npx playwright test
- name: Upload report
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 14
テストが失敗したときもレポートを確認できるよう、アップロードの手順は !cancelled() の条件で実行しています。プルリクエストでテストを必須にしたい場合は、リポジトリのブランチ保護ルールでこのジョブを必須のステータスチェックに指定します。
CIでつまずきやすい点
- wp-envの起動に時間がかかる:初回はDockerイメージやWordPressのダウンロードが入るため、数分かかることがあります。タイムアウトする場合はジョブのタイムアウト設定を見直します
- テーマの有効化に失敗する:
your-theme-slugはテーマのディレクトリ名です。wp-envがマウントしたテーマ名はnpx wp-env run cli wp theme listで確認できます - ローカルでは通るのにCIで失敗する:Webフォントや外部スクリプトの読み込みが遅れ、検査のタイミングによって結果が変わることがあります。
page.goto()の後に特定の要素の表示を待つ処理を入れると安定します - 本番サイトに対して実行したくなる:CIから本番URLを検査することもできますが、テストのたびに本番へアクセスが発生し、ログイン中の状態も再現しにくくなります。テーマの変更を確かめる目的なら、wp-envのような使い捨ての環境で検査するのが安全です
自動テストを通った後に人が確認すること
axe-coreのテストが通っても、それで基準を満たしたとは言えません。リリース前には少なくとも次の点を手で確かめておくと安心です。
- Tabキーだけでメニュー・検索・フォーム・ボタンを操作でき、フォーカスの位置が目で追えるか
- モーダルやドロワーメニューを開いたときにフォーカスが内部へ移り、閉じた後に元の位置へ戻るか
- スクリーンリーダー(NVDAやVoiceOverなど)で読み上げたとき、見出しの順序やリンクの名前が意味の通るものになっているか
- 動きのあるアニメーションが、OSの動きを減らす設定(CSSの
prefers-reduced-motionで検出できるもの)で抑えられるか
これらはチェックリストにしてプルリクエストのテンプレートに入れておくと、自動テストと手動確認の役割分担が明確になります。
まとめ
- axe-coreはアクセシビリティの問題の一部を自動で検出するエンジンで、CIでは退行を防ぐ網として使います
- wp-envで検証用のWordPressを立ち上げ、Playwrightと@axe-core/playwrightで代表的なテンプレートのページを検査します
withTags()でWCAGのレベルを絞り、最初は重大度の高い違反だけで失敗させ、段階的に基準を上げます- GitHub Actionsではレポートを成果物として保存し、失敗時も原因を追えるようにします
- 自動テストの後にキーボード操作やスクリーンリーダーでの確認を行い、WCAG 2.2の基準に照らして判断します