2.2. 結合テスト規定
このドキュメントは、結合テスト(インテグレーションテスト)の実装に関する具体的な規約を定めます。結合テストは、個々のユニットが連携した際に、システムとして正しく機能することを保証します。
1. 結合テストの定義と目的
- 定義:
- 結合テストとは、複数のコンポーネント(ユニット)を組み合わせて、それらが連携する部分を検証するテストです。
- 単体テストではモックやスタブで置き換えていた、実際の外部依存(データベース、ファイルシステム、外部APIなど)と接続してテストを行います。
- 目的:
- コンポーネント間のインターフェースの不整合(データ形式の違い、呼び出し規約の誤りなど)を検出します。
- 外部サービスとの接続が正しく行えることを検証します。(例: データベースのスキーマとO/Rマッパーのエンティティ定義が一致しているか)
- 単体テストでは見つけられない、複数のコンポーネントが絡み合った複雑なシナリオでのバグを検出します。
2. 結合テストのスコープ(対象範囲)
結合テストで検証すべき、代表的な連携ポイントは以下の通りです。
- データベース連携:
- アプリケーションのロジックが、実際のデータベースに対して、正しくデータの読み書き(CRUD)を行えるか。
- トランザクションが期待通りに機能するか(コミット、ロールバック)。
- ファイルシステム連携:
- ファイルの読み書き、フォルダの作成・削除などが正しく行えるか。
- 外部API連携:
- サードパーティのAPIや、マイクロサービス間のAPI呼び出しが、実際のエンドポイントに対して正しく行えるか。
- メッセージキュー連携:
- メッセージの送受信が、実際のブローカー(RabbitMQ, Kafkaなど)を通じて正しく行えるか。
- APIエンドポイントのテスト:
- APIのコントローラー層から、ビジネスロジック層、データアクセス層までを含めた一連のフローをテストする。HTTPリクエストを実際に送信し、レスポンスを検証します。
3. テスト環境の管理
結合テストは実際の外部サービスと連携するため、テスト環境の管理が極めて重要です。
- 原則: ローカルで完結させる:
- 可能な限り、Docker Compose などを活用し、必要なデータベースや外部サービスをローカルコンテナとして起動し、テストを実行できる環境を構築することを強く推奨します。
- これにより、他の開発者やCI環境との競合を避け、誰でも安定してテストを実行できます。
- テスト用データベース:
- テストごとに、データベースの状態をクリーンな状態にリセットする必要があります。
- 戦略1 (推奨): 各テストの実行前にトランザクションを開始し、テスト終了後にロールバックする。
- 戦略2: 各テストの実行前に、スキーマを再作成し、テストデータを投入する。
- 設定とシークレット:
- テスト環境用の接続文字列やAPIキーは、ソースコードにハードコーディングせず、設定ファイルや環境変数から読み込むようにします。CI環境では、GitHub Secretsなどを使って安全に管理します。
4. 結合テストの実装パターン
4.1. APIエンドポイントテスト
- 目的: APIの振る舞いを、外部のクライアント視点で検証します。
- 推奨ツール:
- C# (ASP.NET Core):
Microsoft.AspNetCore.Mvc.TestingのWebApplicationFactoryを利用し、インメモリでテストサーバーを起動してテストします。 - Python (FastAPI/Flask):
TestClientを利用します。 - TypeScript (Node.js/Express):
Supertestなどのライブラリを利用します。
- C# (ASP.NET Core):
C# でのテスト例 (WebApplicationFactory):
public class UserControllerTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly HttpClient _client;
public UserControllerTests(WebApplicationFactory<Program> factory)
{
_client = factory.CreateClient();
}
[Fact]
public async Task GetUser_WithValidId_ReturnsOk()
{
// Act
var response = await _client.GetAsync("/api/users/1");
// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
var user = await response.Content.ReadFromJsonAsync<UserDto>();
Assert.NotNull(user);
Assert.Equal(1, user.Id);
}
}
5. 注意事項
- 実行速度: 結合テストは単体テストに比べて実行が遅いため、数は単体テストよりも少なくなるべきです(テストピラミッド)。
- 不安定さ (Flakiness): ネットワークや外部サービスの状況によって、テストが時々失敗する(Flaky Test)可能性があります。失敗の原因がテスト対象のコードにあるのか、環境にあるのかを切り分けられるように設計し、リトライ処理の導入などを検討します。
- CIでの実行: 実行時間が長いため、CIパイプラインでは、単体テストとは別のステージとして実行することを推奨します。Pull Request時には必須としつつ、プッシュごとの実行はスキップするなどの戦略も考えられます。