필사 모드: フロントエンドテスト 2026 — Playwright / Cypress / Vitest / Jest / Storybook 9 / Chromatic 徹底比較
日本語プロローグ — 「Selenium一つで全てを賄った時代は終わった」
2018年頃に「フロントエンドのテストは何を使う?」と聞けば、答えはシンプルだった。ユニットはJest、E2EはSeleniumかCypress、ビジュアルリグレッションは気合のある人だけBackstopJS。それだけだった。「コンポーネント単位のテスト」という言葉はまだぎこちなく、「Storybookがテストインフラ」という発想はなかった。
2026年5月現在、その絵は粉々になった。ある会社のフロントエンドテストパイプラインを描けば、だいたいこんな形だ。
- **ユニットテスト** — Vitest 3またはJest 30、Testing Libraryと一緒に。
- **コンポーネントテスト** — Storybook 9 + Vitest、もしくはPlaywright Component Testing。
- **E2Eテスト** — Playwright 1.50+(半分以上)、Cypress 14、WebdriverIO 9。
- **ビジュアルリグレッション** — Chromatic、Percy、Applitools(SaaS)あるいはLoki、BackstopJS、Reg-Suit(OSS)。
- **ネットワークモッキング** — MSW(Mock Service Worker)2.x。
- **AI補助** — Playwright MCP、Browser MCP、Claude / Cursorエージェントが直接テスト作成。
- **CI統合** — GitHub Actions + Playwright trace + Chromatic publish。
この記事は2026年時点で上記ツールがそれぞれどこに立ち、何が得意で何が苦手か、そして「自分のチームは何を選ぶべきか」を整理する。単なるリストではなく — Playwrightの標準化、Vitestの台頭、Storybook 9の軽量化、AIエージェントがブラウザを直接運転する新しいパラダイムまで — 2024〜2026年の間にこの市場を揺らした4つの流れを一緒に見る。
1章・2026年のフロントエンドテスト地図 — Unit / Component / E2E / Visualの4軸
まずは大局。フロントエンドテストは4つの軸に分かれる。
| 軸 | 何を検証するか | 代表ツール |
| --- | --- | --- |
| Unit | 関数、フック、ユーティリティ — 最速のフィードバック | Vitest 3、Jest 30、Mocha |
| Component | コンポーネント単位のレンダリング・相互作用 | Testing Library、Storybook 9 + Vitest、Playwright CT |
| E2E(End-to-End) | ユーザーフロー、複数ページ | Playwright、Cypress 14、WebdriverIO 9、Selenium 5 |
| Visual Regression | ピクセル単位のUI変化検出 | Chromatic、Percy、Applitools、Loki、BackstopJS、Reg-Suit |
ここに2024〜2026年で新たに加わったカテゴリが二つある。
- **Network mocking** — API呼び出しを傍受する層。MSWが事実上の標準。
- **AI agent testing** — LLMが直接ブラウザを運転。Playwright MCP、Browser MCP。
そして2026年のトレンドは明白だ。**「一つのツールで複数の軸を束ねる」**。PlaywrightはE2E + Component + Visualを一括で提供し、Vitestは(Storybookと共に)Unit + Componentを束ねた。Cypressも同様の統合を試みるが速度で押し負ける。点ツールから始めてプラットフォーム化するか、最初からプラットフォームとして来るかの二択。
テスティングピラミッド(ユニットが多く、E2Eが少ない)は今も有効だが — 2026年にはその形が変形した。Mike Cohnのクラシックなピラミッドはコンポーネント層が抜けて「ダイヤモンド」または「トロフィー」型になった。コンポーネントテストが爆発的に増え、ユニットテストはドメインロジック中心に軽くなり、コンポーネントテストが真ん中を埋める。
2章・Playwright — 事実上の標準(VS Code統合、Trace Viewer)
PlaywrightはMicrosoftが作ったE2Eテストツールで、2020年の1.0リリース以降急速に市場を制した。2026年5月時点で1.50+。State of JS 2024調査では使用意向の最も高いE2Eツールに選ばれた。
コア概念
- **Browser context** — 各テストごとに独立したブラウザコンテキスト。Cookie・ストレージは隔離。
- **Auto-waiting** — `click`、`fill`などのアクションが自動的に要素を待つ。明示的なsleepは不要。
- **Locator** — DOM検索が都度再評価されるlazyオブジェクト。stale element問題なし。
- **Trace Viewer** — 失敗したテストのスナップショット・ネットワーク・コンソールをGUIで再生。
- **Component Testing** — React / Vue / Svelteコンポーネントを隔離環境でマウント。
強み
- **速度** — Cypressより2〜3倍速い場合が多い。Chromium・Firefox・WebKitすべてサポート。
- **VS Code拡張** — GUIでテスト作成・実行・デバッグ。Codegenで自動生成。
- **Trace Viewer** — 失敗解析が30秒で済む。他のツールには真似できない。
- **並列実行** — デフォルトでワーカー分散。CIで60%の時間削減はよくある。
- **複数ページ・ドメイン** — 一つのテストで複数オリジンを自由に行き来できる。
弱み
- **学習コスト** — Cypressより抽象化が深い。最初の数日は戸惑う。
- **コンポーネントテストはベータからGAへ** — 1.40系でGAになったが、Vitest + Testing Libraryほど軽量ではない。
- **画像比較はSaaSが強い** — `toHaveScreenshot`はあるが、Chromatic・Percyのベースライン管理には及ばない。
いつ選ぶか
- 新規プロジェクト開始 — ほぼ無条件でPlaywright。
- 複数ブラウザ検証が必要(特にSafari / WebKit)。
- 大きなmonorepoで並列E2Eが必要。
- Traceベースのデバッグが重要なチーム。
// playwright.config.ts
export default defineConfig({
testDir: './e2e',
fullyParallel: true,
retries: process.env.CI ? 2 : 0,
reporter: [['html'], ['github']],
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
{ name: 'mobile-chrome', use: { ...devices['Pixel 7'] } },
],
})
// e2e/checkout.spec.ts
test('user can complete checkout', async ({ page }) => {
await page.goto('/products/coffee-beans')
await page.getByRole('button', { name: 'Add to cart' }).click()
await page.getByRole('link', { name: 'Cart' }).click()
await expect(page.getByText('Coffee Beans')).toBeVisible()
await page.getByRole('button', { name: 'Checkout' }).click()
await page.getByLabel('Email').fill('test@example.com')
await page.getByRole('button', { name: 'Place order' }).click()
await expect(page).toHaveURL(/thank-you/)
})
Playwrightの本当の価値はTrace Viewerだ。CIで失敗したテストのtrace.zipを取得してローカルで開けば、各アクションのDOMスナップショット・ネットワーク呼び出し・コンソールログがGUIタイムラインで再生される。「なぜ失敗した?」がキャプチャで終わる。Cypressのビデオ録画の一段上だ。
3章・Cypress 14 — 依然強力
Cypressは2017年頃に登場し、しばらくの間E2Eの標準だった。2026年5月時点で14。シェアはPlaywrightに押されたが、依然大きなユーザーベースを持つ。
コア概念
- **In-browser test runner** — テストが実ブラウザ内で実行される。DOMに直接アクセス。
- **Time-travel debugger** — 各コマンドのスナップショットを左パネルで時系列に追える。
- **Real-time reload** — コードを保存すれば即座にテストが再実行。
- **Cypress Cloud** — クラウドダッシュボード、並列実行分散、flaky検出。
- **Component Testing** — React / Vue / Angularコンポーネントを隔離環境で。
強み
- **DXが圧倒的** — 始めるのが楽。`cy.visit` `cy.get` `cy.click`が直感的。
- **Time-travel debugging** — 各コマンドのDOMスナップショットが自動キャプチャ。デバッグが楽しい。
- **リアルタイムhot reload** — TDDサイクルが速い。
- **豊富なドキュメント・コミュニティ** — Stack Overflowに答えがほぼ全部ある。
弱み
- **単一ドメイン制約** — `cy.origin`が追加されたが、依然複数ドメインは扱いにくい。
- **Safari / WebKitサポートが弱い** — 実験段階、安定性不足。
- **速度** — Playwrightより30〜50%遅い。
- **iframeの扱いが厄介** — 広告や外部ウィジェットを含むページが痛い。
- **Cypress Cloud価格** — 並列実行と結果保存が無料tierですぐ制限。
いつ選ぶか
- 既存のCypressコードベースが大きい場合 — 移行コストが大きい。
- 単一ドメインSPA、小規模チーム。
- デバッグ体験を最優先する場合。
// cypress/e2e/login.cy.js
describe('Login flow', () => {
beforeEach(() => {
cy.intercept('POST', '/api/login', { fixture: 'login-success.json' }).as('login')
cy.visit('/login')
})
it('logs in with valid credentials', () => {
cy.get('[data-cy=email]').type('user@example.com')
cy.get('[data-cy=password]').type('s3cret!')
cy.get('[data-cy=submit]').click()
cy.wait('@login')
cy.url().should('include', '/dashboard')
cy.contains('Welcome back').should('be.visible')
})
})
Cypress 14で追加された最大の機能は**WebKit GA**と**Component Testing UX改善**だ。だがPlaywrightが既に一歩先を行っており、新規プロジェクトがCypressを選ぶ割合は2024年から急速に下がっている。
4章・Vitest 3 — Viteと共に来る最速
Vitestは2021年Anthony Fuが作ったユニットテストランナーで、Viteのトランスフォーマー・HMRをそのまま活用する。2026年時点で3.x、JS / TS新規プロジェクトのユニットテスト標準となった。
コア概念
- **Vite-native** — Vite configをそのまま再利用。esbuild + Rollupがトランスパイル。
- **HMR for tests** — 変更されたモジュールのみ再評価、ミリ秒単位のサイクル。
- **Jest互換API** — `describe` / `it` / `expect`がJestとほぼ同じ。
- **Workspaces** — monorepoで複数パッケージを一つのvitestコマンドで。
- **Browser mode** — 実ブラウザでコンポーネントテスト(Playwright / WebdriverIOバックエンド)。
強み
- **速度が圧倒的** — Jest比2〜10倍速い。コールドスタートも速い。
- **Viteエコシステムと一体** — Viteプロジェクトなら別途設定なしで即動作。
- **TypeScript first-class** — esbuildがトランスパイルするのでts-jestのような迂回が不要。
- **Worker pool最適化** — Node worker_threadsで隔離 + 高速実行。
- **Storybook 9と統合** — `@storybook/addon-vitest`でストーリーがそのままテスト。
弱み
- **CRA / Next.jsレガシー** — Webpackベースのプロジェクトは移行コスト。
- **JSDOM / happy-dom互換性** — 一部のDOM APIで小さな差。
- **Jestの巨大なプラグインエコシステム** — `jest-extended`など一部ミラーリングが不十分。
いつ選ぶか
- Viteを使う全てのプロジェクト。
- 新規プロジェクト開始 — ほぼ無条件でVitest。
- ユニットテスト速度が重要な場合(CI分単位の削減)。
// vitest.config.ts
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'happy-dom',
setupFiles: ['./test/setup.ts'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: ['node_modules/', 'test/'],
},
},
})
// src/utils/format.test.ts
describe('formatCurrency', () => {
it('formats JPY without decimals', () => {
expect(formatCurrency(12345, 'JPY')).toBe('¥12,345')
})
it('formats USD with two decimals', () => {
expect(formatCurrency(12.5, 'USD')).toBe('$12.50')
})
it('handles negative numbers', () => {
expect(formatCurrency(-100, 'USD')).toBe('-$100.00')
})
})
Vitest 3の最大の変化は**Browser mode GA**だ。JSDOMではなく実Chromiumでコンポーネントをマウントしてテストする。Playwright Component Testingと似た領域だが、Viteベースのプロジェクトではより自然。
5章・Jest 30 — レガシー + Next互換
JestはFacebookが2014年に作ったユニットテストランナーで、しばらくの間JSテストの事実上の標準だった。2025年9月に30がリリースされ、2026年5月には30.xマイナーリリースが安定段階にある。
コア概念
- **Snapshot testing** — `expect(tree).toMatchSnapshot()` — UIツリーをシリアライズして保存。
- **Module mocking** — `jest.mock()`でimportパスを偽物に置換。
- **Fake timers** — `jest.useFakeTimers()`でsetTimeout / setIntervalを制御。
- **Coverage** — Istanbulベースのカバレッジが内蔵。
強み
- **巨大なエコシステム** — `jest-extended`、`jest-fetch-mock`など数万のプラグイン。
- **CRA / Next.jsデフォルト統合** — Next.jsの`next/jest`が標準設定を提供。
- **安定性** — 10年の検証。大コードベースで信頼性が高い。
- **VS Code統合** — Jest Runner拡張がうまく動く。
弱み
- **速度** — Vitest比2〜5倍遅い。大コードベースでCI時間が負担。
- **ESMサポートがぎこちない** — 一部のESMパッケージでhackが必要。
- **TypeScriptはts-jestまたはbabel** — Vitestのesbuild比で遅い。
いつ選ぶか
- 既存のJestコードベースが大きい場合。
- Next.js 12未満またはWebpackベースのCRA。
- Jest専用プラグインに依存する場合。
// jest.config.js
const nextJest = require('next/jest')
const createJestConfig = nextJest({ dir: './' })
const customConfig = {
setupFilesAfterEach: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jsdom',
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!src/**/*.stories.tsx',
],
}
module.exports = createJestConfig(customConfig)
Jest 30の最大の変化は**初のnative ESMサポート安定化**と**メモリ使用量30%削減**。移行コストのため依然大組織ではJestを使うが、新規プロジェクトでJestを選ぶことは少なくなっている。
6章・Testing Libraryの哲学 — Implementation detailを避ける
Testing Libraryは2018年にKent C. Doddsが作ったライブラリ群だ。DOM、React、Vue、Svelte、Solidそれぞれのアダプターがある。2026年時点で全てのコンポーネントテストの基礎。
中核哲学
- **「The more your tests resemble the way your software is used, the more confidence they can give you.」**
- コンポーネントの内部stateを見ず、ユーザーが見てクリックするものを見る。
- `getByRole`、`getByLabelText`、`getByText` — アクセシビリティ基準のクエリ。
- `getByTestId`は最終手段。
強み
- **リファクタリングに優しい** — コンポーネント内部構造が変わってもテストはそのまま。
- **アクセシビリティと共に進む** — クエリがARIA roleベースなので自然にa11yを検証。
- **フレームワーク独立** — React / Vue / Svelteどこでも同じ哲学。
- **TanStack / Mantine / Radixのようなライブラリも Testing Library基準で構築**。
弱み
- **純粋ユニットテストより遅い** — DOMレンダリングが必要。
- **userEvent対fireEvent** — 二つのAPIの差が初心者に混乱を与える。
- **非同期処理** — `findBy*`、`waitFor`の使い方を混同する人が多い。
例 — React Testing Library + Vitest
describe('LoginForm', () => {
it('shows error when password is too short', async () => {
const user = userEvent.setup()
render(<LoginForm onSubmit={() => {}} />)
await user.type(screen.getByLabelText(/email/i), 'user@example.com')
await user.type(screen.getByLabelText(/password/i), 'abc')
await user.click(screen.getByRole('button', { name: /sign in/i }))
expect(
await screen.findByText(/password must be at least 8 characters/i)
).toBeInTheDocument()
})
it('calls onSubmit with valid input', async () => {
const onSubmit = vi.fn()
const user = userEvent.setup()
render(<LoginForm onSubmit={onSubmit} />)
await user.type(screen.getByLabelText(/email/i), 'user@example.com')
await user.type(screen.getByLabelText(/password/i), 'longerpassword')
await user.click(screen.getByRole('button', { name: /sign in/i }))
expect(onSubmit).toHaveBeenCalledWith({
email: 'user@example.com',
password: 'longerpassword',
})
})
})
よく陥る罠 — `screen.getByText("Loading...")`のようなテキスト完全一致はi18nで壊れる。`getByRole("status")`または正規表現が安全。そして`data-testid="submit-button"`は本当に最終手段としてのみ。ユーザーはtestidを見ない。
7章・Storybook 9(2025年6月) — 軽量化しVitestと統合
Storybookは2016年に登場したコンポーネントワークショップだ。2025年6月にリリースされた9バージョンは大きな転換点だった。軽くなり(バンドルサイズ約50%減)、Vitestと深く統合された。
主要変化(Storybook 9)
- **軽量化** — 9.0発表で「最大75%少ない依存、48%軽いインストール」という数値。
- **Vitestベースのテスト** — `@storybook/addon-vitest`でストーリーがそのままテストに。
- **Component testing** — Play functionが事実上の相互作用テスト標準。
- **Visual testing内蔵** — Chromatic連携がよりスムーズに。
- **A11y検証内蔵** — `@storybook/addon-a11y`がデフォルトオプション化。
強み
- **単一作成、多用途活用** — 一つのストーリーがカタログ・相互作用テスト・ビジュアルリグレッション・a11y検証すべてをカバー。
- **デザイナーとの協業** — Figma統合。デザイントークンをリアルタイム確認。
- **Vitest統合** — ストーリー実行がそのままユニットテスト実行と同じインフラ。
- **Plugins / Addonsエコシステム** — `addon-controls`、`addon-actions`、`addon-docs`。
弱み
- **ビルド時間** — 大きなデザインシステムでStorybookビルドが分単位。
- **CSF(Component Story Format)3** — 学習が必要。最初に書くチームは戸惑う。
- **バンドラー分岐** — ViteベースかWebpackベースかで設定が分かれる。
例 — CSF 3 + Play function
// Button.stories.tsx
const meta: Meta<typeof Button> = {
title: 'UI/Button',
component: Button,
tags: ['autodocs'],
}
export default meta
type Story = StoryObj<typeof Button>
export const Primary: Story = {
args: {
variant: 'primary',
children: 'Click me',
},
}
export const Clicked: Story = {
args: { variant: 'primary', children: 'Click me' },
play: async ({ canvasElement }) => {
const canvas = within(canvasElement)
const btn = canvas.getByRole('button', { name: /click me/i })
await userEvent.click(btn)
await expect(btn).toHaveAttribute('aria-pressed', 'true')
},
}
// vitest.workspace.ts — Storybook 9 + Vitest統合
export default defineWorkspace([
'./vitest.config.ts',
{
extends: './vitest.config.ts',
plugins: [storybookTest({ configDir: '.storybook' })],
test: {
name: 'storybook',
browser: {
enabled: true,
headless: true,
name: 'chromium',
provider: 'playwright',
},
},
},
])
Storybook 9の真の価値は「ストーリーを一度書けばカタログ・テスト・ビジュアルリグレッション・アクセシビリティが全部ついてくる」点だ。デザインシステムチームなら事実上必須。
8章・Chromatic / Percy / Applitools — ビジュアルリグレッション
ビジュアルリグレッション(Visual Regression)はUI変更が意図したものか否かをピクセル単位で検査する。SaaSの三強はChromatic、Percy(BrowserStack)、Applitoolsだ。
Chromatic
- Storybookを作った会社が直接運営。Storybookと一体。
- ストーリー単位のビジュアルリグレッションが強み。
- Cross-browserのベースラインをクラウドに保存。
- レビューワークフロー(diff → approve → merge)が綺麗。
- 価格はsnapshot基準 — 小規模チームは無料tierで十分。
Percy(BrowserStack)
- 2017年BrowserStackが買収。Percy CLIでPlaywright / Cypress / WebdriverIO統合。
- 複数viewport、複数ブラウザのベースライン。
- BrowserStackの実デバイスクラウドと連携。
Applitools
- AIベースのビジュアル比較が強み — 「意味のある変化のみ」を検出。
- Visual AIアルゴリズムがdynamic content(タイムスタンプ、広告)を自動無視。
- Ultrafast Grid — 一度キャプチャして複数ブラウザ・デバイス組合せで検証。
- エンタープライズ価格。大組織で圧倒的。
三者の違い
| 項目 | Chromatic | Percy | Applitools |
| --- | --- | --- | --- |
| 母体 | Storybook | BrowserStack | 独立SaaS |
| 強み | Storybook統合 | 複数viewport、BSデバイス | AI Visual diff |
| 価格モデル | snapshot基準 | snapshot + DOM基準 | enterprise seat |
| Free tier | 寛大(月5,000 snapshot) | 小さい | 評価版のみ |
| AI処理 | 部分的 | 部分的 | 中核機能 |
// Playwright + Percy
test('homepage looks correct', async ({ page }) => {
await page.goto('/')
await percySnapshot(page, 'Homepage')
})
// Playwright + Applitools Eyes
test('checkout flow visual', async ({ page }) => {
const eyes = new Eyes()
const cfg = new Configuration()
cfg.setBatch(new BatchInfo('Smoke 2026-05-16'))
eyes.setConfiguration(cfg)
await eyes.open(page, 'Shop', 'Checkout')
await page.goto('/checkout')
await eyes.check('Checkout page', undefined)
await eyes.close()
})
ビジュアルリグレッションの最大の罠は**flaky snapshot**だ。フォントロード、アニメーション、カルーセル、広告 — このような動的要素をマスキングしなければ95%のdiffがfalse positive。Applitoolsが強い理由はこれを自動で処理するから。
9章・Loki / BackstopJS / Reg-Suit — オープンソースのビジュアルリグレッション
SaaSが負担になる、あるいはベースラインを自分のリポジトリに置きたいならOSSの選択肢がある。
Loki
- Storybook専用。`loki test`で全ストーリーをキャプチャ・比較。
- Chromium / Firefox / WebKitサポート。Dockerベースで一貫したレンダリング。
- ベースラインはgitに一緒にコミット — レビューはPRで。
BackstopJS
- 最も古い(2014年)オープンソースのビジュアルリグレッションツール。
- Puppeteerベース。URLリストとセレクターで定義。
- HTMLレポートが綺麗。小規模チームで依然人気。
Reg-Suit
- 日本発のOSS。メルカリなどが採用。
- S3またはGCSにスナップショット保存。PR diffをGitHubコメントで。
- Playwright / Cypress / Storybookどこからでもキャプチャを投げられる。
三者の違い
| 項目 | Loki | BackstopJS | Reg-Suit |
| --- | --- | --- | --- |
| 母体 | Storybookエコシステム | 独立 | 日本OSS |
| ベースライン保存 | git | ローカル | S3 / GCS |
| キャプチャエンジン | Chromium | Puppeteer | 外部(Playwrightなど) |
| PR統合 | 直接 | 弱い | 強い(GitHub bot) |
// backstop.json — BackstopJSの基本設定
{
"id": "my-project",
"viewports": [
{ "label": "mobile", "width": 375, "height": 667 },
{ "label": "desktop", "width": 1920, "height": 1080 }
],
"scenarios": [
{
"label": "Homepage",
"url": "http://localhost:3000/",
"delay": 500,
"misMatchThreshold": 0.1
}
],
"engine": "puppeteer",
"report": ["browser"]
}
OSSの強みはベースラインを自インフラに置くこと。セキュリティが厳格な金融・ヘルスケアではSaaSを使えない場合が多く、Reg-Suitまたはセルフホストが好まれる。
10章・Browser MCP + Playwright MCP — AIエージェントがブラウザを運転
2024年後半から大きな変化があった。MCP(Model Context Protocol)が標準化され、AIエージェントが直接ブラウザを運転するパターンが一般化した。2026年5月時点でPlaywright MCPとBrowser MCPの二陣営がある。
Playwright MCP(Microsoft)
- Microsoftが直接作った公式MCPサーバー。PlaywrightのすべてのAPIをMCPツールとして公開。
- Claude・Cursor・VS Code Copilotがこれを通してブラウザアクションを呼び出す。
- Accessibility treeベース — スクリーンショットではなく意味的構造でページを見る。
- Traceキャプチャと共に作動。エージェントが作ったテストもTrace Viewerで再生。
Browser MCP
- オープンソース陣営のMCPサーバー。多様なバックエンド(Playwright、Puppeteer、Selenium)。
- Local Chrome拡張を通して現在のユーザーのセッションで作動。
- ログイン状態で作業すべきシナリオに強い。
使用パターン
// .cursor/mcp.json — Playwright MCPを登録
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest"]
}
}
}
この設定後にAIエージェントに「チェックアウトフローのテストを書いて実行して」と頼めば、エージェントが直接ブラウザを開いてクリック・入力しながら`*.spec.ts`を生成する。Codegenの次世代。
限界
- **flaky** — エージェントが非決定的でテスト自体が安定しない可能性。
- **コスト** — LLMトークンコストが実行ごとに。
- **セキュリティ** — 本番資格情報をエージェントに渡すのは危険。
そこで2026年のパターンは**「エージェントが草案を作成 → 人がレビュー + 安定化 → CIに登録」**だ。エージェントが毎CIで回るのはまだ先。
11章・MSW(Mock Service Worker) + ネットワークモッキング戦略
MSWは2019年Artem Zakharchenkoが作ったネットワークモッキングライブラリだ。2026年時点で2.x、フロントエンドテストの事実上の標準ネットワークモッキングツールとなった。
コア概念
- **Service Workerベース** — ブラウザのネットワーク層で傍受。`fetch`、`axios`、`XHR`問わず。
- **Node環境でも作動** — `setupServer`でVitest / Jestで使用。
- **REST + GraphQL** — 両プロトコル対応。
- **タイプセーフ** — TypeScriptとよく馴染む。
強み
- **アプリコード無修正** — `axios`を`jest.mock()`するのではなく、実ネットワーク呼び出しを傍受。
- **開発・テスト・Storybook共通** — 同じハンドラを三環境で再利用。
- **GraphQLサポート** — Apollo Client / urql統合がスムーズ。
- **Devtools統合** — ブラウザdevtoolsのNetworkタブにそのまま見える。
例 — MSWハンドラ
// mocks/handlers.ts
export const handlers = [
http.get('/api/products', () => {
return HttpResponse.json([
{ id: 1, name: 'Coffee Beans', price: 25000 },
{ id: 2, name: 'Tea Set', price: 35000 },
])
}),
http.post('/api/cart', async ({ request }) => {
const body = await request.json()
return HttpResponse.json({ ok: true, cartId: 'abc-123' }, { status: 201 })
}),
http.get('/api/user/me', () => {
return new HttpResponse(null, { status: 401 })
}),
]
// test/setup.ts — Vitestで
const server = setupServer(...handlers)
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
// browser entrypoint(開発環境)
if (process.env.NODE_ENV === 'development') {
const worker = setupWorker(...handlers)
worker.start()
}
MSWの真の価値は**「テスト・開発・Storybookで同じモッキングコードを使う」**点だ。バックエンドがまだないときもフロントエンドが進行可能、テストと実開発が同じfixtureを共有。
代替としてPlaywrightの`page.route()`、Cypressの`cy.intercept()`もあるが — 各ツール専用で再利用性が低い。そこでMSWを下層に置き、E2Eではその上にPlaywright routeを乗せるハイブリッドがよくある。
12章・Page Object / Component Testingパターン
E2Eテストが増えるとコード重複が問題となる。そこで2026年の標準パターンは二つ。
Page Object Model(POM)
- 1ページ = 1クラス。セレクターとアクションをクラスにカプセル化。
- Selenium時代から受け継がれたパターン。2026年もPlaywright・Cypressで有効。
// e2e/pages/CheckoutPage.ts
export class CheckoutPage {
readonly page: Page
readonly emailInput: Locator
readonly submitButton: Locator
constructor(page: Page) {
this.page = page
this.emailInput = page.getByLabel('Email')
this.submitButton = page.getByRole('button', { name: 'Place order' })
}
async goto() {
await this.page.goto('/checkout')
}
async fillEmail(email: string) {
await this.emailInput.fill(email)
}
async submit() {
await this.submitButton.click()
}
async expectSuccess() {
await expect(this.page).toHaveURL(/thank-you/)
}
}
// e2e/checkout.spec.ts
test('user completes checkout', async ({ page }) => {
const checkout = new CheckoutPage(page)
await checkout.goto()
await checkout.fillEmail('user@example.com')
await checkout.submit()
await checkout.expectSuccess()
})
Component Testing
- コンポーネントを隔離環境でマウントして検証。
- Playwright CT、Cypress CT、Vitest browser mode、Storybook play function。
- 「ユニットテスト並みに速くE2E並みに本物っぽい」位置。
どのパターンをいつ
- **ユニット / 純関数** — Vitest、JSDOM。
- **コンポーネント単独** — Storybook + VitestまたはPlaywright CT。
- **2〜3コンポーネント組合せ** — Testing Library + Vitest。
- **ページ全体** — Page Object + Playwright / Cypress。
- **ユーザージャーニー** — Page Object + Playwright、データ隔離。
POMの罠 — 抽象化しすぎるとテストが何をしているか見えない。「Login → Cart → Checkout」が一行で終われば読みやすいが失敗解析が難しい。適度な抽象化 + Playwright Trace Viewerの組合せが最適。
13章・韓国 / 日本の事例 — トス、カカオ、メルカリ
韓国 — トスのUIテスト
トスは100名以上のフロントエンドチームを持つ大組織で、自前のデザインシステム(Toss DS)を運営する。公開ブログ・発表資料に表れるパターンは以下の通り。
- **Storybook + Chromatic** — デザインシステムの全コンポーネントがStorybookに登録。
- **Playwright** — E2Eの標準。マルチブラウザ検証。
- **Vitest + React Testing Library** — コンポーネント単位テスト。
- **自前MSWハンドラライブラリ** — トスAPIパターンに合わせた共通fixture。
- **CIでビジュアルリグレッションが遮断** — Chromatic承認なしではマージ不可。
トスブログの「フロントエンドにテストは本当に必要か?」のような記事に見える哲学は — 「テストはデザインシステムと一体」。コンポーネント単位が強ければページ単位は少なく。
韓国 — カカオのフロントエンド
カカオ陣営(カカオ、カカオバンク、カカオエンタープライズ)も類似スタックだ。
- **JestまたはVitest** — レガシーはJest、新規はVitest。
- **Cypressが多く残っている** — 2020〜2023年に採用したコードベースが多い。
- **Playwrightに移行中** — 新規プロジェクトと大規模移行。
- **カカオバンクはより厳格** — 金融規制で自前インフラ検証、OSSビジュアルリグレッション(Reg-Suitまたは自前)。
日本 — メルカリのコンポーネントテスティング
メルカリはStorybook + Vitest + Reg-Suitの組合せを公開的に発表したことがある。パターンは以下の通り。
- **Storybook** — デザインシステムと全コンポーネント。
- **Reg-Suit** — ビジュアルリグレッション、S3にベースライン、GitHub PRに自動コメント。
- **VitestまたはJest** — ユニット。
- **Playwright** — E2E。
- **MSW** — ネットワークモッキング。
メルカリ Engineering Blogのビジュアルリグレッション記事がReg-Suitの実使用事例としてよく引用される。日本でReg-Suitが強い理由の一つがメルカリの採用。
結論 — 地域別推奨
| シナリオ | 韓国推奨 | 日本推奨 |
| --- | --- | --- |
| スタートアップ(10〜50人) | Vitest + Playwright + Chromatic | Vitest + Playwright + Reg-Suit |
| 中堅(50〜500人) | Storybook 9 + Chromatic + Playwright | Storybook 9 + Reg-Suit + Playwright |
| 大企業(500+) | 自前デザインシステム + Chromatic + Playwright | 自前 + Reg-Suit + Playwright |
| 金融 | 自前ホストReg-Suit + Playwright | 自前ホスト + Selenium 5残存 |
| グローバルSaaS | Applitools + Playwright | Applitools + Playwright |
14章・どのスタックを選ぶべきか — シナリオ別ガイド
シナリオA — 大規模SaaS(数十ページ、多言語、複数ブラウザ)
- **Unit**: Vitest 3 + React Testing Library
- **Component**: Storybook 9 + Vitest browser mode
- **E2E**: Playwright 1.50+(Chromium、Firefox、WebKit、Mobile Safari)
- **Visual**: ChromaticまたはApplitools
- **Network**: MSW 2.x
- **CI**: GitHub Actions + Playwright trace + Chromatic publish + 失敗時Slack
- **AI**: Playwright MCPで新規テスト草案生成
シナリオB — デザインシステム / コンポーネントライブラリ
- **Unit**: Vitest 3
- **Component**: Storybook 9(CSF 3 + play function)
- **Visual**: Chromatic(Storybookと一体)
- **A11y**: `@storybook/addon-a11y` + axe-core
- **Docs**: Storybook autodocs
- **E2Eは最小化** — ライブラリはコンポーネント単位が核心
シナリオC — E-commerce(カート、決済、複数ページ)
- **Unit**: Vitest 3
- **Component**: Storybook 9またはTesting Library
- **E2E**: Playwright(Page Objectパターン)
- **Visual**: PercyまたはChromatic(モバイルviewport核心)
- **Network**: MSW + Playwright routeハイブリッド
- **決済フローは隔離されたテストアカウント + Stripe test mode**
シナリオD — メディア / コンテンツサイト
- **Unit**: Vitest 3(SEOメタ検証中心)
- **E2E**: Playwright(Lighthouse CIと共に)
- **Visual**: ChromaticまたはBackstopJS
- **Network**: MSWでCMS応答モッキング
- **パフォーマンス回帰が重要** — Playwright + Lighthouse統合
シナリオE — レガシー移行(Jest + Cypress → Vitest + Playwright)
- 一度に全部移行せず、新コードは新ツールで。
- JestとVitest共存 — `vitest run --project new`で漸進的に。
- Cypress E2Eはそのまま残し、新規E2EだけPlaywright。
- 12〜18ヶ月の移行が現実的。
コスト見積もり(2026年5月基準、50人フロントエンドチーム)
| ツール | 無料tier | 有料(月額) |
| --- | --- | --- |
| Playwright | 無料 | — |
| Vitest | 無料 | — |
| Storybook | 無料 | — |
| Chromatic | 月5,000 snapshot無料 | 約$149〜$649 |
| Percy | 月5,000 snapshot無料 | 約$199+ |
| Applitools | 評価版 | enterprise quote |
| Cypress Cloud | 月500結果無料 | 約$75〜$300+ |
| MSW | 無料 | — |
| Loki / BackstopJS / Reg-Suit | 無料 | — |
小規模チームの出発点は単純だ — Vitest + Playwright + Chromatic無料tier。ここから始めてチームが大きくなればStorybook 9をデザインシステム中心に、ビジュアルリグレッションを有料tierに、そしてPlaywright MCPを導入して新規テスト作成速度を上げるのが標準ルート。
おわりに — 「ツールを買うのではなく、信頼を買うのだ」
2026年のフロントエンドテスティング市場は単一ツールのトーナメントではなく4軸の合奏だ。そして次の5つの流れが市場を揺らしている。
1. **Playwrightの標準化** — 新規E2Eの70%+シェア。時間が経つほど格差拡大。
2. **Vitestの台頭** — Viteエコシステムと共に事実上の標準ユニットランナー。
3. **Storybook 9の軽量化** — デザインシステム + コンポーネントテスト + ビジュアルリグレッションのハブ。
4. **AIエージェントが直接テスト作成** — Playwright MCP、Browser MCPが日常化。
5. **MSWの標準化** — ネットワークモッキング = MSW。ツール独立なfixture。
小規模チームの初行 — `npm i -D vitest @testing-library/react @playwright/test msw`。この4つで95%のケースがカバーされる。次のステップがStorybook 9 + Chromatic、その次がPlaywright MCP統合。
一つの真理 — **「ツールを買うのではなく、信頼(テストが壊れた時に本当にバグを捕まえるという信頼)を買うのだ」**。どのツールを選んでもその信頼が90%未満なら、そのテストはPRを遮断するノイズに過ぎない。ツール評価の最初の質問は常に「このテストが赤線を出した時、実際にバグを捕まえた比率は?」だ。
参考 / References
- Playwright — [https://playwright.dev/](https://playwright.dev/)
- Playwright VS Code Extension — [https://playwright.dev/docs/getting-started-vscode](https://playwright.dev/docs/getting-started-vscode)
- Playwright Trace Viewer — [https://playwright.dev/docs/trace-viewer](https://playwright.dev/docs/trace-viewer)
- Playwright Component Testing — [https://playwright.dev/docs/test-components](https://playwright.dev/docs/test-components)
- Playwright MCP — [https://github.com/microsoft/playwright-mcp](https://github.com/microsoft/playwright-mcp)
- Cypress — [https://www.cypress.io/](https://www.cypress.io/)
- Cypress 14 release notes — [https://docs.cypress.io/guides/references/changelog](https://docs.cypress.io/guides/references/changelog)
- Cypress Cloud — [https://www.cypress.io/cloud](https://www.cypress.io/cloud)
- Vitest — [https://vitest.dev/](https://vitest.dev/)
- Vitest Browser Mode — [https://vitest.dev/guide/browser/](https://vitest.dev/guide/browser/)
- Jest — [https://jestjs.io/](https://jestjs.io/)
- Jest 30 announcement — [https://jestjs.io/blog/2025/06/04/jest-30](https://jestjs.io/blog/2025/06/04/jest-30)
- Testing Library — [https://testing-library.com/](https://testing-library.com/)
- React Testing Library — [https://testing-library.com/docs/react-testing-library/intro/](https://testing-library.com/docs/react-testing-library/intro/)
- Storybook — [https://storybook.js.org/](https://storybook.js.org/)
- Storybook 9 release — [https://storybook.js.org/blog/storybook-9/](https://storybook.js.org/blog/storybook-9/)
- Storybook Vitest addon — [https://storybook.js.org/docs/writing-tests/test-addon](https://storybook.js.org/docs/writing-tests/test-addon)
- Chromatic — [https://www.chromatic.com/](https://www.chromatic.com/)
- Percy — [https://percy.io/](https://percy.io/)
- Applitools — [https://applitools.com/](https://applitools.com/)
- Applitools Visual AI — [https://applitools.com/platform/visual-ai/](https://applitools.com/platform/visual-ai/)
- Loki (Storybook visual regression) — [https://loki.js.org/](https://loki.js.org/)
- BackstopJS — [https://github.com/garris/BackstopJS](https://github.com/garris/BackstopJS)
- Reg-Suit — [https://github.com/reg-viz/reg-suit](https://github.com/reg-viz/reg-suit)
- Selenium — [https://www.selenium.dev/](https://www.selenium.dev/)
- WebdriverIO — [https://webdriver.io/](https://webdriver.io/)
- MSW (Mock Service Worker) — [https://mswjs.io/](https://mswjs.io/)
- Model Context Protocol — [https://modelcontextprotocol.io/](https://modelcontextprotocol.io/)
- State of JS 2024 — [https://stateofjs.com/](https://stateofjs.com/)
- Kent C. Dodds — Testing Trophy — [https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications](https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications)
- メルカリ Engineering Blog — [https://engineering.mercari.com/blog/](https://engineering.mercari.com/blog/)
- トス技術ブログ — [https://toss.tech/](https://toss.tech/)
- カカオ技術ブログ — [https://tech.kakao.com/](https://tech.kakao.com/)
현재 단락 (1/551)
2018年頃に「フロントエンドのテストは何を使う?」と聞けば、答えはシンプルだった。ユニットはJest、E2EはSeleniumかCypress、ビジュアルリグレッションは気合のある人だけBackst...