# AAAパターンで実現するクリーンなテストコード

> テストコードを整理するAAAパターンについて解説。Arrange（準備）、Act（実行）、Assert（確認）の3ステップで、より保守性の高いテストコードを実現する方法を、具体的なコード例とともに紹介します。

- 公開日: 2024-12-03
- 更新日: 2024-12-05
- 著者: Tsukamura
- タグ: エンジニア概念マップ, テスト
- URL: https://tech.anycloud.co.jp/articles/test-aaa

---

あなたは次のようなテストコードを見たことはありませんか？

```typescript
test('商品追加のテスト', () => {
  const cart = new ShoppingCart();
  expect(cart.getTotal()).toBe(0);
  cart.addItem('apple', 100);
  expect(cart.getTotal()).toBe(100);
  cart.addItem('banana', 150);
  expect(cart.getTotal()).toBe(250);
});

```

一見問題なさそうに見えるこのテストコード。しかし、このような書き方には実は大きな問題が潜んでいます。今回は、テストコードを整理するための重要な考え方「AAAパターン」について解説します。

## AAAパターンとは？

AAAパターンは、テストコードを以下の3つのフェーズに分けて構造化する手法です。

1.  **Arrange（準備）**：テストに必要な前提条件を整える
2.  **Act（実行）**：テスト対象の機能を実行する
3.  **Assert（確認）**：期待する結果が得られたかを検証する

この3つのフェーズを明確に分けることで、テストの意図がクリアになり、保守性が大幅に向上します。

## 悪い例と良い例で学ぶAAAパターン

### 悪い例：フェーズが混在したテストコード

```typescript
test('商品追加時の合計金額テスト', () => {
  const cart = new ShoppingCart();
  expect(cart.getTotal()).toBe(0);     // 準備と確認が混在
  cart.addItem('apple', 100);          // 実行
  expect(cart.getTotal()).toBe(100);   // 確認
  cart.addItem('banana', 150);         // また実行
  expect(cart.getTotal()).toBe(250);   // さらに確認
});

```

このコードの問題点

-   各フェーズの境界が不明確
-   複数の動作を一度にテストしている
-   テストが失敗した際の原因特定が困難

### 良い例：AAAパターンを適用したテストコード

```typescript
test('商品追加時の合計金額が正しく計算されること', () => {
  // Arrange（準備）
  const cart = new ShoppingCart();
  const testItems = [
    { item: 'apple', price: 100 },
    { item: 'banana', price: 150 }
  ];
  const expectedTotal = 250;

  // Act（実行）
  testItems.forEach(({ item, price }) => {
    cart.addItem(item, price);
  });
  const actualTotal = cart.getTotal();

  // Assert（確認）
  expect(actualTotal).toBe(expectedTotal);
});

```

改善された点

-   テストの各フェーズが明確に分離されている
-   テストの意図が理解しやすい
-   期待値と実際の値の比較が1か所にまとまっている
-   デバッグが容易

## AAAパターンを実践するためのTips

### 1\. コメントでフェーズを区切る

```typescript
// Arrange
// Act
// Assert

```

### 2\. 空行でフェーズを視覚的に分ける

```typescript
// Arrange
const service = new Service();
const input = 'test';

// Act
const result = service.process(input);

// Assert
expect(result).toBe('TEST');

```

### 3\. 各フェーズの役割を意識する

-   **Arrange**：テストに必要なオブジェクトの生成、データの準備
-   **Act**：テスト対象の機能を1回だけ実行
-   **Assert**：期待する結果との比較を行う

## AAAパターン採用のメリット

1.  可読性の向上
    -   テストの流れが一目で分かる
    -   コードレビューが効率化される
2.  保守性の向上
    -   テストの修正が容易になる
    -   新しいテストケースの追加がスムーズ
3.  デバッグの効率化
    -   テスト失敗時の原因特定が容易
    -   どのフェーズで問題が発生したかが明確

## まとめ

AAAパターンは、テストコードを整理するための強力なツールです。このパターンを意識することで

-   テストの意図が明確になる
-   コードの保守性が向上する
-   チーム内でのコード理解が促進される

特に大規模なプロジェクトや長期的なメンテナンスが必要なコードベースでは、AAAパターンが推奨されます(｀・ω・´)

みなさんも、次回テストコードを書くときは、AAAパターンを意識してみてはいかがでしょうか？
