- Published on
フロントエンドテスト 2026 — Playwright / Cypress / Vitest / Jest / Storybook 9 / Chromatic 徹底比較
- Authors

- Name
- Youngju Kim
- @fjvbn20031
プロローグ — 「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
import { defineConfig, devices } from '@playwright/test'
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
import { test, expect } from '@playwright/test'
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.visitcy.getcy.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
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
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
import { describe, it, expect } from 'vitest'
import { formatCurrency } from './format'
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
import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { LoginForm } from './LoginForm'
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
import type { Meta, StoryObj } from '@storybook/react'
import { expect, userEvent, within } from '@storybook/test'
import { Button } from './Button'
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統合
import { defineWorkspace } from 'vitest/config'
import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'
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
import { test } from '@playwright/test'
import percySnapshot from '@percy/playwright'
test('homepage looks correct', async ({ page }) => {
await page.goto('/')
await percySnapshot(page, 'Homepage')
})
// Playwright + Applitools Eyes
import { test } from '@playwright/test'
import { Eyes, BatchInfo, Configuration } from '@applitools/eyes-playwright'
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
import { http, HttpResponse } from 'msw'
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で
import { setupServer } from 'msw/node'
import { handlers } from '../mocks/handlers'
import { afterAll, afterEach, beforeAll } from 'vitest'
const server = setupServer(...handlers)
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
// browser entrypoint(開発環境)
import { setupWorker } from 'msw/browser'
import { handlers } from './mocks/handlers'
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
import { Page, Locator, expect } from '@playwright/test'
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
import { test } from '@playwright/test'
import { CheckoutPage } from './pages/CheckoutPage'
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無料 | 約649 |
| Percy | 月5,000 snapshot無料 | 約$199+ |
| Applitools | 評価版 | enterprise quote |
| Cypress Cloud | 月500結果無料 | 約300+ |
| MSW | 無料 | — |
| Loki / BackstopJS / Reg-Suit | 無料 | — |
小規模チームの出発点は単純だ — Vitest + Playwright + Chromatic無料tier。ここから始めてチームが大きくなればStorybook 9をデザインシステム中心に、ビジュアルリグレッションを有料tierに、そしてPlaywright MCPを導入して新規テスト作成速度を上げるのが標準ルート。
おわりに — 「ツールを買うのではなく、信頼を買うのだ」
2026年のフロントエンドテスティング市場は単一ツールのトーナメントではなく4軸の合奏だ。そして次の5つの流れが市場を揺らしている。
- Playwrightの標準化 — 新規E2Eの70%+シェア。時間が経つほど格差拡大。
- Vitestの台頭 — Viteエコシステムと共に事実上の標準ユニットランナー。
- Storybook 9の軽量化 — デザインシステム + コンポーネントテスト + ビジュアルリグレッションのハブ。
- AIエージェントが直接テスト作成 — Playwright MCP、Browser MCPが日常化。
- 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/
- Playwright VS Code Extension — https://playwright.dev/docs/getting-started-vscode
- Playwright Trace Viewer — https://playwright.dev/docs/trace-viewer
- Playwright Component Testing — https://playwright.dev/docs/test-components
- Playwright MCP — https://github.com/microsoft/playwright-mcp
- Cypress — https://www.cypress.io/
- Cypress 14 release notes — https://docs.cypress.io/guides/references/changelog
- Cypress Cloud — https://www.cypress.io/cloud
- Vitest — https://vitest.dev/
- Vitest Browser Mode — https://vitest.dev/guide/browser/
- Jest — https://jestjs.io/
- Jest 30 announcement — https://jestjs.io/blog/2025/06/04/jest-30
- Testing Library — https://testing-library.com/
- React Testing Library — https://testing-library.com/docs/react-testing-library/intro/
- Storybook — https://storybook.js.org/
- Storybook 9 release — https://storybook.js.org/blog/storybook-9/
- Storybook Vitest addon — https://storybook.js.org/docs/writing-tests/test-addon
- Chromatic — https://www.chromatic.com/
- Percy — https://percy.io/
- Applitools — https://applitools.com/
- Applitools Visual AI — https://applitools.com/platform/visual-ai/
- Loki (Storybook visual regression) — https://loki.js.org/
- BackstopJS — https://github.com/garris/BackstopJS
- Reg-Suit — https://github.com/reg-viz/reg-suit
- Selenium — https://www.selenium.dev/
- WebdriverIO — https://webdriver.io/
- MSW (Mock Service Worker) — https://mswjs.io/
- Model Context Protocol — https://modelcontextprotocol.io/
- State of JS 2024 — https://stateofjs.com/
- Kent C. Dodds — Testing Trophy — https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications
- メルカリ Engineering Blog — https://engineering.mercari.com/blog/
- トス技術ブログ — https://toss.tech/
- カカオ技術ブログ — https://tech.kakao.com/