migrate-selenium-java-to-codeceptjs について
Selenium または Selenide の Java テストスイートを CodeceptJS 4 に移行するためのスキルです。既存スイートを動かし続けながら、事前調査、並行環境の構築、テストパターンの移行を進めます。
主な機能
- 01Javaテストスイートと共通抽象を調査
- 02Javaプロジェクトと並行してCodeceptJSを導入
- 03テストをWebDriverヘルパーへ移行
- 04ページオブジェクト、ヘルパー、テストデータを変換
- 05再設計が必要なJava固有機能を特定
活用シーン
- 01SeleniumまたはSelenideの移行を計画
- 02CodeceptJSへの移行中もJavaテストを継続実行
- 03既存のテスト抽象をCodeceptJSの対応要素に対応付け
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ codeceptjs/ skills --skill migrate-selenium-java-to-codeceptjsインストール後、Claude Code で/migrate-selenium-java-to-codeceptjsを入力して読み込まれたか確認します。
詳細
Selenium / Selenide(Java)→ CodeceptJS 4 への移行
この移行は単なる構文の移植ではありません。すべてのファイルで言語が変わります。Java は JavaScript(または TypeScript)に、Maven/Gradle は npm に、JUnit/TestNG は CodeceptJS ランナーに置き換わります。機械的な変換は十分に実行可能です。メリットも確かにあります(セマンティックロケーター、自動待機、第一級の抽象化、AI による作成支援)。また、パターンも引き継げます。
押さえておくべき基礎的な違いは 3 つあります。
- テストは明示的な待機なしで順に実行されます。 CodeceptJS はすべての
I.*呼び出しを内部レコーダーに自動でキューイングし、DOM/要素の安定性を自動的に待ちます。Selenium のWebDriverWait+ExpectedConditions.*の定型コードは不要になります。Selenide の.shouldBe(visible)/.shouldHave(text(...))のチェーンは通常、アクション自体にまとめられます(I.click('Save')は待機してクリックし、アサーションを行います)。CodeceptJS のawaitはグラブ(await I.grabTextFrom(...))にのみ使用します。通常のアクションでも動作しますが、推奨されません。これは spec ファイルで最も大きく目に見える変化です。 WebDriver/driverではなく、ヘルパーを使います。I.*は設定済みのヘルパーに処理を振り分けます。デフォルトでは WebDriver ヘルパーを使用してください。 Java のテストスイートがすでに使用しているものと同じ W3C WebDriver プロトコルで通信するため、最も自然に移行できます。同じ Selenium サーバー、同じブラウザードライバー、同じケイパビリティ、そして使用している場合は同じ Grid を利用できます。WebDriver でテストスイートが成功したら、ヘルパーのブロックを 1 つ変更するだけで Playwright ヘルパーに切り替えられます(最新で高速、フレークが少なく、1 つの設定でネイティブに複数のブラウザーをサポート)。どちらの場合もテストコードは同一です。- 第一級の抽象化が用意されています。 ページオブジェクト、
authプラグイン、複数ユーザー向けのsession(...)、カスタムヘルパー、customLocatorプラグインが組み込まれています。Java のテストスイートでは、すでにこれらを(PageFactory、LoginHelper、DriverManagerで)一元管理していることが多いため、Java 固有の接着コードをそのまま引き継ぐのではなく、フレームワークの慣用的な方法に統合できます。
信頼できるリファレンス:node_modules/codeceptjs/docs/(basics、locators、playwright、webdriver、custom-helpers、pageobjects)。
実行する条件
次のいずれかに該当する場合です。
pom.xmlでselenium-java、selenide、webdrivermanager、junit-jupiter、junit、またはtestngが依存関係として宣言されている。build.gradle/build.gradle.ktsにorg.seleniumhq.selenium:selenium-java、com.codeborne:selenide、org.junit.jupiter:junit-jupiter、またはorg.testng:testngが含まれている。*Test.java/*IT.java/*Tests.java/*Steps.javaを含むsrc/test/java/ツリーがある。org.openqa.selenium.*(WebDriver、WebElement、By、WebDriverWait、ExpectedConditions、Actions、JavascriptExecutor、Select、Keys)からのインポートがある。com.codeborne.selenide.*(Selenide、SelenideElement、Configuration、Condition、ElementsCollection)からのインポートがある。- JUnit / TestNG のアノテーションがある:
@Test、@BeforeEach/@BeforeMethod/@BeforeClass/@BeforeAll/@BeforeSuite、@After*、@DataProvider、@ParameterizedTest、@FindBy/@FindAll。 PageFactory.initElements(...)、WebDriverManager.*.setup()、new ChromeDriver(...)、new RemoteWebDriver(...)、Selenide.open(...)、$(...)/$$(...)のチェーンを呼び出している。src/test/java/配下に Cucumber-JVM のステップ定義(io.cucumber.java.en.*)がある。- ユーザーが「Selenium / Selenide / Java から移行/移植/変換」と依頼している。
移行できないもの
最初に、できないことを正直に伝えておきましょう。
- テストコード内の Java 言語機能 — ジェネリクス、ストリーム、ラムダ、カスタム例外階層、AspectJ ウィービング、JUnit
@ExtendWith拡張機能、TestNGIInvokedMethodListenerリスナー。これらはプレーンな JS で再現します。通常はより短くなりますが、忠実な翻訳ではなく、最もシンプルな移植方法を選んでください。 - テストに関連付けられた Maven / Gradle のビルドフェーズ — 統合前後のフェーズ、プロファイル駆動のテスト除外、surefire-failsafe の分割。npm スクリプトと CodeceptJS の
--grep/tagフィルターで再実装します。 - デフォルトの WebDriver ヘルパーでのクライアント側ネットワークのインターセプト。WebDriver には Playwright の
I.mockRoute(...)に相当する機能がありません。WebDriver を使っている間は、WireMock(または任意のプロキシ/サービス仮想化ツール)をサイドカーとして使います。オプションで Playwright に切り替えた後、必要に応じてスタブをI.mockRoute(...)に移植してください。 - カスタムの Selenium
EventFiringWebDriver/ Selenide イベントリスナー — CodeceptJS では代わりにイベントフック(event.test.before、event.step.failed)とaiTraceプラグインを使用します。リスナーが不可欠な役割を担っていた場合は、それらを使って再実装してください。 - Java 固有のレポート機能(テストメソッドへの Allure アノテーション、ExtentReports、ReportPortal Java エージェント) — CodeceptJS のレポーターに切り替えます。ダッシュボード向けには
@testomatio/reporterが最も直接的な代替手段です。Allure の形式を維持する必要があるチーム向けには、CodeceptJS アダプターがあります。 - Cucumber-JVM のステップ定義言語とフック — フィーチャーファイルはそのまま移植し、ステップ定義は CodeceptJS BDD を使って JS で書き直します。Java 固有のグルーコード(
@ScenarioScope、PicoContainer DI)は移植できません。
ワークフロー
フェーズを順番に実行します。各区切りでコミットし、リグレッションが発生した場合に二分探索できるようにしてください。
1. Java プロジェクトの棚卸し
何かに手を付ける前に、まず全体像を把握します。2 段階で進めます。
プロジェクトの構成 — grep / find を使って、移行コストの目安を確認します。
pom.xml/build.gradle{,.kts}— Selenium/Selenide/JUnit/TestNG のバージョンと、追加の依存関係(RestAssured、WireMock、Allure、Cucumber、AssertJ、Hamcrest、Awaitility)を確認します。src/test/java/**/*.java— ファイル数とパッケージ構成を確認します。- ドライバーの初期化 —
WebDriverManager.*.setup()、new ChromeDriver(...)、RemoteWebDriver、Configuration.*(Selenide)の使用箇所を確認します。通常はDriverManager/BrowserFactory/BaseTestクラスに集約されています。 @FindBy(、@FindAll(、PageFactory.initElements(、WebDriverWait(、ExpectedConditions.、.shouldBe(、.shouldHave(、.shouldNot(、JavascriptExecutor、new Actions(、new Select(、@DataProvider、@ParameterizedTest、Cucumber.featureの出現回数を数えます。それぞれ、既知の置き換えパターンに対応します。
共通ロジックとページオブジェクト — Java のテストスイートは POM やヘルパーに依存していることが多いため、テストに手を付ける前に見つけます。
- ページオブジェクト — 通常は
src/test/java/**/pages/、**/pageobjects/、**/po/の下にあります。@FindByフィールドと、操作を実行するメソッドを持つクラスです。ほぼ必ず存在します。 CodeceptJS のページオブジェクトに 1 対 1 で移行します。 - ベーステストクラス —
BaseTest、BaseUITest、AbstractTestなどです。通常、@BeforeEachによるドライバーのセットアップ、@AfterEachによるドライバーの終了、失敗時のスクリーンショット取得ロジック、共通ユーティリティを含みます。ドライバーのセットアップは不要になります(ライフサイクルは CodeceptJS が管理します)。失敗時のスクリーンショット取得はscreenshotプラグインに移行し、共通ユーティリティはヘルパーに分割します(詳細は後述)。 - ヘルパー/マネージャークラス —
LoginHelper、ApiHelper、DbHelper、BrowserHelper、DataFactory、WaitUtilsなどです。UI ヘルパー(DOM の操作、JS の実行、Robot を使ったファイルアップロード)はWebExtraに移行します。HTTP ヘルパー(RestAssured ラッパー、プログラムによるログイン、API 経由のシード/後処理)はApiExtrasに移行します。DB 関連と純粋なユーティリティクラスは、通常の JS モジュールまたはApiExtrasのメソッドにします。 - リスナー/拡張機能 — TestNG の
ITestListener、JUnit 5 の@ExtendWith(...)などです。CodeceptJS のプラグイン、イベントフック、またはBefore/Afterフックに移行します。 - データプロバイダー/フィクスチャ —
@DataProviderメソッド、@ParameterizedTestのソース、Jackson/OpenCSV/Apache POI で読み込む JSON/CSV/Excel ファイルなどです。CodeceptJS のデータ駆動シナリオではData(...)に、ファイルの読み込みでは ES の import またはfs/promisesに移行します。 - Cucumber のステップ定義 — 該当する場合は、すべてのステップの正規表現と現在の Java 本文を一覧にします。それぞれ、CodeceptJS の BDD を使った JS のステップ定義に移行します。
共通抽象化ごとに、現在の Java での配置場所と、移行先の CodeceptJS の配置場所を記載した簡潔な棚卸しを作成します。コードを書く前に、ユーザーに確認してもらいます。
2. CodeceptJS を並行ディレクトリにインストールする
言語をまたぐ移行では、並行して共存させる必要があります。Java ファイルをその場で JS に書き換えることはできません。兄弟ディレクトリ(例:e2e/、codeceptjs/、またはチームが明確に分離することを望む場合は別のリポジトリ)を作成します。
mkdir e2e && cd e2e
npx codeceptjs init
WebDriver ヘルパーを選択します。 Selenium-Java からの移植先として最適です。同じ W3C プロトコル、同じ機能、そして利用している場合は同じ Grid を使えます。Java のテストスイートは CI で並行して実行し続けられるため、移植が完了するまでカバレッジを維持できます。
通常、ドライバーのセットアップは不要です。 WebDriver ヘルパーは WebdriverIO v9 上で動作し、対応するブラウザードライバーを実行時に自動でダウンロードして起動します。Chromedriver / Geckodriver をインストールしたり、Selenium サーバーを実行したり、host / port を設定したりする必要はありません。ヘルパーを設定して実行するだけでよく、新たに必要なものはありません。
// codecept.conf.js
helpers: {
WebDriver: {
url: 'https://your-app.example.com',
browser: 'chrome',
windowSize: '1280x720',
smartWait: 5000,
desiredCapabilities: {
'goog:chromeOptions': { args: ['--disable-gpu', '--no-sandbox'] },
},
},
},
ヘルパーは、接続情報(host / port)が設定されていない場合にのみ、ローカルドライバーを起動します。そのため、自動管理を有効にするには、これらを省略します。
smartWait を使うと、ロケーターを検索するたびに Selenide と同等の暗黙的な待機が適用されます。さらに自動リトライを組み合わせれば、Java のテストスイートにある WebDriverWait / ExpectedConditions.* の行のほとんどが不要になります。
代替手段:Selenium を Docker で実行します。 並行実行や分離実行、ブラウザーのバージョン固定、ローカルブラウザーのない CI、または既存の Grid が必要な場合にのみ使用します。規約については、codeceptjs-fundamentals と node_modules/codeceptjs/docs/webdriver.md § "Selenium in Docker (Selenoid)" で説明されています。コンテナーを起動して、ヘルパーブロックに host / port を追加します。これにより自動管理が無効になり、代わりにコンテナーへ接続します。
# Selenoid (parallel-friendly) — see https://aerokube.com/selenoid for full setup
docker run -d --name selenoid -p 4444:4444 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $PWD/selenoid:/etc/selenoid aerokube/selenoid:latest-release
# or the simplest single-browser option
docker run -d --name selenium -p 4444:4444 --shm-size=2g \
selenium/standalone-chrome:latest
// add to the WebDriver block only when using the Docker/Grid fallback
host: '127.0.0.1',
port: 4444,
移植に着手する前に、インストールのスモークテストを実行します。 スタブ Scenario(Scenario('boot', ({ I }) => I.amOnPage('/')))を用意し、npx codeceptjs run --steps を実行して、ブラウザーが開き、テストが成功することを確認します。ドライバー、機能、コンテナーに関する問題は、抽象化を移植した後ではなく、ここで解決します。
テストスイートが成功したら、Playwright への切り替えを検討します。 移行が完了し、WebDriver でテストが安定したら、ヘルパーを切り替えることで、1 つの設定によるクロスブラウザー対応(Chromium / Firefox / WebKit)、ネットワークのモックに使う I.mockRoute(...)、そして約 2〜3 倍の実行速度を得られます。移行は機械的に行えます。WebDriver ヘルパーブロックを Playwright ブロックに置き換え(playwright.md を参照)、Docker の代替手段を使っていた場合はそれを停止し、再実行します。テストコードはそのままです。WebDriver でテストが成功するまでは、これを行わないでください。 新たに加わる 2 つの要素(ヘルパーと移植したテスト)を同時にデバッグするのは、無駄な労力です。
3. 設定を移植する
Java の設定ソースを codecept.conf.{js,ts} に対応付けます。主な移植先:WebDriver ヘルパー(後の切り替えに備えた Playwright の代替設定も示します):
| Java のソース | CodeceptJS 4(WebDriver ヘルパー — デフォルト) | Playwright(後で切り替える場合) |
|---|---|---|
Configuration.baseUrl(Selenide) | helpers.WebDriver.url | helpers.Playwright.url |
Configuration.browser = "chrome" | helpers.WebDriver.browser: 'chrome' | helpers.Playwright.browser: 'chromium' |
Configuration.headless = true | desiredCapabilities['goog:chromeOptions'].args に --headless を追加します(または setHeadlessWhen(CI) を使用します) | helpers.Playwright.show: false |
Configuration.timeout/Selenium の暗黙的な待機 | helpers.WebDriver.smartWait(ロケーターの検索ごとに自動リトライします) | helpers.Playwright.waitForTimeout |
pageLoadTimeout | helpers.WebDriver.timeouts['page load'] | helpers.Playwright.timeout |
Configuration.browserSize = "1280x720" | helpers.WebDriver.windowSize: '1280x720' | helpers.Playwright.windowSize: '1280x720' |
ChromeOptions().addArguments(...) | desiredCapabilities['goog:chromeOptions'].args | chromium.args/launchOptions.args |
WebDriverManager.*.setup() | 削除します — WebdriverIO v9 はドライバーを自動管理します(セットアップ不要)。フォールバックを使用する場合のみ Docker を使います | 削除します — Playwright がブラウザーを管理します |
RemoteWebDriver の URL → Selenium Grid | helpers.WebDriver.host/port を追加して Grid/Selenoid を指定します(フォールバック経路) | Grid を削除します — Playwright はローカルで実行されます |
Maven surefire/failsafe の <systemPropertyVariables> | process.env.* | process.env.* |
pom.xml/build.gradle のテスト依存関係 | package.json の devDependencies(codeceptjs、webdriverio、任意のプラグイン) | package.json(codeceptjs、playwright) |
@Test(retryAnalyzer = ...)/Selenide のリトライ | トップレベルの retry: N | トップレベルの retry: N |
@Test(timeOut = 30000)(TestNG) | シナリオごとに Scenario(...).timeout(30) | シナリオごとに Scenario(...).timeout(30) |
| テストメソッドでの Allure | @testomatio/reporter または Allure CodeceptJS アダプター | 同じ |
4. 共有の抽象化を移植する
ここが土台になります。スペックを書き直す前に行ってください。各スペックの書き直しで必要な動詞(I.doSmth(...)、loginPage.fill(...))がすでに用意されていれば、作業量を減らせます。
共有ヘルパークラスに関する厳守事項。 Java の *Helper/*Util/*Manager クラスにあるすべてのメソッドを、カスタム CodeceptJS ヘルパーのメソッドにします。操作の種類に応じて、2 つのヘルパーに分けてください — アクセス方法が異なり、それぞれ適切な API も異なります。
WebExtra(lib/helpers/WebExtra.js)は、ブラウザーを操作する処理に使います — 開いているページ、DOM、JavaScript の実行、ストレージ、ネットワークレスポンスの待機が必要な処理です。すべてのJavascriptExecutor.executeScript(...)の本体はここに移し、browser.execute(...)(WebDriver)またはpage.evaluate(...)(後で Playwright に切り替えた後)として実装します。this.helpers['WebDriver'].browser(WebdriverIO のブラウザーインスタンス)にアクセスします。node_modules/codeceptjs/docs/custom-helpers.md § WebDriver Exampleを参照してください。ApiExtras(lib/helpers/ApiExtras.js)は、HTTP のみを扱う処理に使います — プログラムによるログイン、データのシード/ティアダウン、API に対する CRUD です。すべての RestAssured ラッパー/Apache HttpClient 呼び出しはここに移し、REST ヘルパー経由で実行します。this.helpers['REST'](またはGraphQL)にアクセスします。node_modules/codeceptjs/docs/api.mdを参照してください。
両方のヘルパーを codecept.conf.{js,ts} の helpers に登録します。
API の処理でブラウザーヘルパーの基盤となる HTTP 機能を使い、REST ヘルパーを迂回してはいけません。 REST と JSONResponse のスタックがスキップされ、ステップのログ記録、I.seeResponseCodeIsSuccessful によるアサーション、共有ヘッダーが使えなくなります。API でブラウザーと同じ認証が必要な場合は、設定の冒頭で Cookie を一度共有します。
import { setSharedCookies } from '@codeceptjs/configure'
setSharedCookies()
…または、トークンベースの認証では REST ヘルパーに defaultHeaders を設定するか、テストごとに I.amBearerAuthenticated(secret(token)) を使用します。
WebExtra の例 — WebDriver ヘルパーを使ったブラウザー操作です(BrowserHelper.java からの JavascriptExecutor 呼び出しは、ここでは browser.execute(...) になります)。
import Helper from '@codeceptjs/helper'
import fs from 'node:fs/promises'
export default class WebExtra extends Helper {
async scrollIntoView(selector) {
const { browser } = this.helpers['WebDriver']
const el = await browser.$(selector)
await el.scrollIntoView()
}
async setLocalStorage(key, value) {
const { browser } = this.helpers['WebDriver']
await browser.execute((k, v) => localStorage.setItem(k, v), key, value)
}
async writeJsonFile(filePath, data) {
await fs.writeFile(filePath, JSON.stringify(data, null, 2))
}
}
後で Playwright ヘルパーに切り替えるときは、各メソッドの本体だけを変更します。
WebExtraが提供するI.*のインターフェイスは変わりません。this.helpers['WebDriver'].browserをthis.helpers['Playwright'].pageに置き換え、browser.execute(...)をpage.evaluate(...)に変換します。テストは変更不要です。
ApiExtras の例 — HTTP のみを使います(LoginHelper.java からの RestAssured ラッパーはここに配置されます)。
import Helper from '@codeceptjs/helper'
export default class ApiExtras extends Helper {
async loginViaApi(email, password) {
const REST = this.helpers['REST']
await REST.sendPostRequest('/api/auth/login', { email, password })
}
async seedUser(payload) {
const REST = this.helpers['REST']
const { data } = await REST.sendPostRequest('/api/users', payload)
return data
}
}
ヘルパーのコードスタイル — どちらにも適用されます。
- すべての
import文はファイルの先頭に記述します。メソッド内でconst fs = await import('node:fs/promises')とすることはできません。 - 組み込みアサーション(API では
I.seeResponseCodeIsSuccessful、ブラウザーではI.seeElement)、ExpectHelper、またはcodeceptjs/assertionsのファクトリーを使います。if (cond) throw new Error('...')は使わないでください。失敗時には、適切なアサーションエラーが表示される必要があります。 WebExtraでユーザーをキーとするセッションキャッシュのマップを追加している場合、authプラグインを再実装しています。そこで作業を止め、セッションの再利用はauthプラグイン(フェーズ 8)に任せてください。
ページオブジェクト。 CodeceptJS ではページオブジェクトが DI の第一級の要素として扱われるため、Java の POM は非常に簡単に移植できます。慎重に移植してください — 元の Java クラスにあったメソッドだけを残します。PageFactory は完全に削除してください。@FindBy が提供する遅延検索は、I.* の呼び出しで通常のロケーター文字列を使えば、すでに実現できます。
// Java
public class LoginPage {
@FindBy(id = "email") WebElement emailField;
@FindBy(css = "[type=submit]") WebElement submitBtn;
public LoginPage(WebDriver driver) { PageFactory.initElements(driver, this); }
public void login(String email, String password) {
emailField.sendKeys(email);
$(By.id("password")).setValue(password);
submitBtn.click();
}
}
// CodeceptJS
import { inject } from 'codeceptjs'
const { I } = inject()
export default {
fields: {
email: '#email',
password: '#password',
submit: { css: '[type=submit]' },
},
login(email, password) {
I.fillField(this.fields.email, email)
I.fillField(this.fields.password, secret(password))
I.click(this.fields.submit)
},
}
codecept.conf.{js,ts} の include に登録すると、ページオブジェクトが Scenarios に自動注入されます。
避けるべきページオブジェクトのアンチパターン(元の Java コードにすでにある場合を除く)。
- アサーションメソッド(
checkTitleVisible() { I.seeElement(...) })— ページオブジェクトにはアクションを表す動詞(fillForm、submitOrder)を使います。アサーションはテストに記述してください。 - 単一の
I.click/I.see*/I.grabTextFromを呼び出すだけの一行ラッパー — テストからI.*を呼び出すのと比べて、ラッパーを使う利点はありません。 - 1 つのテストだけで使われるメソッド — 手順はテストに記述してください。
- あらゆるメソッド内の
if (cond) throw new Error(...)— 代わりにI.see*、I.seeNumberOfElements、ExpectHelper、またはcodeceptjs/assertionsのファクトリーを使ってください。
フック。 Java の @BeforeEach/@BeforeMethod によるドライバーのセットアップは不要です(ライフサイクルは CodeceptJS が管理します)。その他のフック本体は CodeceptJS のフックに移植します。@BeforeEach/@BeforeMethod → Before(({ I }) => ...)、@BeforeAll/@BeforeClass → BeforeSuite(...)、@After* → 対応する After*。プロジェクト全体のセットアップ(DB シード、API トークンの発行)は、設定の bootstrap()/teardown() に記述します。
次に進む前に、正常に動作することを確認してください。npx codeceptjs check -c <config> が成功し、npx codeceptjs list -c <config> に Java のすべてのヘルパーメソッドが、WebExtra または ApiExtras のいずれかが提供する I.* アクションとして表示される必要があります。
5. 仕様ファイルを変換する
フェーズ 4 の抽象化を活用しながら、1 ファイルずつ進めます。仕様ごとの作業は writing-codeceptjs-tests スキルに任せてください。このスキルは MCP 経由で実際のブラウザーを操作し、各手順を検証してからコミットします。
| Java(JUnit 5 / TestNG / Selenide) | CodeceptJS 4 |
|---|---|
class LoginTest { @Test void X() { ... } } | Feature('Login') + Scenario('X', ({ I }) => { ... }) |
@Test、クラスごとに複数 | それぞれに Scenario(...) を 1 つ |
@DisplayName("X")(JUnit 5)/@Test(description = "X")(TestNG) | Scenario(...) のタイトル |
@BeforeEach/@BeforeMethod | Before(({ I }) => { ... }) |
@AfterEach/@AfterMethod | After(({ I }) => { ... }) |
@BeforeAll/@BeforeClass | BeforeSuite(({ I }) => { ... }) |
@AfterAll/@AfterClass | AfterSuite(...) |
@Disabled/@Ignore/enabled = false | xScenario(...) または Scenario.skip(...) |
@Tag("smoke")(JUnit 5)/@Test(groups = "smoke")(TestNG) | Scenario(...).tag('@smoke') |
@ParameterizedTest + @CsvSource(...) | Data([{ ... }, { ... }]).Scenario(...) |
@Test(dataProvider = "rows") + @DataProvider | 同様に Data(rows).Scenario(...) |
driver.get('/x')/Selenide.open('/x') | I.amOnPage('/x') |
loginPage.login(...)(POM 呼び出し) | LoginPage.login(...)(ページオブジェクトが自動で注入されます) |
明示的な待機コードは削除します。 これは機械的な編集の中で最も大きな変更です。
// Selenium — gone
new WebDriverWait(driver, Duration.ofSeconds(10))
.until(ExpectedConditions.elementToBeClickable(By.id("save")))
.click();
// Selenide — collapses
$("#save").shouldBe(visible).click();
// CodeceptJS — auto-waits
I.click('#save')
特定の待機が重要な場合(クリック前にスピナーが消えるのを待つ場合など)は、適切な I.waitFor* を使って残します。
I.waitForInvisible('.spinner', 10)
I.click('#save')
反復処理。 テスト、ページオブジェクト、ヘルパーでは、I.* 呼び出しを含むループに for...of を使います。Array.prototype.forEach は決して使わないでください。.forEach は反復コールバックの戻り値を無視するため、その中の await は外側の関数をブロックしません。また、CodeceptJS レコーダーがステップを順不同でキューに入れたり、ループが終わる前にシナリオを終了したりする可能性があります。
for (const sort of testSort) {
I.click(locate(this.filterFormLabel).withText(sort))
}
バッチごとに:npx codeceptjs dry-run --steps -c <config> を実行します。すべてのシナリオを読み込み、すべての I.* 呼び出しを解決しますが、ブラウザーは使いません。タイプミス、インポート漏れ、include に含まれていないページオブジェクト、存在しない動詞を数秒で検出できます。実際の実行に進む前に修正してください。
次に、バッチを実行します:npx codeceptjs run --steps -c <config>。
- 最初の実行は、ほとんどの場合失敗します。ロケーターのずれ、明示的な
WebDriverWaitコードで隠れていたタイミングの問題、認証/セッションの違い、データの前提条件などが原因です。想定内です。修正も移行作業の一部です。 - 失敗するたびに
debugging-codeceptjs-testsを呼び出し、その場で修正します(ブレークポイント、実際のページの検査、検証済みの修正)。当てずっぽうの書き直しや、retryで問題を隠すことはしないでください。 - バッチの完了は、ドライランが通ったときではなく、実行がすべて成功したときです。
6. ロケーター
すべてのロケーターにコンテキストを指定してください。 すべてのアクションの最後の引数で検索範囲を限定します — I.click('Save', '.toolbar')、I.fillField('Email', '[email protected]', '#login-form')、I.click({ role: 'button', name: 'Delete' }, '.modal')。短いセマンティックロケーターまたは ARIA ロケーターにコンテキストを加えるほうが、長くてスコープのないロケーターより適しています。ページの内容に即した読みやすさを保ち、重複するラベルを長くせずに区別でき、マークアップの変更にも強くなります。以下の表の各行にこれを適用してください — ソースフレームワークのチェーンは、通常、領域 と ユーザーに表示される内容 にきれいに分割できます。
CodeceptJS での優先順位 — 条件に合う中で最も優先順位の高いものを選び、コンテキストを加えます。
- セマンティック文字列 — ボタンのテキスト、ラベル、プレースホルダー、リンクテキスト:
I.click('Save', '.toolbar')、I.fillField('Email', '[email protected]', '#login-form')。 プレーンな文字列はすでにaria-labelに一致するため、aria-label="Save"のアイコンのみのコントロールにはI.click('Save', <context>)を使います —'aria-label=Save'や{ css: '[aria-label="Save"]' }は使わないでください。 - ARIA ロール —
I.click({ role: 'button', name: 'Sign In' }, '#login-form')。 customLocatorプラグイン経由の$name— テストスイートでdata-test/data-qa属性を多用している場合。locate()ビルダー —I.click(locate('button').withText('Edit').inside('tr').withText('Acme'))。多くの場合、I.click('Edit', locate('tr').withText('Acme'))のように分割するほうが適しています。- CSS / XPath — 最後の手段としてのみ使用します。
Java のテストスイートでは、By.id、By.cssSelector、By.xpath、By.linkText、@FindBy(...) が多用されます。対応関係は次のとおりです。
| Java | CodeceptJS |
|---|---|
By.id("save") / @FindBy(id = "save") | '#save' |
By.cssSelector(...) / @FindBy(css = ...) | { css: '...' } |
By.xpath(...) / @FindBy(xpath = ...) | { xpath: '...' } |
By.linkText("Edit") / @FindBy(linkText = ...) | 'Edit'(セマンティック) |
By.partialLinkText("Edit") | locate('a').withText('Edit') |
By.tagName("button") / By.className(...) | 'button' / '.cls' |
By.name("email") | { name: 'email' }(Selenide 相当の [name=email] 検索) |
@FindBy(how = How.NAME, using = "email") | { name: 'email' } |
Selenide $(...).find(...) / .parent() | locate(...).inside(...) / .parent() |
$$(...).filter(text("Active")).first() | locate(...).withText('Active').first() |
テストスイートで [data-test=...] / [data-qa=...] 属性を多用している場合は、customLocator プラグインを有効にして、{ css: '[data-test=submit]' } ではなく $submit と書けるようにしてください。詳しいガイダンスは writing-codeceptjs-tests § ロケーターを参照してください。
7. アクション、アサーション、値の取得
| Java(Selenium / Selenide) | CodeceptJS 4 |
|---|---|
el.click() / $(...).click() | I.click(sel) |
el.sendKeys("x") / $(...).setValue("x") | I.fillField(sel, 'x') |
el.clear() / $(...).clear() | I.clearField(sel) |
new Select(el).selectByVisibleText("A") / $(...).selectOption("A") | I.selectOption(sel, 'A') |
チェックボックス el.click() / $(...).setSelected(true) | I.checkOption(sel) / I.uncheckOption(sel) |
new Actions(driver).moveToElement(el).perform() | I.moveCursorTo(sel) |
Actions...dragAndDrop(a, b).perform() | I.dragAndDrop(srcSel, dstSel) |
Actions...keyDown(Keys.CONTROL).sendKeys("a")... | I.pressKey(['Control', 'a']) |
el.isDisplayed() / $(...).shouldBe(visible) | I.seeElement(sel) |
el.getText() / $(...).getText() | await I.grabTextFrom(sel) |
$(...).shouldHave(text("X")) / assertEquals("X", el.getText()) | I.see('X', sel) |
$(...).shouldHave(value("X")) / assertEquals("X", el.getAttribute("value")) | I.seeInField(sel, 'X') |
$$(...).shouldHave(size(5)) / assertEquals(5, els.size()) | I.seeNumberOfElements(sel, 5) |
driver.getCurrentUrl().contains("/x") / webdriver().shouldHave(url(...)) | I.seeInCurrentUrl('/x') |
((JavascriptExecutor) driver).executeScript(js, args) | page.evaluate を呼び出す WebExtra のメソッド |
driver.manage().getCookies() | await I.grabCookie() |
driver.manage().addCookie(...) | I.setCookie({...}) |
((TakesScreenshot) driver).getScreenshotAs(...) | 削除 — 失敗時は screenshot プラグインが処理します。手動の場合は I.saveScreenshot('name.png') |
await を付けるのは値の取得だけです。通常のアクションは自動的にキューに追加されます。
8. セッションと認証
Java のスイートには、UI ログインやプログラムによるログインと Cookie の注入を行う LoginHelper / AuthBase がほぼ必ず含まれています。どちらも auth プラグインに移行できます。セットアップの手順については、codeceptjs-auth スキルを参照してください。
- プログラムによるログイン →
ApiExtrasのメソッド(loginViaApi)。authプラグインのロール定義がこれを一度呼び出し、結果の Cookie / ストレージ状態をキャッシュします。 - UI ログイン →
WebExtraのメソッド(login)。authプラグインのロールから同じ方法で呼び出します。 - テスト間での Cookie の再利用 → 手動のロジックは削除します。
authはヘルパーの Cookie とストレージをキャッシュします(Playwright のstorageState、WebDriver の Cookie ジャーのいずれでも、同じプラグイン設定で利用できます)。 - 複数ユーザーのシナリオ →
codeceptjs/effectsのsession(...)を使用します。
9. テストデータとフィクスチャ
| Java | CodeceptJS 4 |
|---|---|
Object[][] を返す @DataProvider | Data([{ ... }, { ... }]).Scenario(...) |
@ParameterizedTest + @CsvSource / @ValueSource | Data([...]).Scenario(...) |
Jackson ObjectMapper.readValue(jsonFile, ...) | import users from './fixtures/users.json' with { type: 'json' } |
OpenCSV CSVReader | @codeceptjs/data または通常の csv-parse インポート |
| Apache POI による Excel の読み込み | 使用頻度は低いです。事前にシートを JSON / CSV に変換するか、必要な場合に限り xlsx を使用します |
Faker(Java) | @faker-js/faker(そのまま置き換えて使えます) |
10. API テストとモック
| Java | CodeceptJS 4 |
|---|---|
RestAssured given().when().then() | REST ヘルパー:await I.sendPostRequest(...) + I.seeResponseCodeIsSuccessful / I.seeResponseContainsKeys / Zod スキーマ |
| Apache HttpClient のラッパー | REST ヘルパー経由で ApiExtras のメソッドを呼び出します |
| WireMock のクライアント側スタブ | WebDriver では WireMock を維持します(または任意のサイドカープロキシを使用します)。WebDriver にはクライアント側のネットワークインターセプト機能がありません。後で Playwright に切り替えた後、I.mockRoute(url, route => route.fulfill({...})) に移行します |
| WireMock のバックエンドサイドカー | サイドカープロセスとして WireMock を実行したままにします。CodeceptJS は、どちらの場合もバックエンドサービスのモックを置き換えません |
WebDriver ヘルパーが対応していない唯一の機能は、クライアント側のネットワークモックです。Java スイートで WireMock のクライアント側スタブを多用していて、それらを
I.mockRoute(...)としてインラインで使いたい場合は、WebDriver でテストが成功した直後に Playwright への切り替えを予定する強い理由になります。
11. Cucumber-JVM(使用している場合)
Java スイートが Cucumber 駆動の場合:
.featureファイルは現在の場所に置いたままにするか、CodeceptJS プロジェクト内のfeatures/に移動します。- CodeceptJS BDD(
node_modules/codeceptjs/docs/bdd.md)を設定して、これらのファイルを読み込みます。 - Java のステップ定義をそれぞれ JS のステップ定義に書き換え、
I.*とページオブジェクトを呼び出します。フィーチャーを変更せずに済むよう、ステップのテキストと正規表現はそのままにします。 - Java 固有の Cucumber glue(
@ScenarioScope、PicoContainer、cucumber.options)は不要になります。CodeceptJS BDD には独自のフック機能があります。
12. Java スイートの廃止
すべての spec の移植が完了し、CodeceptJS の実行が CI で成功してから、次の作業を行います。
- Java のテストソース(テスト専用の場合は
src/test/java/、src/test/resources/)を削除します。 pom.xml/build.gradleから Selenium / Selenide / JUnit / TestNG / RestAssured / WireMock-Java / Allure /webdrivermanagerを削除します。- CI から Maven / Gradle のテスト実行コマンドを削除し、
npx codeceptjs run-workers <N>(またはrun)ジョブに置き換えます。
確認
- デフォルトの方法では、確認は不要です。WebdriverIO v9 がドライバーを起動します。Docker にフォールバックする場合のみ、コンテナに接続できること、および
curl -fsS http://127.0.0.1:4444/statusがready: trueを返すことを確認します。 npx codeceptjs check -c <config>— 設定、ヘルパー、プラグインの健全性を確認します。npx codeceptjs list -c <config>— 移植した Java のヘルパーメソッドがすべてWebExtraまたはApiExtrasのI.*アクションとして表示されること、各ページオブジェクトのメソッドが表示されることを確認します。npx codeceptjs dry-run --steps -c <config>— すべての Scenario が読み込まれることを確認します。- WebDriver で全件実行します:
npx codeceptjs run --steps -c <config>。初回の実行では失敗が想定されます。失敗ごとに、debugging-codeceptjs-testsスキルを使って修正してください(retryや、根拠のない書き換えはしないでください)。変換したスイート全体が成功したときにのみ、移行は完了です。 codeceptjs-run-analysisに引き継ぎ、output/trace_*/のアーティファクトを調査します(aiTraceプラグインを有効にする必要があります)。find src/test/java -name "*.java"— Java のツリーを削除する前に、結果が空であることを確認します。
任意のフォローアップ:Playwright に切り替える
移行が完了し、WebDriver の実行が CI で安定したら、今後の作業に向けてヘルパーの切り替えを検討してください。
npm i -D playwright。helpersのWebDriverブロックをPlaywrightブロックに置き換えます(node_modules/codeceptjs/docs/playwright.mdを参照)。host/port/desiredCapabilitiesは削除します。- 各
WebExtraメソッドの本体を、this.helpers['WebDriver'].browser.execute(...)からthis.helpers['Playwright'].page.evaluate(...)に変換します。ヘルパーが追加するI.*のインターフェースは変わりません。 - Docker にフォールバックしていた場合は、コンテナを停止します。Playwright がブラウザーを独自に管理します。
dry-runとスモークテストを再実行します。ページオブジェクト、spec、フィクスチャ、authプラグインの設定に変更はありません。
これにより、1 つの設定から複数ブラウザー(Chromium / Firefox / WebKit)でのテスト、高速な実行、ネイティブな I.mockRoute(...) によるネットワークモック、MCP ループを通じたより充実した ARIA スナップショットを利用できます。
関連スキル
writing-codeceptjs-tests— 仕様ごとの書き換え手順(MCP 主導の検証済みステップ)debugging-codeceptjs-tests— 最初の全件実行から、失敗したテストすべてに使用しますcodeceptjs-auth—LoginHelper/ Cookie ベースのセッション再利用を置き換えますcodeceptjs-fundamentals— Docker にフォールバックする Selenium の規約。配線を確認するため、移行後に実行します- 参考ドキュメント:
node_modules/codeceptjs/docs/(基本、webdriver、playwright、ロケーター、カスタムヘルパー、API、認証、BDD、エフェクト)