Junitでテストを記述しているとインプットが違うだけで、結果やテスト内容が変わらないことがあります。
そういったときに1ケースに対して1テストメソッドを作るのは手間ですよね。。。
@ParameterizedTest
を使えば対応できますよ!
@ParameterizedTest
でできること
@ParameterizedTest
を使わない場合はこんな感じのコードになりますよね。
@Test
public void sample1() {
assertThat("a".length()).isEqualTo(1);
}
@Test
public void sample2() {
assertThat("b".length()).isEqualTo(1);
}
(こんなテスト書かないですが、あくまでサンプルとして…)
@ParameterizedTest
を使うとこうなります。
@ParameterizedTest
@ValueSource(strings = {"a", "b"})
public void sample(String string) {
assertThat(string.length()).isEqualTo(1);
}
こんな感じで@ValueSource
の引数にパラメータを追加するだけで複数のテストをまとめることができます!
パラメータを指定する方法が何通りかあるのでご紹介します。
@ValueSource
- 「パラメータが1つ」でかつ「型が基本型」の場合に使用する
- パラメータの型によって引数の指定の仕方が変わる
- @ValueSourceの引数で指定した値は、メソッドの引数で受け取る
基本型を一通り扱えるようなのですが、ここでは私がよく使うものにしぼってもう少し詳細に紹介します。
String
- 空文字や空白文字は扱えるが、nullは扱えない
- nullを扱いたい場合は後述の@MethodSourceを使用する
@ParameterizedTest
@ValueSource(strings = {"a", "b", "c"})
public void string(String value) {
System.out.println("string: " + value);
}
string: 'a'
string: 'b'
string: 'c'
string: ''
string: ' '
int
@ParameterizedTest
@ValueSource(ints = {1, 2 ,3})
public void ints(int value) {
System.out.println("ints: " + value);
}
ints: 1
ints: 2
ints: 3
@CsvSource
- 複数のパラメータをメソッドに渡したい時に使用する
- パラメータは文字列で記述し、Csvの名前の通りカンマ区切りで複数のパラメータを結合する
- 数値を指定した場合はStringでもintでも受け取れる
@ParameterizedTest
@CsvSource({"1, val1", "2, val2", "3, val3"})
public void csv(int num, String value) { // 数値をintで受け取る
System.out.println("num: '" + num + "', value: '" + value + "'");
}
@ParameterizedTest
@CsvSource({"1, val1", "2, val2", "3, val3"})
public void csv(String num, String value) { // 数値をStringで受け取る
System.out.println("num: '" + num + "', value: '" + value + "'");
}
num: '1', value: 'val1'
num: '2', value: 'val2'
num: '3', value: 'val3'
- nullや空文字も扱える
- デフォルトだと前後の空白文字はトリミングされるが、”で囲むことで前後の空白文字も残せる
@ParameterizedTest
@CsvSource({"空文字, ''", "空白文字, ' '", "null, "})
public void csv(String type, String value) {
System.out.println(type + ": '" + value + "'");
}
空文字: ''
空白文字: ' '
null: 'null'
@EnumSource
- enumクラスの定義を元にテストを行いたい時に使える
names
やmode
を指定するとinclue,excludeとかができる- modeのデフォルトは
INCLUDE
enum SampleEnum {
ENUM1,
ENUM2,
ENUM3
}
@ParameterizedTest
@EnumSource(SampleEnum.class)
public void enumSource(SampleEnum value) {
System.out.println("enum: " + value);
}
enum: ENUM1
enum: ENUM2
enum: ENUM3
@ParameterizedTest
@EnumSource(value = SampleEnum.class, names = {"ENUM1", "ENUM2"})
public void enumInclude(SampleEnum value) {
System.out.println("enum: " + value);
}
enum: ENUM1
enum: ENUM2
@ParameterizedTest
@EnumSource(value = SampleEnum.class, names = {"ENUM1", "ENUM2"}, mode = EnumSource.Mode.EXCLUDE)
public void enumExclude(SampleEnum value) {
System.out.println("enum: " + value);
}
enum: ENUM3
@MethodSource
- 任意のクラスを引数に渡せる
- 引数に渡すために
Stream, Iterable, Iterator
のいずれかを返り値とするstaticメソッドを定義する - 前述の通り、nullも扱える
@ParameterizedTest
@MethodSource("source")
public void methodSource(String value) {
System.out.println("value: " + value);
}
public static Stream<String> source() {
return Stream.of("string1", "string2", null);
}
value: string1
value: string2
value: null