🐕

JSDOMを使ったReact Testing Library等のテストが時代遅れかも知れないので調べてみた

に公開

TL;DR

フロントエンドテストでJSDOMを推奨しない流れがあると聞いて調査してみた。
結論として、Vitest Browser ModeやPlaywright Component Testingなど実ブラウザベースのツールは確かに登場しているが、2025年9月時点では以下の状況:

  • 急いで移行する必要はない: JSDOMは依然として広く使われており(週3,400万DL超)、実ブラウザテストは初回起動で5〜10秒、反復実行でも20ms〜数分遅くなるケースがある
  • コストとメリットのバランス: 既存のJSDOMテスト資産を捨てて全面移行するコストは大きく、移行による即座のメリットは限定的
  • 将来的には移行の流れ: ツールの成熟と共に実ブラウザテストが標準になる可能性は高いが、現時点ではVitest Browser Modeも"experimental"扱い

推奨アプローチ: 当面はJSDOMを維持しつつ、ページ級のクリティカルなハッピーパスだけを実ブラウザで補強するハイブリッド運用が現実的。ツールの成熟度を見極めながら段階的に移行を検討する。


ネタ元の記事 "Why I Won't Use JSDOM"
https://www.epicweb.dev/why-i-won-t-use-jsdom

ネタ元記事 "Why I Won’t Use JSDOM" の主張

JSDOMの根本的問題
Node.jsで動作し、ブラウザのふりをするが、結果的にどちらでもない中途半端な存在になっている。具体的な技術的制限として、標準ではないイベントを生成して環境間で一貫性がない、グローバルAPIを問題のある方法でパッチする、ブラウザのエクスポート条件を強制することで依存関係を不適切に解決する、などがある。

テスト哲学
記事の核心は「テスト環境が実際のコード実行環境に近いほど、テストの価値が高まる」という考え方にある。この観点から見ると、JSDOMはNode.js上でブラウザを模倣するにすぎず、実際のブラウザ環境との乖離が避けられない。

推奨される解決策
著者はVitest Browser Modeを主要な代替案として推奨している。これは実際のブラウザ環境でコンポーネントテストを実行する仕組みで、従来のReact Testing Libraryと似たAPIを保ちつつ、真のブラウザ環境での検証を可能にする。またPlaywrightを実行エンジン(ブラウザプロバイダー)として活用することで、より強力で信頼性の高いテスト環境を構築できるとしている。

結論
20年前に必要だったポリフィルによる解決策から脱却し、現代のツールを使って「ブラウザ向けコードを実際のブラウザでテストする」パラダイムシフトを提唱している。

調べる前の仮説

JSDOM自体はまだ非推奨ではないが、Vitest Browser Mode や Playwright Component Test などの実ブラウザを用いたテストが普及したので、それぞれ使い分けることが重要。軽量高速が効果的なユニットテストなどではVitest + JSDOMで高速に。よりユーザー目線の統合テストは Vitest Browser Mode などを用いて実DOMでテストを行う。のが良いのではないだろうか?

まずは主張と実体を調べ、その課題を解決するツールが育っているのか、その課題感は目的に対して妥当なのか?を調べる必要がある。

※仮説を持つことで、成功でも失敗でも、確実に自分の学習を高めることが出来るため、調査前段階の手持ちの知識で当たりをつけておいています。

調査中の疑問と解決リスト(執筆中メモ)

  • なぜフロントエンドテストにはJSDOMが用いられたのか?
    • E2Eと比較して軽量高速にDOMを模倣したテストを実現したかったから
  • なぜ記事では「JSDOMを使わない」と主張しているのか?
    • JSDOMは、node.jsで実行され、ブラウザのふりをするが、結局どちらでも無いから

JSDOMを推奨しない流れは、世の中的には受け入れられ始めているのか?

結論: 実ブラウザベースのテストツールは登場しているが、JSDOMは依然として主流であり、市場は移行期にある

市場データと技術トレンド

推進派の反応

より慎重な見解・使い分けを主張する意見

具体的な移行事例

技術的背景の変化

  • CI/CD環境の改善: ヘッドレスブラウザの起動コストが大幅削減
  • ツールの成熟: Playwright/Puppeteerで実ブラウザテストが簡単に
  • デバッグ体験: 視覚的確認や実際のブラウザデベロッパーツールが使用可能

参考記事:

JSDOMと実ブラウザのテストの実行時間の差はどの程度あるのか?

結論: 実ブラウザテストはJSDOMより遅く、初回起動で5〜10秒、反復実行でも20ms〜数分の差が発生する。環境やテスト規模で大きく変動するため、CI時間への影響を見極めた上でハイブリッド運用が推奨される

今回は公開記事を調べるまでとしました。理想は全部同じ条件で試してみたかったですが、、、時間が足りず申し訳ない。

実測値から見える違い

  • ミニマムケースでは、Zenn記事の検証でVitest Browser Mode 95ms / JSDOM 75ms(約20ms差)という実測値が報告されている。[Vitest Browser Modeがアツい]
  • 初回起動と反復実行時間について、株式会社一創の検証ではBrowser Modeの初回起動に5〜10秒のオーバーヘッドが発生し、シンプルなDOM操作でもjsdomより体感で遅くなることが指摘されている。[Vitest Browser Modeの導入・セットアップ方法を徹底解説]
  • 大規模スイートでは、Playwright Component TestをChromium/Firefox/WebKit/モバイルChromeで並列実行した事例が約1,200テストを17分(2ブラウザ構成なら10分)で完走し、JSDOMベースより30〜40%遅い一方で許容範囲だったと報告されている。[Write tests. Not too many. Mostly end-to-end.]
  • ブラウザ起動に時間がかかるケースとして、Playwrightが13テストでも1分〜1分30秒かかると報告されたGitHub Issueがあり、環境やバージョン差でオーバーヘッドが大きく変動する点に注意が必要だ。[Playwright issue #22815]

CI運用での示唆

  • Browser ModeはJSDOMより遅くなる前提で「どのテストを実ブラウザに寄せるか」を決め、軽量ケースはJSDOMに残すハイブリッド運用が推奨される。[Vitest Browser Modeの導入・セットアップ方法を徹底解説]
  • Playwright Component Testは30〜40%遅延しつつも、並列化すれば17分で1,200テストを処理できるため、UIクリティカルな経路に絞ったスモークテストとして組み込むとCIの遅延を抑えやすい。[Write tests. Not too many. Mostly end-to-end.]
  • 初回ダウンロードのオーバーヘッドは避けられないので、Playwright公式が推奨するようにブラウザバイナリのキャッシュ場所を明示しつつ、毎回のnpx playwright installが走る前提でCI時間を見積もる。[Playwright公式ドキュメント: Continuous Integration]

今現在 JSDOM + React Testing Library + Vitest の構成で Integration Test が沢山実装してある場合、どうすると良さそうか?

仮説: ページ級ハッピーパスをBrowser Modeで補強する

Vitest 3系のtest.projects機能を使うと、JSDOMとBrowser Modeを同じリポジトリ内で並行運用できる。プロジェクトごとにincludeグロブを指定できるため、tests/**/*.unit.test.tsはJSDOMで、tests/**/*.browser.test.tsは実ブラウザで、というようにファイル名やディレクトリ単位でテスト環境を振り分けられる。

この仕組みを活かせば、軽量なユニットテストはJSDOMで高速に回し、ページ級のクリティカルなハッピーパスだけをBrowser Modeで補強するハイブリッド運用が現実的かもしれない。
これなら既存のJSDOMテスト資産を捨てる必要がなく、CI時間の増加も最小限に抑えられる。

Browser Modeは2025年6月時点でも“experimental”扱いで、ブラウザ起動の初期化オーバーヘッドやPlaywrightなどのプロバイダー設定が運用コストになる?Vitestの背景解説体験記事でもJSDOMより遅くなる傾向が報告されているため、ページ級ハッピーパスのみに限定することでCI時間の増加を抑えられるのでは無いか。

一方で実ブラウザはレイアウトやネイティブイベント、ブラウザAPIの差異を捕捉でき、JSDOMでは検出しづらいバグを拾いやすい。Epic Web Devの記事Playwrightコンポーネントテストの大規模事例が示すように、重要なユーザーフローだけをBrowser Modeへ寄せるハイブリッド運用が信頼性と実行コストのバランスを取りやすいのでしょう。
((JSDOMでそんなに落とし穴に引っかかったことが無いから調査結果としてだけおいておきますね。落とし穴報告お待ちしております。SafariとかMobileとか考慮を本気でやり始めたら出会うんですかね?))

そのままJSDOMでしばらく進む、成熟に合わせて乗り換える

2025年9月時点でもJSDOM + React Testing Library + Vitestの構成は、セットアップ済みのCI/CDや開発者スキルセットをほぼそのまま活かせる「枯れた」選択肢として機能し続けている。移行コストとリスクをどう捉えるかを整理するために、当面JSDOMを維持した場合の利点・欠点と、実ブラウザ系ツールが「成熟した」と判断できる指標を言語化しておく。

メリット

  • 既存テスト資産の再利用: モックやカスタムレンダラーなどJSDOM前提で作られた支援コードを考慮する必要がなく、開発チームの学習コストも最小化できる。
  • 実行速度と安定性: 実ブラウザを起動しないため、Browser Modeよりもウォームアップと反復実行が依然として高速で、体験記事でも20ms前後の差が観測されている。[Vitest Browser Modeがアツい]
  • インフラ要件が軽い: Node.js環境だけで完結するので、Playwrightのバイナリ配布やGPUサポートなどCIリソースの追加管理が不要。

デメリット

  • 仕様差分による見逃し: ネイティブイベントやレイアウト、ブラウザ固有APIを完全には再現できず、「ブラウザでは壊れるがJSDOMでは通る」ケースが残る。[Why I Won’t Use JSDOM]
  • 誤検知・メンテ負債: 依存ライブラリがブラウザ向けエクスポート条件を持つ場合にパッチが必要になり、時間とともにメンテコストが積み上がる。ブラウザ実行へ移行したSingleStoreの事例でも、JSDOM特有の不一致が大きなモチベーションとして語られている。[Our Journey From JSDOM and React Testing Library Toward Cypress Component Testing - SingleStore]
  • エコシステムの方針ズレ: Testing Libraryコミュニティでも「実ブラウザを前提にしたレンダリングをサポートしてほしい」という要望が継続しており、将来的にJSDOM依存が非推奨となる可能性を抱えている。[Render in browser instead of JSDom]

調査はAIを伴奏させて調べて時短したので、引用元をちゃんと見に行って参考にしてください。
自分が知りたくなって調べた記事です。

GitHubで編集を提案
GLOBIS Tech

Discussion