writing-webdriverio-code について
Writing WebdriverIO Codeは、テストのひな型を実装済みのWebdriverIOテストにし、既存のspecを拡張・修正するスキルです。プロジェクトの規約に従い、決定性のあるセットアップ、堅牢なセレクター、明確なアサーションを重視します。
主な機能
- 01ひな型のテストシナリオを実装
- 02既存specの拡張や修正
- 03プロジェクト規約とコンテキストの適用
- 04堅牢なセレクターと明示的な待機
- 05分離された決定性のあるテストデータ設定
- 06不安定なテストの根本原因を調査
活用シーン
- 01擬似コードのコメントを実行可能なテストに変換
- 02既存のWebdriverIO specにシナリオを追加
- 03不安定なブラウザテストの診断と安定化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ klamping/ webdriverio-skills --skill writing-webdriverio-codeインストール後、Claude Code で/writing-webdriverio-codeを入力して読み込まれたか確認します。
詳細
WebdriverIO コードの記述
スキャフォールドのコメントを、本番環境で使用できるテストコードに変換します。
このスキルでは、次のいずれかを使用できます。
creating-test-structureで作成したスキャフォールド- 新しいテスト、リファクタリング、またはバグ修正が必要な既存の WebdriverIO スペック
どちらの場合も、安定していて、読みやすく、デバッグしやすい具体的な WebdriverIO の実装を作成します。
使用するタイミング
- スキャフォールドがあり、疑似コードから WDIO コマンドやアサーションへの変換が必要な場合。
- 既存のテストファイルにシナリオを追加する場合。
- 既存のテストが不安定、脆弱、または不正確で、修正が必要な場合。
使用しないタイミング
- Markdown のテスト計画からスイート全体のスキャフォールドを作成する必要がある場合(
creating-test-structureを使用してください)。 - コードを実装せず、describe/it の階層だけを整理する場合。
- ファイル単位の WDIO コードではなく、広範なテスト戦略(テストピラミッド/範囲)を決める必要がある場合。
入力仕様
- 疑似コードのコメントがあるスキャフォールド済みのスペックファイル(任意)。
- または、拡張/修正する既存の実装済みスペックファイル。
- プロジェクトに既存のページオブジェクト、フィクスチャ、ヘルパー。
- プロジェクトの規約(リンティング、命名、アサーションのスタイル)。
プロジェクトコンテキストファイル
実装の前に、利用可能な場合はプロジェクトのキャッシュファイルを読み込んでください。
.webdriverio-skills/project-context.md.webdriverio-skills/project-context.json.webdriverio-skills/custom-rules.md.webdriverio-skills/health-recommendations.mdreferences/website-analysis/<target>/website-analysis.mdreferences/website-analysis/<target>/website-analysis.json
これらを、規約、スクリプト、環境の使用方法、チームによる上書き設定のデフォルト情報源として使用してください。
ウェブサイト分析の参照情報は、ルート/コンポーネントのコンテキスト、想定される状態、認証が必要なフローへの対応を確認するために使用してください。
<target> は、小文字のサイトホスト名に解決してください(ユーザーの URL またはプロジェクトの baseUrl のホスト名を優先します)。
利用できない場合は unknown-target を使用し、他のコンテキスト情報を使って処理を続けてください。
ファイルが見つからない場合や古くなっている場合は、最初に managing-project-customizations を実行してください。
変換ワークフロー
- 対象がスキャフォールド変換か、既存テストの直接的な拡張/修正かを特定します。
- プロジェクトのコンテキストとカスタムルールを読み込み、厳守する制約として適用します。
- 疑似コードがある場合は、コメントを実行順に実装します。
- 新しいメソッドを作成する前に、既存のページオブジェクトのメソッドを優先して使用します。
- 耐性のあるセレクターと明示的な期待条件を使用します。
- 動作が明確になったら、疑似コードのコメントを削除します。
- 自明でない意図を説明するコメントだけを残します。
スイート開始時の状態管理
- スイートの開始時に、テスト間に漏れる可能性のある状態(Cookie、ローカルストレージ、セッション/認証状態)をリセットします。
- 再実行しても同じベースラインになるよう、開始時の事前条件を冪等にします。
- 隠れたテスト間の状態に頼らず、フックで明示的にセットアップすることを優先します。
- クリーンアップは必須として扱いますが、クラッシュ後に実行されない可能性のある
afterフックだけに依存しないでください。
テストデータの決定論的なセットアップとクリーンアップ
- 可能な場合は、API/フィクスチャを使って決定論的なテストデータを作成します。
- フィクスチャ/データには、用途が明確に分かる名前を付けます。
- 必要とするテストのスコープの近くにセットアップを置きます(厳密に分離する場合は
beforeEach、安定した状態を共有する場合はbefore)。 - 作成したデータには、必ずクリーンアップの手段を用意します。
- テストデータの前提条件をコードで検証してから処理します。
テスト構成のルール
- 各テストを、セットアップ、検証、ティアダウンの明確なフェーズに分けます。
- セットアップを共有する場合は、各テストにコピーせず、フック(
before、beforeEach)にまとめます。 - 各
it(...)は、ユーザーが観察できる1つの動作に焦点を当てます。 - テストは互いに独立させ、単独でも並列でも安全に実行できるようにします。
フレームワークのルール(Mocha/Jasmine)
describe、it、フックには、プロジェクト既存のスタイルを合わせます。- ネストした
describeブロックは、実装レイヤーではなくユーザーのコンテキストを表すために使用します。 - よりフラットな構成のほうが読みやすい場合は、深くネストしたスイートを避けます。
.only/.skipはローカルでのデバッグに限って使用し、仕上げる前に削除します。
ページオブジェクトのルール
- セレクターとページ固有のアクションは、ページオブジェクト/コンポーネントにまとめます。
- スペックでは動作とアサーションに集中します。
- 新しい抽象化を追加する前に、既存のページオブジェクトのメソッドを再利用します。
- 小さく目的を絞ったページオブジェクトのメソッドを追加し、何でも処理する汎用ヘルパーは避けます。
効率的な要素の検索
- 子要素を選択する前に、意味のあるコンテナーに検索範囲を絞ります。
- 同じセレクターを繰り返し検索せず、テストのステップ内で取得済みの要素を再利用します。
- インデックスによる検索より、一意で意味のあるセレクターを優先します。
- インデックスによる選択は、UI の仕様で位置が明示されている場合にのみ使用します。
セレクターのルール
- ユーザー向けのセレクター(
button=...、aria/...)を優先します。 - テキスト/ARIA が不安定な場合は、
data-testidを使用します。 - 壊れやすいクラスの連鎖や、レイアウトに依存するセレクターは避けます。
- 要素の検索範囲を絞り、衝突を減らします。
待機のルール
- 可能な場合は、操作(
click、setValue)の自動待機を利用します。 - 意味のある UI 状態の遷移には、明示的な待機(
waitForDisplayed、waitForClickable、waitUntil)を使用します。 - 内部実装の詳細より、ユーザーに見える結果を待つことを優先します。
- 同期の手段として
browser.pauseを使用しないでください。 - 短い固定待機は、既知の UI 制約(避けられないアニメーションのタイミングなど)に関連する場合にのみ許可します。使用はまれにし、理由を記録してください。
- 文書化された理由がない限り、暗黙のタイムアウトは既定値のままにします。
待機方法の判断ガイド
| 状況 | 推奨する方法 | 避ける方法 |
|---|---|---|
| 要素の操作 | WDIO の自動待機+操作 | 事前の pause |
| アクション後の非同期 UI 更新 | アサーションの再試行または waitFor... | 固定のスリープ |
| 要素以外の条件 | 明確な条件を指定した browser.waitUntil(...) | 手動ループによるポーリング |
| 既知のアニメーション遅延 | 安定したシグナルがない場合に限り、短く理由を記録した pause | 広範な長時間の一時停止 |
サードパーティ依存関係のアサーションを避ける
- 外部プロバイダーの内部動作ではなく、アプリケーションが担う動作をテストします。
- 外部要因による不安定さを避けるため、可能な場合はサードパーティとの連携をスタブ/モックします。
- 外部サービスとの契約は、ベンダーの稼働状況や UI ではなく、リクエスト/レスポンスの処理で検証します。
- 必要な場合に限り、外部連携経路のスモークチェックを最小限にとどめます。
アサーションのルール
- ユーザーに見える結果と重要な状態をアサートします。
expect-webdriverioのマッチャー(toHaveText、toBeDisplayed、toHaveUrlContaining)を使用します。- アサーション対象を明確にして、意味のある失敗メッセージが表示されるようにします。
- 動作が順序に依存する場合は、リストの件数/順序を明示的にアサートします。
- シナリオにとって重要な動作だけを検証し、不要な過剰アサーションは避けます。
テストの命名ルール
- テスト名は、動作が明確に伝わる文にします。
- ユーザーや開発者に馴染みのあるドメイン用語を使います。
- 曖昧な名前(
should work、happy path test)は避けます。 - 実装手順ではなく、期待される結果に基づいてテストに名前を付けます。
セキュリティのルール
- シークレットをハードコードしないでください。
- 認証情報を入力するときは、機密性の高い値をマスクします(サポートされている場合は
setValue(..., { mask: true }))。 - トークンや認証情報がログに漏れないようにします。
デバッグしやすいテストを書く
- テストのステップを実行順に読みやすく保ちます。
- 余分に調べなくても失敗箇所が分かるアサーション対象を使用します。
- 複雑な処理の流れには、簡潔なステップ単位のログを追加します。
- 失敗が意図にすぐ結び付くよう、スペック内の抽象化は浅く保ちます。
不安定なテストの切り分け手順
- 失敗を確実に再現します(まずは単一のテストを実行し、その後、繰り返し実行します)。
- 不安定なステップを特定します(セレクター、待機、データ、環境、共有状態)。
- 根本原因を分類します(タイミング、状態の漏れ、壊れやすいロケーター、テストデータのずれ、外部依存関係)。
- 根本原因を修正します(スリープ/再試行で隠さないでください)。
- 解決する前に複数回実行し、安定していることを確認します。
クイックリファレンス
| テストの意図 | WDIO での一般的な実装 |
|---|---|
| ページに移動する | await browser.url('/path') |
| コントロールを操作する | await el.click() / await el.setValue(...) |
| 表示結果を検証する | await expect(el).toBeDisplayed() |
| コンテンツ/状態を検証する | await expect(el).toHaveText(...) / toHaveValue(...) |
| 非同期の状態変化を待つ | await el.waitForDisplayed() または browser.waitUntil(...) |
よくある間違い
- スキャフォールドが常に必要だと思い込む。
- 疑似コードのコメントを実装せずに残す。
- コメントを壊れやすいセレクターに変換する。
- 条件を待たずに
browser.pauseを使用する。 - テストの意図が見えにくくなるほどヘルパー抽象化を多用する。
- テストを実行順序に依存させる。
- リトライを根本原因の修正の代わりとして扱う。
例
it('should default to showing the global feed', async function () {
const activeTabs = await $$('.feed-toggle .nav-link.active');
await expect(activeTabs).toBeElementsArrayOfSize(1);
await expect(activeTabs[0]).toHaveText('Global Feed');
});
完了とは、すべての疑似コードのコメントが保守しやすい WDIO コードに置き換えられているか、または自明でない文脈を示すものとして意図的に残されている状態です。