Posted at

@ParameterizedTestで1メソッドで複数のテストケースに対応!


概要


  • Junitでテストを記述しているとインプットが違うだけで、結果やテスト内容が変わらないことがある

  • そういったときに1テストに対して1テストメソッドを作るのが手間に感じた


  • @ParameterizedTestを使えば対応できるので使ってみた


@ParameterizedTestでできること


  • 使わない場合

    @Test

public void sample1() {
assertThat("a".length()).isEqualTo(1);
}

@Test
public void sample2() {
assertThat("b".length()).isEqualTo(1);
}

(こんなテスト書かないけどあくまでサンプルとして…)


  • 使う場合

    @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クラスの定義を元にテストを行いたい時に使える


  • namesmodeを指定するとinclue,excludeとかができる

  • modeのデフォルトはINCLUDE


使用するEnumクラス

    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


include

    @ParameterizedTest

@EnumSource(value = SampleEnum.class, names = {"ENUM1", "ENUM2"})
public void enumInclude(SampleEnum value) {
System.out.println("enum: " + value);
}


実行結果

enum: ENUM1

enum: ENUM2


exclude

    @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



  • @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