unit-testing-01jpfcdnrsxk3j5vqvjgqp2f6t.md•5.61 kB
---
description: ユニットテストの基本原則とベストプラクティス
ruleId: unit-testing-01jpfcdnrsxk3j5vqvjgqp2f6t
tags:
- testing
- development
- quality
globs:
- "**/*.test.ts"
- "**/*.spec.ts"
- "**/*Test.java"
- "**/*Test.scala"
- "**/*_test.go"
- "**/*_test.rs"
- "**/*.test.py"
- "**/*_test.rb"
---
# ユニットテスト
ユニットテストは、ソフトウェア開発において個々のコンポーネントや関数が意図したとおり動作するかを検証する手法です。適切なユニットテストを実装すると、コードの品質を向上させ、回帰バグを早期に発見できます。
## 基本原則
### 1. 独立性を保つ
- 各テストケースは他のテストに依存せず、独立して実行できるようにする
- テストケース間で共有される状態を避け、外部依存関係をテストケースごとに分離することでテスト間の干渉を防ぐ
- テストの実行順序を考慮しない設計にする
### 2. 高速であること
- テストは数ミリ秒から数秒以内に完了するべき
- 外部リソース(データベース、ファイルシステム、ネットワーク)へのアクセスは最小限に抑える
- 必要に応じてモックやスタブを活用する
### 3. 再現性を確保する
- テストは毎回同じ結果を返すべき(決定論的であること)
- ランダム値や時間に依存する処理は、固定値でモック化する
- テストデータは明示的に定義し、外部からの変更の影響を受けないようにする
### 4. 自己検証性を持つ
- テスト結果は自動的に成功/失敗が判定されるべき
- 手動での確認や解釈が必要なテストは避ける
- 明確なアサーションを使用する
### 5. 網羅性を確保する
- 正常系(期待通りの入力と動作)だけでなく、異常系(不正入力やエラー条件)もテストする
- エッジケースや境界値のテストを含める
- 複雑な分岐やパスに対しては、網羅率を高める
## テスト構造
### AAA(Arrange-Act-Assert)パターン
すべてのテストは以下の3つのセクションで構成することを推奨します。
1. **Arrange(準備)**:テストに必要なオブジェクトやデータを初期化
2. **Act(実行)**:テスト対象を動作させる
3. **Assert(検証)**:期待される結果と実際の結果を比較検証。
```typescript
// TypeScriptでのAAAパターンの例
test('ユーザー名が正しく設定される', () => {
// Arrange
const user = new User();
const expectedName = 'John Doe';
// Act
user.setName(expectedName);
// Assert
expect(user.getName()).toBe(expectedName);
});
```
## 言語別のテストフレームワーク
### Java
- JUnit 5
- TestNG
- Mockito(モック用)
### Scala
- ScalaTest
- Specs2
- ScalaMock
### TypeScript/JavaScript
- Jest
- Mocha + Chai
- Jasmine
- Testing Library
### Rust
- cargo test (標準)
- mockall(モック用)
### Go
- testing パッケージ(標準)
- testify
- gomock
### Python
- pytest
- unittest(標準)
- mock(標準)
## コードカバレッジ
コードカバレッジは、テストによって実行されたコードの割合を示す指標です。以下のカバレッジ目標を設定します。
- **ライン(命令)カバレッジ**:80%以上
- **ブランチ(分岐)カバレッジ**:75%以上
- **関数カバレッジ**:90%以上
ただし、カバレッジの数値だけを目標にせず、テストの品質と意義を重視してください。
## モックとスタブの使用
### モックの適切な使用
- 外部依存関係(データベース、API、ファイルシステムなど)をモック化する
- 重い計算や時間のかかる処理をモック化して高速化する
- 非決定的な動作(時間、乱数など)を制御可能にする
### モックの過剰使用を避ける
- 実装詳細と過度に結合するモックは使用しない
- ビジネスロジック自体のモック化は最小限に留める
- 可能な限り実際のコンポーネントを使用する
## テスト駆動開発(TDD)の推奨
可能な場合は、テスト駆動開発(TDD)アプローチを採用することを推奨します。
1. **赤**:まず失敗するテストを書く
2. **緑**:テストが通るための最小限のコードを実装する
3. **リファクタリング**:コードをクリーンアップし、重複を排除する。
このサイクルを繰り返すことで、堅牢で保守性の高いコードを作成できます。
## 避けるべきプラクティス
- **スナップショットテストの乱用**:UI変更ごとに更新が必要になるため、過度に依存しない
- **過度に具体的なテスト**:実装詳細ではなく動作をテストする
- **不適切なアサーション**:曖昧な比較や包括的すぎる検証を避ける
- **複雑なセットアップ**:テストの準備が複雑になりすぎる場合は、設計の問題を示している可能性がある
## 参考
- [Martin Fowler - Unit Testing](https://martinfowler.com/bliki/UnitTest.html)
- [Kent Beck - Test-Driven Development By Example](https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530)
- [Robert C. Martin - Clean Code](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)