codeceptjs-exploration について
CodeceptJS テストを作成・保守する開発者向けのページ探索ガイドです。ページスナップショットと要素検査、ロケーター選択の指針を組み合わせ、候補を検証して壊れやすいセレクターを避けます。
主な機能
- 01コード実行とページスナップショット取得
- 02要素の状態、テキスト、属性の確認
- 03ARIA、スクリーンショット、HTML による探索
- 04コンテキストと意味に基づくロケーター選択
- 05ロケーターの一意な一致を事前確認
活用シーン
- 01新しいテスト用のページ要素の特定
- 02失敗したテストのロケーター調査
- 03古い、または壊れやすいセレクターの置換
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ codeceptjs/ skills --skill codeceptjs-explorationインストール後、Claude Code で/codeceptjs-explorationを入力して読み込まれたか確認します。
詳細
CodeceptJS ページ探索
テストの作成、失敗のデバッグ、古くなったロケーターのリファクタリングには、共通する作業があります。ページを開き、適切な要素を見つけ、安定したロケーターを選ぶことです。このガイドでは、その手順を説明します。
ツール
run_code— CodeceptJS コードを実行し、生成された値を返します。console.*を記録し、最終状態のスナップショットを保存します。「何かを実行して結果を見る」場合に使います。snapshot— 操作せずに状態を取得します(URL、Cookie、localStorage、HTML、ARIA、スクリーンショット、コンソール)。「今ページに何が表示されているか」を確認する場合に使います。
アーティファクトの参照元は、次の優先順位で選びます。
- ARIA スナップショット — 構造化されていてスタイルによるノイズがなく、重複やアクセシブルネームの確認が簡単です
- スクリーンショット — 見た目を確認でき、ARIA ではわからないレイアウトの崩れを見つけられます
- HTML — ARIA だけでは情報が足りない場合(アクセシブルネームのないカスタムウィジェット、属性に応じた動作など)に限ります
要素を調べる
I.grabWebElement(locator) → 1 つの WebElement、I.grabWebElements(locator) → 配列。Playwright/Puppeteer/WebDriver で共通のヘルパー API を使用できます。
| 確認したいこと | メソッド |
|---|---|
| レンダリング済み/表示中/有効かどうか | exists()、isVisible()、isEnabled() |
| テキスト/値/属性/プロパティの取得 | getText()、getValue()、getAttribute(n)、getProperty(n) |
| ページ上の位置 | getBoundingBox() — 画面外やサイズがゼロかどうかを確認します |
| レンダリングされたマークアップ | toOuterHTML()、toSimplifiedHTML(300)(省略され、MCP で扱いやすい形式) |
| 修正に使う安定したセレクター | toAbsoluteXPath() |
| iframe 内 | inIframe(async (body) => { ... }) |
| 子要素をたどる | $(loc)、$$(loc) |
| ブラウザー側の関数 | evaluate(fn, ...args) |
目的のロケーターで見つからない場合に候補を探す
Edit で何も見つからない場合、コントロールの表示が「Change」だったり、aria-label="Edit user" が設定されていたり、.btn-edit 内に存在したりする可能性があります。I.grabWebElements と許容範囲の広い XPath を使って候補を幅広く探し、そこから絞り込みます。
XPath では、次の条件を OR でつなぎます。
- 表示テキスト —
text()(子孫要素も含める場合は.) - 属性 —
@class、@aria-label、@title、@data-action、@id - 同義語 — edit/change/modify、delete/remove/trash、submit/send/save
translate(...) で大文字と小文字を区別しない検索にします。
//*[contains(translate(., 'EDIT', 'edit'), 'edit')
or contains(translate(@class, 'EDIT', 'edit'), 'edit')
or contains(translate(@aria-label, 'EDIT', 'edit'), 'edit')
or contains(translate(., 'CHANGE', 'change'), 'change')]
結果に対して toSimplifiedHTML(150) を順に実行し、適切な候補を選び、その候補を識別できる属性またはテキストを使って安定したロケーターを確定します。
安定したロケーターを選ぶ
順番に 2 つのことを決めます。**検索対象を絞る領域(コンテキスト)**と、その領域内で要素を特定する方法です。先に領域を指定すると、識別子を短く、意味のあるものにできます。絞り込み時に見つけた識別情報は、コンテキスト引数に指定します。
I.click('Edit user', '.user-row') // ✅ region + what the user sees
I.click('#user-row-42 button.edit') // ❌ same element, brittle, unreadable
安定した領域には、ランドマーク(nav、main、{ role: 'dialog' })、アプリのシェルコンテナー(.sidebar、.toolbar、.modal)、locate(...) でデータを使って特定した行やカードがあります。識別子の優先順位(詳しい理由は codeceptjs-fundamentals の「Locators」を参照してください):
- 表示ラベル/アクセシブルネーム — 通常の文字列で
aria-labelにも一致するため、{ css: '[aria-label="..."]' }に展開しないでください - コンテキスト内で曖昧な場合、またはチェック対象にロールが含まれる場合は、ARIA ロール
- チームのテスト属性が存在する場合は、
customLocatorを使った$name - スコープを絞った複合 CSS:
I.click('button.edit', '#user-row-42') toAbsoluteXPath()— 最終手段です。チームにdata-testidの追加を依頼してください
検証していないロケーターを確定しないでください — run_code(I.seeElement(loc, context) または grabWebElement(loc))を使い、一致する要素が正確に 1 つであることを確認します。
よくあるパターン
- Strict mode で 2 件以上一致する →
grabWebElements('Save')とtoSimplifiedHTML(200)を各要素に実行して識別情報を見つけ、コンテキストとして渡します:I.click('Save', '.modal') - ボタンはレンダリングされているのに動作しない →
grabWebElement('Submit')にisEnabled()とgetBoundingBox()を実行します。無効状態か、画面外か、サイズがゼロでしょうか? - リスト内の行が違う →
grabWebElements('.user-row')を使い、各行のgetText()で特定してから、安定した識別子としてgetAttribute('data-id')を取得します - iframe 内 →
(await I.grabWebElement('iframe.editor')).inIframe(async (body) => body.$('button'))
避けるべきこと
- 候補を確認する前にロケーターを選ぶこと。
- セマンティックロケーターが利用できるのに、
toAbsoluteXPath()をコミットすること。 - コンテキストを使えば短くできるのに、スコープを指定しないロケーターをコミットすること。
- スクリーンショットを無視すること。「HTML に存在する」≠「ユーザーに見える」です。
- WebElement のメソッドで対応できるのに、
usePlaywrightTo/useWebDriverToを使うこと。
関連スキル
codeceptjs-fundamentals— ロケーターの優先順位、await ルールwriting-codeceptjs-tests— モード B の探索中にこれを呼び出しますdebugging-codeceptjs-tests— ライブ検査時にこれを呼び出します。オフライン版はcodeceptqです