スナップショットテスト

コンポーネントの出力を保存し、変更時に差分を検出するテスト手法

テストフロントエンド

スナップショットテストとは

スナップショットテスト (Snapshot Test) は、コンポーネントやデータの出力を .snap ファイルに保存し、次回のテスト実行時に差分を検出する手法である。意図しない UI の変更を検知するが、意図的な変更時はスナップショットを更新する。

Vitest でのスナップショットテスト

import { describe, it, expect } from 'vitest';
import { render } from '@testing-library/react';
import { UserCard } from './UserCard';

describe('UserCard', () => {
  it('renders correctly', () => {
    const { container } = render(
      <UserCard name="Alice" email="alice@example.com" />
    );
    expect(container).toMatchSnapshot();
  });
});

初回実行時に .snap ファイルが生成される:

// __snapshots__/UserCard.test.tsx.snap
exports[`UserCard renders correctly 1`] = `
<div>
  <div class="card">
    <h2>Alice</h2>
    <p>alice@example.com</p>
  </div>
</div>
`;

インラインスナップショット

it('formats price correctly', () => {
  expect(formatPrice(1234)).toMatchInlineSnapshot(`"¥1,234"`);
});

.snap ファイルではなく、テストコード内にスナップショットを埋め込む。小さな出力に適している。

スナップショットの更新

# 意図的な変更後にスナップショットを更新
npx vitest --update

メリットとデメリット

メリット デメリット
意図しない変更を検知 大きなスナップショットはレビューが困難
テストの記述が簡単 「とりあえず更新」で形骸化しやすい
リグレッション防止 実装の詳細に依存

効果的な使い方

✅ 適する ❌ 適さない
小さなコンポーネントの出力 大きなページ全体
シリアライズ結果 (JSON) 頻繁に変わる UI
エラーメッセージ 動的なデータ (日時、ID)

ビジュアルリグレッションテストとの違い

観点 スナップショットテスト ビジュアルリグレッション
比較対象 HTML / テキスト スクリーンショット (画像)
CSS の変更検知
ツール Vitest Chromatic, Percy
速度 高速 低速

スナップショットテストは HTML 構造の変更を検知するが、CSS の変更 (色、レイアウト) は検知しない。CSS の変更も検知するにはビジュアルリグレッションテスト (Chromatic) を使う。

現場での応用を知るには関連書籍も役立つ。

関連用語