2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおけるテスト戦略:ユニット・統合・E2Eテストの役割と設計的分離原則

Posted at

概要

“テストを書いたコードは壊れない”のではない。
“壊れても気づける構造”に変わる。それがテスト戦略の本質である。

JavaScriptの開発において、ユニットテスト・統合テスト・E2Eテストは単なる実装補助ではなく、設計上の意思決定ツールである。
本稿では、テスト階層を設計上のスコープとして捉え、それぞれの目的・設計・選定技術・分離戦略を体系的に解説する。


1. テストピラミッドの設計原則

       ┌────────────┐
       │   E2E      │ ← 仕様検証・ブラウザ操作
       ├────────────┤
       │ Integration│ ← ユニット同士の連携
       ├────────────┤
       │   Unit     │ ← 単機能ロジック検証
       └────────────┘
  • 単体で速いユニットテストを基盤に
  • ✅ 統合で接続ミス・依存関係を検証
  • ✅ E2Eで“ユーザー目線の仕様”を検証

2. ユニットテストの設計

✅ 目的:1つの関数・モジュールの振る舞いの検証

// sum.js
export function sum(a, b) {
  return a + b;
}
// sum.test.js
import { sum } from './sum';

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});
  • ✅ 外部依存を持たない(副作用ゼロ)
  • ✅ 仕様が関数レベルで明確になる
  • ✅ フレームワーク例:Jest, Vitest

3. 統合テストの設計

✅ 目的:複数ユニット間の相互作用の検証

// userService.js
export async function getUserInfo(api, id) {
  const res = await api.fetch(`/users/${id}`);
  return res.data;
}
// userService.test.js
const mockApi = { fetch: jest.fn().mockResolvedValue({ data: { name: 'Toto' } }) };

test('getUserInfo returns user name', async () => {
  const result = await getUserInfo(mockApi, 1);
  expect(result.name).toBe('Toto');
});
  • ✅ HTTP・DBなどの抽象化インターフェースをモック
  • ✅ ユニットでは見えない依存間の連携不整合を検出
  • ✅ モック戦略が設計の粒度に直結

4. E2Eテストの設計

✅ 目的:ブラウザ上でのユーザー操作とUIの仕様検証

// 使用例(Playwright / Cypress)
test('ログイン後にプロフィール画面が表示される', async ({ page }) => {
  await page.goto('/login');
  await page.fill('#email', 'toto@example.com');
  await page.fill('#password', 'secret');
  await page.click('text=ログイン');
  await expect(page.locator('h1')).toHaveText('プロフィール');
});
  • ✅ 実際のブラウザ + 本物のUI
  • 自動UI回帰テストのコア
  • ✅ 実行コストが高いため、重要機能に限定

5. カバレッジとテスト優先順位の判断軸

機能 変更頻度 重要度 優先すべきテスト
ロジック関数 ユニット
API通信 統合
認証周辺 統合 + E2E
UI表示部 スナップショット or E2E
設定画面 ユニット or 無し

→ ✅ テストを書くコスト vs 発生しうる障害コストでバランスを設計


6. テストと設計の相関性

  • 関数が長すぎる → テストが書きにくい → 設計が悪い
  • 副作用が多すぎる → テストが不安定 → 責務が混在している
  • 依存が密結合 → モックが困難 → 分離設計が必要

→ ✅ “テストしにくい構造”は、“壊れやすい構造”の警告である


よくあるミスと対策

❌ カバレッジ100%を目指すが意味のないテストばかり

→ ✅ “重要な振る舞い”に焦点を当てた設計的テストを優先


❌ UIテストをすべてE2Eで行い、実行が遅くなる

→ ✅ E2Eは仕様の証明、UI部品はユニット+スナップショットでカバー


❌ 外部APIに直で依存し、テストが不安定

→ ✅ 抽象化されたAPI層をインジェクション可能な形で分離


結語

テストとは、「壊れたことを検出する仕組み」ではない。
それは、「壊れても影響を限定できる構造」を作る設計の一部である。

  • ユニットで責務を閉じ
  • 統合で依存を検証し
  • E2Eで体験を担保する

信頼性は偶然では得られない。
それは意図して設計された“検証構造”によってのみ生まれる。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?