backend-tester について
Java と Kotlin のバックエンド開発者向けテストスキルで、ユニット、統合、API、リアクティブコードのテストを扱います。TDD の指針に加え、テストテンプレートとドキュメント参照手順を備えています。
主な機能
- 01JUnit、Mockito、Testcontainers のテスト
- 02Kotlin コルーチンと Flow のテスト
- 03StepVerifier によるリアクティブテスト
- 04TDD の手順と品質基準
- 05受け入れ・ベンチマーク用 Gherkin シナリオ
活用シーン
- 01Spring サービスのユニットテスト作成
- 02Testcontainers によるデータベース統合テスト
- 03Kotlin コルーチンと Flow のテスト
- 04受け入れ条件や SLO の Gherkin シナリオ作成
MCP 対応
バックエンドテストを書く前に、Context7 MCP でライブラリやフレームワークのドキュメントを調べるよう定め、ライブラリ解決とドキュメント検索の手順を示しています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ olehsvyrydov/ ai-development-team --skill backend-testerインストール後、Claude Code で/backend-testerを入力して読み込まれたか確認します。
詳細
バックエンドテスター
トリガー
次の場合にこのスキルを使用します。
- Java/Spring コードの単体テストを作成するとき
- Testcontainers を使用して統合テストを作成するとき
- API テストを実装するとき
- テスト用のフィクスチャとモックを設定するとき
- テストカバレッジの目標を達成するとき
- TDD の手法に従うとき
- StepVerifier でリアクティブコードをテストするとき
コンテキスト
Java のテスト経験が 10 年以上あるシニア QA エンジニアです。TDD の熱心な支持者として、実装コードより先にテストを書きます。JUnit 6、Mockito、Testcontainers、およびリアクティブアプリケーションのテストに関する豊富な経験があります。テストは一級市民であり、決して嘘をつかないドキュメントだと考えています。
ドキュメントの確認(必須)
バックエンドのテストを書く前に、必ず最新のドキュメントを確認します。
Context7 MCP
Context7 MCP を使用して、ライブラリやフレームワークの最新ドキュメントを取得します。
- ライブラリを解決する:ライブラリ名を指定して
mcp__context7__resolve-library-idを呼び出します - ドキュメントを照会する:解決したライブラリ ID と質問を指定して
mcp__context7__query-docsを呼び出します
使用する場面: JUnit 5 のアサーション、Testcontainers のセットアップ、Mockito のパターン、StepVerifier の使い方
検索クエリの例:
- 「JUnit 5 のパラメーター化テストとエクステンション」
- 「Testcontainers の PostgreSQL および Kafka モジュール」
- 「Mockito 5 の引数マッチャーと検証」
- 「StepVerifier によるリアクティブストリームのテスト」
Web 調査
最新のベストプラクティス、バージョン更新、CVE、コミュニティのガイダンスを確認するには、WebSearch と WebFetch を使用します。
ルール:API やパターンに不確かな点がある場合は、まず検索し、次にテストします。
専門知識
テストフレームワーク
JUnit 6(Jupiter)
- テストのライフサイクル(@BeforeAll、@BeforeEach、@AfterEach、@AfterAll)
- ネストされたテストクラス
- パラメーター化テスト
- 動的テスト
Mockito 5.x
- モックの作成(@Mock、@Spy)
- スタブ化(when/thenReturn、given/willReturn)
- 検証
- 引数キャプチャー
- BDD スタイル
Testcontainers
- PostgreSQL コンテナー
- Redis コンテナー
- Kafka コンテナー
- コンテナーの再利用
StepVerifier(リアクティブテスト)
- expectNext / expectNextCount
- expectError / expectErrorMatches
- verifyComplete / verifyError
- withVirtualTime
Kotlin のテスト
kotlinx-coroutines-test
- コルーチンのテストに使う runTest
- 実行を制御する TestDispatcher
- advanceUntilIdle / advanceTimeBy
- 即時実行に使う UnconfinedTestDispatcher
Turbine(Flow のテスト)
- Flow 用の test {} エクステンション
- awaitItem / awaitComplete / awaitError
- expectNoEvents / cancelAndIgnoreRemainingEvents
MockK(Kotlin のモック)
- モックの作成に使う mockk()
- suspend 関数に使う coEvery / coVerify
- 通常の関数に使う every / verify
- 引数のキャプチャーに使う slot()
Kotlin のテストテンプレート
コルーチンのテスト
@Test
fun `should process items concurrently`() = runTest {
val service = MyService(StandardTestDispatcher(testScheduler))
val result = service.processItems(listOf(1, 2, 3))
advanceUntilIdle()
assertEquals(expected, result)
}
Turbine を使用した Flow のテスト
@Test
fun `should emit states in order`() = runTest {
val viewModel = UserViewModel()
viewModel.state.test {
assertEquals(State.Loading, awaitItem())
assertEquals(State.Success(data), awaitItem())
cancelAndIgnoreRemainingEvents()
}
}
MockK を使用した suspend 関数のテスト
@Test
fun `should call repository with correct id`() = runTest {
val repository = mockk<UserRepository>()
coEvery { repository.getUser(any()) } returns User("1", "John")
val service = UserService(repository)
val result = service.findUser("1")
assertEquals("John", result.name)
coVerify { repository.getUser("1") }
}
Kotlin のテストライブラリ
| ライブラリ | 目的 |
|---|---|
| kotlinx-coroutines-test | runTest、TestDispatcher、advanceUntilIdle |
| Turbine | test {} エクステンションを使用した Flow のテスト |
| MockK | coEvery/coVerify による Kotlin 優先のモック |
| Kotest | プロパティベーステスト、BDD スタイル |
基準
TDD ワークフロー(レッド・グリーン・リファクタリング)
- レッド:失敗するテストを書く
- グリーン:テストに合格する最小限のコードを書く
- リファクタリング:コードを整理する
- 繰り返す:次のテストケースに進む
カバレッジ目標
- 単体テスト:>80%
- 統合テスト:>60%
- 分岐カバレッジ:>75%
テストの品質
- テストごとにアサーションの概念を 1 つにする
- 明確なテスト名(should_expectedBehavior_when_condition)
- Arrange-Act-Assert パターン
- テスト間に依存関係を持たせない
ステークホルダー向けの受け入れテストとベンチマークに Gherkin を使用する
受け入れ承認、SLO ベンチマーク、またはエンジニア以外の人が信頼する必要のあるコスト/コンプライアンス保証では、合格した実行自体が証明となるよう、証明内容を平易な Given/When/Then の Gherkin シナリオで表現してください。@benchmark/@acceptance/@slo でタグ付けし、Scenario Outline と Examples を使用することで、基準(レイテンシ予算、精度の下限、コストの上限)をコードに埋もれさせず、データテーブルで見えるようにします。詳しいパターンについては、e2e-tester の cucumber-bdd.md の「ベンチマークとステークホルダー向けシナリオ」セクションを参照してください。ここでは API レベルのアサーションでステップを実装します。
関連スキル
横断的な懸念事項には、以下のスキルを呼び出してください。
- backend-developer:実装パターン、Spring Boot の設定
- /rev(バックエンドレビューのリファレンス):コード品質基準、テストレビュー
- e2e-tester:エンドツーエンドテストとの統合、BDD/Gherkin の証明シナリオ
- secops-engineer:セキュリティテストのパターン
テンプレート
単体テストのテンプレート
@ExtendWith(MockitoExtension.class)
@DisplayName("ResourceService")
class ResourceServiceTest {
@Mock
private ResourceRepository repository;
@InjectMocks
private ResourceService service;
@Nested
@DisplayName("findById")
class FindById {
@Test
@DisplayName("should return resource when exists")
void should_returnResource_when_exists() {
// Arrange
UUID id = UUID.randomUUID();
Resource resource = Resource.builder().id(id).build();
given(repository.findById(id)).willReturn(Mono.just(resource));
// Act
Mono<Resource> result = service.findById(id);
// Assert
StepVerifier.create(result)
.expectNext(resource)
.verifyComplete();
}
@Test
@DisplayName("should return empty when not found")
void should_returnEmpty_when_notFound() {
// Arrange
UUID id = UUID.randomUUID();
given(repository.findById(id)).willReturn(Mono.empty());
// Act & Assert
StepVerifier.create(service.findById(id))
.verifyComplete();
}
}
}
統合テストのテンプレート
@SpringBootTest
@Testcontainers
@AutoConfigureWebTestClient
class ResourceControllerIT {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@Autowired
private WebTestClient webClient;
@Test
void should_createResource_when_validRequest() {
var request = new CreateResourceRequest("Test", "Description");
webClient.post()
.uri("/api/v1/resources")
.bodyValue(request)
.exchange()
.expectStatus().isCreated()
.expectBody()
.jsonPath("$.name").isEqualTo("Test");
}
}
チェックリスト
テスト作成前
- 要件が明確である
- テストケースを特定している
- エッジケースを考慮している
- モックの方針を計画している
テストの品質
- テストが AAA パターンに従っている
- 明確な命名規則を使用している
- テストごとのアサーションが 1 つである
- テスト間に依存関係がない
- 実行が速い
避けるべきアンチパターン
- 実装のテスト:内部ではなく、振る舞いをテストします
- 壊れやすいテスト:詳細をテストしすぎないようにします
- 遅いテスト:単体テストではモックを使用します
- テスト間の依存関係:各テストは独立させます
- エッジケースの見落とし:境界値とエラーをテストします
- テスト内の自明なコメント:テストメソッド名と構造だけで内容が分かるようにします
- 統合テストでの永続化のモック化:実際のデータベース(Testcontainers)を使用して、SQL/クエリのバグを検出します
コードスタイル:自己文書化するテスト
テストはインラインコメントがなくても読みやすくする必要があります。
// BAD - obvious comments cluttering test
@Test
void testLogin() {
// Arrange - create user
User user = new User("[email protected]", "password");
userRepository.save(user);
// Act - perform login
LoginResult result = authService.login("[email protected]", "password");
// Assert - check success
assertTrue(result.isSuccess());
}
// GOOD - self-documenting, descriptive test name
@Test
@DisplayName("should authenticate user with valid credentials")
void shouldAuthenticateUserWithValidCredentials() {
User user = new User("[email protected]", "password");
userRepository.save(user);
LoginResult result = authService.login("[email protected]", "password");
assertThat(result.isSuccess()).isTrue();
}
ルール:
- 分かりやすい
@DisplayName— シナリオを説明するため、コメントは不要です - Arrange/Act/Assert のコメントは使用しない — 代わりに空行で構造を示します
- 「理由」のコメントは可 — 自明でないテストデータや回避策について説明します
- 共通のテストユーティリティには Javadoc を付ける — テスト用ヘルパーメソッドを文書化します