Skip to content
Published on

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

Authors

プロローグ — 「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-waitingclickfillなどのアクションが自動的に要素を待つ。明示的な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.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 GAComponent 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互換APIdescribe / 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 testingexpect(tree).toMatchSnapshot() — UIツリーをシリアライズして保存。
  • Module mockingjest.mock()でimportパスを偽物に置換。
  • Fake timersjest.useFakeTimers()でsetTimeout / setIntervalを制御。
  • Coverage — Istanbulベースのカバレッジが内蔵。

強み

  • 巨大なエコシステムjest-extendedjest-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を見ず、ユーザーが見てクリックするものを見る。
  • getByRolegetByLabelTextgetByText — アクセシビリティ基準のクエリ。
  • 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-controlsaddon-actionsaddon-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 — 一度キャプチャして複数ブラウザ・デバイス組合せで検証。
  • エンタープライズ価格。大組織で圧倒的。

三者の違い

項目ChromaticPercyApplitools
母体StorybookBrowserStack独立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どこからでもキャプチャを投げられる。

三者の違い

項目LokiBackstopJSReg-Suit
母体Storybookエコシステム独立日本OSS
ベースライン保存gitローカルS3 / GCS
キャプチャエンジンChromiumPuppeteer外部(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ベース — ブラウザのネットワーク層で傍受。fetchaxiosXHR問わず。
  • Node環境でも作動setupServerでVitest / Jestで使用。
  • REST + GraphQL — 両プロトコル対応。
  • タイプセーフ — TypeScriptとよく馴染む。

強み

  • アプリコード無修正axiosjest.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 + ChromaticVitest + Playwright + Reg-Suit
中堅(50〜500人)Storybook 9 + Chromatic + PlaywrightStorybook 9 + Reg-Suit + Playwright
大企業(500+)自前デザインシステム + Chromatic + Playwright自前 + Reg-Suit + Playwright
金融自前ホストReg-Suit + Playwright自前ホスト + Selenium 5残存
グローバルSaaSApplitools + PlaywrightApplitools + 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無料149149〜649
Percy月5,000 snapshot無料約$199+
Applitools評価版enterprise quote
Cypress Cloud月500結果無料7575〜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