🕒 学習時間
21:00~21:30
🧑💻 実施した学習内容
1. 疑問点
@ParameterizedTest, @ValueSource, @MethodSource, @CsvSource, @CsvFileSource, @EnumSource, @ConvertWith, @ArgumentsSourceについて
2. 技術の概要
◾️何をするものか
JUnit 5(JUnit Jupiter)の@ParameterizedTestは、同じテストロジックに対して異なる引数を渡して複数回テストを実行する際に不可欠なアノテーションです。これと組み合わせてよく使われる、データソースや表示名をカスタマイズするアノテーション群をまとめました。
「パラメータ化テスト」を実現するためのアノテーション群。
→ 同じテストロジックを「複数の入力データ」で繰り返し実行できる。
◾️背景・目的(なぜ必要か)
従来のテストでは以下の課題があった:
- 同じロジックのテストを複数書く必要がある(重複コード)
- 境界値・異常値テストが漏れやすい
- テストケースの可読性が低い
→ パラメータ化テストにより「データとロジックを分離」し、網羅性・保守性を向上させる
3. 内容
◾️ 1. パラメータソース(データ源)のアノテーション
→テストメソッドに渡すデータを定義します。
・@ValueSource: 単一の引数を渡す場合に利用
・@CsvSource: CSV形式で複数の引数を渡す場合に利用。
・@CsvFileSource: CSVファイルから引数を読み込む場合に利用。
・@MethodSource: 別のメソッドが返す値(Stream, Iterable, Iterator, Object)を引数として利用。複雑なオブジェクトを引数にしたい場合は適しています。
・@EnumSource: Enum型をテストデータとして渡す場合に利用。
◾️ 2. 表示名や引数変換の補助アノテーション
→テスト実行時の見栄えや、データの変換を管理します。
・@DisplayName: テストメソッドにわかりやすい名前を付け、JUnitレポートで表示します。
・@ParameterizedTest(name = "..."): パラメータ化テストの表示名をカスタマイズし、具体的にどの引数で実行されたかを分かりやすくします。
・@ConvertWith: 引数の型を自動変換(例えばStringをLocalDateに変換)する場合に使用します。
・@ArgumentsSource: カスタムな引数供給クラス(ArgumentsProviderを実装したクラス)を指定して、高度なデータ供給を行いたい場合に使用します。
① @ParameterizedTest
- パラメータ付きテストを実行するための必須アノテーション
- 通常の@Testの代わりに使用
② @ValueSource
- 単一型の値を配列で渡す
例:
@ParameterizedTest
@ValueSource(strings = {"apple", "banana", "orange"})
void testWithStrings(String input) {
assertNotNull(input);
}
👉 制約:
- 1引数のみ
- プリミティブ or Stringなど単純型のみ
③ @MethodSource
- メソッドからデータ供給(最も柔軟)
@ParameterizedTest
@MethodSource("provideNumbers")
void test(int num) {
assertTrue(num > 0);
}
static Stream<Integer> provideNumbers() {
return Stream.of(1, 2, 3);
}
👉 特徴:
- 複数引数OK
- 複雑なオブジェクトも扱える
④ @CsvSource
- CSV形式で複数引数を定義
@ParameterizedTest
@CsvSource({
"1, one",
"2, two"
})
void test(int num, String word) {
assertNotNull(word);
}
⑤ @CsvFileSource
- 外部CSVファイルからデータ読み込み
@ParameterizedTest
@CsvFileSource(resources = "/data.csv")
void test(String name, int age) {
assertTrue(age > 0);
}
👉 実務でよく使う(データ量が多い場合)
⑥ @EnumSource
- Enumの値をすべて or 指定して渡す
enum Color { RED, BLUE }
@ParameterizedTest
@EnumSource(Color.class)
void test(Color color) {
assertNotNull(color);
}
⑦ @ConvertWith
- カスタム変換ロジックを定義
class StringToIntegerConverter extends SimpleArgumentConverter {
@Override
protected Object convert(Object source, Class<?> targetType) {
return Integer.parseInt((String) source);
}
}
@ParameterizedTest
@ValueSource(strings = {"1", "2"})
void test(@ConvertWith(StringToIntegerConverter.class) int num) {
assertTrue(num > 0);
}
⑧ @ArgumentsSource
- 独自のデータ供給クラスを使う(拡張性最強)
class MyArgumentsProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
Arguments.of(1, "one"),
Arguments.of(2, "two")
);
}
}
@ParameterizedTest
@ArgumentsSource(MyArgumentsProvider.class)
void test(int num, String word) {
assertNotNull(word);
}
4. 用語定義
- パラメータ化テスト:同じテストを複数データで実行する手法
- Arguments:テストに渡す引数の集合
- ArgumentsProvider:データ供給クラス
- Converter:型変換を行う仕組み
5. 解決する課題・メリット
- テストコードの重複削減
- テストケースの網羅性向上(境界値テストが容易)
- データ駆動テスト(Data Driven Testing)が可能
- 可読性向上(ロジックとデータ分離)
6. 使用する注意事項・デメリット
- 学習コストがやや高い(特に@ArgumentsSource)
- 可読性が逆に落ちるケース(複雑なMethodSource)
- デバッグが難しい(どのケースで失敗したか分かりにくい)
7. 類似技術との比較
| アノテーション | 柔軟性 | 複数引数 | 外部データ | 難易度 |
|---|---|---|---|---|
| ValueSource | 低 | × | × | 低 |
| CsvSource | 中 | ○ | × | 低 |
| CsvFileSource | 中 | ○ | ○ | 中 |
| EnumSource | 低 | × | × | 低 |
| MethodSource | 高 | ○ | ○ | 中 |
| ArgumentsSource | 最高 | ○ | ○ | 高 |
8. 基本的な使い方・実装(サンプルコード)
// パラメータ化テストの基本例
@ParameterizedTest
@CsvSource({
"10, 2, 5",
"9, 3, 3"
})
void divideTest(int a, int b, int expected) {
// 実際の計算
int result = a / b;
// 検証
assertEquals(expected, result);
}
◾️解説
- 1行 = 1テストケース
- a / b の結果が expected と一致するか検証
@ParameterizedTest
@CsvSource({
"1, 2, 3",
"2, 3, 5"
})
@DisplayName("加算テスト")
void testAddition(int a, int b, int expected) {
assertEquals(expected, a + b);
}
9. 根拠の掲示
◾️[公式ドキュメント]
https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
◾️[参考記事]
https://www.baeldung.com/parameterized-tests-junit-5
10. 次やること
- @MethodSourceと@ArgumentsSourceを実務レベルで使い分ける
- CSV + DBデータを組み合わせたテスト設計を考える
- SpringBootのControllerテストに組み込む