package.jsonのスクリプトを一通りbun runに揃えたのに、E2Eテストを走らせる瞬間だけnpx playwright testが残っている。そんな状態に心当たりがあるなら、2026年11月5日公開のPlaywright v1.65.0が関係してくる。公式のリリースノートによると、テストランナー自体がBun上で正式に動くようになった。
正式に動くとは言っても、bunコマンドに置き換えるだけで済むのか、それとも何か手順が要るのか。
--bunフラグが要る
公式のリリースノートの見出し「Run tests with Bun」は、こう説明している。「The test runner now runs under Bun.」(テストランナーは、いまBunの上で動く)。
ここで一度立ち止まりたい。bunxはBunに付属するコマンド実行ツールだ。「Bunのコマンドなのだから、bunx playwright testと打てば当然Bunで動くはず」と自分は思っていた。ところが同じ見出しの中に、これを否定する一文がある。「Pass the --bun flag, because without it bunx playwright test runs on Node.js」(--bunフラグを渡すこと。渡さなければbunx playwright testはNode.js上で動く)。
つまり実行コマンドの先頭がbunかnpxかではなく、--bunという明示的なフラグの有無でテストランナーの実行場所が決まる。Bunで動かすコマンドは次の形になる。
bunx --bun playwright test
フラグを付け忘れると、見た目はBun経由でもテストランナーはNode.jsのままになる。ここまでで「Bunで動く」が何を指すかは分かった。次に気になるのは、Playwrightがブラウザを操作する部分も含めてBun化されるのかという点だ。
ブラウザの動きも変わるのか
Playwrightでテストを実行すると、裏では2つの処理が順番に走っている。
- テストランナーが、書かれたテストコード(多くはTypeScript)を読み込んで実行する
- そのコードの指示を受けて、PlaywrightがChromiumやFirefox、WebKitといったブラウザを起動し、クリックや入力を実行する
今回の変更が対象にしているのは1だけだ。テストコードを読み込んで実行する側の実行環境が、Node.jsからBunに替わる。2のブラウザを操作する処理は、Node.js版のPlaywrightと同じ仕組みで動く。--bunフラグを付けても、ブラウザの起動方法や自動操作の挙動が変わるわけではない。
実行場所が替わるだけだとして、具体的に何がシンプルになるのか。
Babelが要らなくなる理由
テストランナーの実行場所がBunに替わると、テストコードの扱われ方も変わる。公式のリリースノートはこう書いている。「Bun transpiles your TypeScript test files itself, so Playwright does not use Babel or its compilation cache.」(BunはTypeScriptのテストファイルを自前で変換するため、PlaywrightはBabelもその変換キャッシュも使わない)。
Node.js版のPlaywrightは、TypeScriptで書かれたテストファイルをそのままでは実行できない。そこでPlaywright自身がBabelという変換ツールを内部で呼び、TypeScriptをJavaScriptに変換してから実行していた。変換にかかる時間を削るため、変換結果をキャッシュに保存する仕組みも持っている。
Bunはこの変換機能を、ランタイム自体にはじめから持っている。テストランナーがBun上で動く以上、TypeScriptのファイルを読み込む時点でBunが自分で変換してしまう。Playwright側がBabelを呼ぶ必要も、変換結果をキャッシュする必要もなくなる。構成がシンプルになるのは、変換を担う層がPlaywrightの外(Bun本体)に移ったからだ。
実行場所と変換の仕組みが変わると分かったところで、乗り換える前に確認しておきたいのは、Node.js版でできていたことのうち何が使えなくなるかだ。
Node.js版との機能差
公式のリリースノートは、Bunで動かすときに一部の機能が異なると明示している。
| 機能 | Node.js | Bun(--bun時) |
|---|---|---|
| ウォッチモード | 対応 | 非対応 |
| UIモードでのファイル変更時の自動再実行 | 対応 | 非対応 |
--only-changedのimport追跡 | 対応 | 非対応 |
--tsconfig・tsconfig.jsonのJSX設定 | 反映される | 反映されない |
| カスタムESMローダー | 対応 | 非対応 |
スタックトレースの非同期フレーム・API名のクラス名(locator.click) | 表示される | 表示されない(clickのみ) |
| テストのconsole出力のトレース・UIモードへの記録 | 残る | 残らない |
この表の差は「遅い・速い」ではなく「できる・できない」の違いだ。とくにウォッチモードとUIモードの自動再実行が使えない点は、ファイルを保存するたびに手動でテストを再実行する運用に戻ることを意味する。開発中に細かくテストを回しながらコードを書くスタイルなら、この差は毎日の作業時間に直接響く。
もう一点、見落としやすいのがスタックトレースの差だ。Node.js版では、テストが失敗した箇所がlocator.clickのようにクラス名付きで表示される。Bunで動かすと、非同期フレームが欠けるためclickとだけ表示され、どのオブジェクトの操作で失敗したのかをエラーメッセージ単体からは読み取りにくくなる。エラーの行番号を手がかりにコードを読み戻る手間が増える。
裏を返すと、CI上でまとめて一度だけ実行し、失敗時はログとスクリーンショットで調べる運用なら、この2つの差はどちらも実害が小さい。冒頭の「ビルドやAPIサーバーはBunに揃えたのに、テストだけNode.js」というチームには、CIと手元の開発ループを分ける道がある。CIのテスト実行だけ--bunフラグでBunに乗り換え、手元の開発ループは当面Node.jsのまま残す、という分け方が現実的だ。
公式のリリースノートによれば、この動作はLinux上のBun 1.4.3で検証されている。macOSやWindowsでの検証結果はリリースノートに記載が無く、ここでは確認できない。
まとめ
Playwright v1.65.0(2026-11-05公開)から、--bunフラグを付けることでテストランナーをBun上で実行できる。変わるのはテストコードを読み込んで実行する層だけで、Playwrightが操作するChromium・Firefox・WebKitの挙動はNode.js版と同じだ。BunがTypeScriptを自前で変換するため、PlaywrightはBabelとその変換キャッシュを使わなくなり、構成がひとつ減る。一方でウォッチモードやUIモードの自動再実行、カスタムESMローダーなど一部の機能はまだ使えない。ビルドやサーバーをBunに揃えている開発者にとっては、--bunフラグひとつでテスト実行までBunに統一できる変更になる。
コメント
気づきや感想をどうぞ記事への補足や、読んで考えたことをお寄せください。個人情報や、他の人を傷つける内容の投稿はお控えください。
投稿にはGoogleログインが必要です。
Googleでログイン投稿にはGoogleアカウントの表示名が公開されます。メールアドレスは取得・公開しません。
コメントを読み込んでいます…