screen-reader-testing について
スクリーンリーダーを使って Web のアクセシビリティを検証する実践的なスキルです。開発者やテスター向けに、対象環境や操作モード、ダイアログや動的な通知などのテスト方法を案内します。
主な機能
- 01主要なスクリーンリーダーの対象範囲
- 02ブラウズ・フォーカス・アプリケーションモード
- 03モーダル、ライブリージョン、タブのテスト例
- 04アクセシブルネームのデバッグ方法
- 05キーボードとフォーカスのテスト手法
活用シーン
- 01スクリーンリーダーごとの ARIA 動作確認
- 02支援技術を使ったフォームとナビゲーションのテスト
- 03動的コンテンツの通知問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ wshobson/ agents --skill screen-reader-testingインストール後、Claude Code で/screen-reader-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/jaws-talkback.mdnvda.mdvoiceover-ios.mdvoiceover.md詳細
スクリーンリーダーのテスト
包括的なアクセシビリティ検証のために、スクリーンリーダーを使ってウェブアプリケーションをテストする実践ガイドです。
このスキルを使用する場面
- スクリーンリーダーとの互換性を検証する
- ARIA の実装をテストする
- 支援技術に関する問題をデバッグする
- フォームのアクセシビリティを検証する
- 動的コンテンツの読み上げをテストする
- ナビゲーションのアクセシビリティを確保する
基本概念
1. 主なスクリーンリーダー
| スクリーンリーダー | プラットフォーム | ブラウザー | 利用率 |
|---|---|---|---|
| VoiceOver | macOS/iOS | Safari | ~15% |
| NVDA | Windows | Firefox/Chrome | ~31% |
| JAWS | Windows | Chrome/IE | ~40% |
| TalkBack | Android | Chrome | ~10% |
| Narrator | Windows | Edge | ~4% |
2. テストの優先順位
Minimum Coverage:
1. NVDA + Firefox (Windows)
2. VoiceOver + Safari (macOS)
3. VoiceOver + Safari (iOS)
Comprehensive Coverage:
+ JAWS + Chrome (Windows)
+ TalkBack + Chrome (Android)
+ Narrator + Edge (Windows)
3. スクリーンリーダーのモード
| モード | 目的 | 使用場面 |
|---|---|---|
| ブラウズ/仮想 | コンテンツを読む | 通常の読み上げ |
| フォーカス/フォーム | コントロールを操作する | フォームへの入力 |
| アプリケーション | カスタムウィジェットを操作する | ARIA アプリケーション |
macOS でテストする前に、VoiceOver のセットアップ、コマンド、チェックリストをお読みください。
必須の iOS Safari のカバレッジについては、VoiceOver のタッチ操作のセットアップとジェスチャーをお読みください。
NVDA でテストする前に、NVDA のセットアップ、モード、コマンド、テストスクリプトをお読みください。
JAWS または TalkBack でテストする前に、プラットフォームのセットアップとコマンドをお読みください。
一般的なテストシナリオ
1. モーダルダイアログ
<div
role="dialog"
aria-modal="true"
aria-labelledby="dialog-title"
aria-describedby="dialog-desc"
>
<h2 id="dialog-title">Confirm Delete</h2>
<p id="dialog-desc">This action cannot be undone.</p>
<button>Cancel</button>
<button>Delete</button>
</div>
// Focus management
function openModal(modal) {
// Store last focused element
lastFocus = document.activeElement;
// Move focus to modal
modal.querySelector("h2").focus();
// Trap focus
modal.addEventListener("keydown", trapFocus);
}
function closeModal(modal) {
// Return focus
lastFocus.focus();
}
function trapFocus(e) {
if (e.key === "Tab") {
const focusable = modal.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
);
const first = focusable[0];
const last = focusable[focusable.length - 1];
if (e.shiftKey && document.activeElement === first) {
last.focus();
e.preventDefault();
} else if (!e.shiftKey && document.activeElement === last) {
first.focus();
e.preventDefault();
}
}
if (e.key === "Escape") {
closeModal(modal);
}
}
2. ライブリージョン
<div role="status" aria-live="polite" aria-atomic="true">
</div>
<div role="alert" aria-live="assertive">
</div>
<div
role="progressbar"
aria-valuenow="75"
aria-valuemin="0"
aria-valuemax="100"
aria-label="Upload progress"
></div>
<div role="log" aria-live="polite" aria-relevant="additions">
</div>
3. タブインターフェース
<div role="tablist" aria-label="Product information">
<button role="tab" id="tab-1" aria-selected="true" aria-controls="panel-1">
Description
</button>
<button
role="tab"
id="tab-2"
aria-selected="false"
aria-controls="panel-2"
tabindex="-1"
>
Reviews
</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
Product description content...
</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
Reviews content...
</div>
// Tab keyboard navigation
tablist.addEventListener("keydown", (e) => {
const tabs = [...tablist.querySelectorAll('[role="tab"]')];
const index = tabs.indexOf(document.activeElement);
let newIndex;
switch (e.key) {
case "ArrowRight":
newIndex = (index + 1) % tabs.length;
break;
case "ArrowLeft":
newIndex = (index - 1 + tabs.length) % tabs.length;
break;
case "Home":
newIndex = 0;
break;
case "End":
newIndex = tabs.length - 1;
break;
default:
return;
}
tabs[newIndex].focus();
activateTab(tabs[newIndex]);
e.preventDefault();
});
デバッグのヒント
// Log what screen reader sees
function logAccessibleName(element) {
const computed = window.getComputedStyle(element);
console.log({
role: element.getAttribute("role") || element.tagName,
name:
element.getAttribute("aria-label") ||
element.getAttribute("aria-labelledby") ||
element.textContent,
state: {
expanded: element.getAttribute("aria-expanded"),
selected: element.getAttribute("aria-selected"),
checked: element.getAttribute("aria-checked"),
disabled: element.disabled,
},
visible: computed.display !== "none" && computed.visibility !== "hidden",
});
}
ベストプラクティス
するべきこと
- 実際のスクリーンリーダーでテストする - シミュレーターだけで済ませない
- まずセマンティック HTML を使う - ARIA は補助的なものです
- ブラウズモードとフォーカスモードでテストする - それぞれ体験が異なります
- フォーカス管理を確認する - 特に SPA では重要です
- まずキーボードのみでテストする - SR テストの基礎となります
してはいけないこと
- 1つの SR だけで十分だと思い込まない - 複数をテストする
- モバイルを無視しない - 利用者が増えています
- 正常系だけをテストしない - エラー状態もテストする
- 動的コンテンツを省略しない - 最もよくある問題です
- 視覚的なテストに頼らない - 体験が異なります
コメント
Markdown 対応