JUnit5のParametrisedTestの@ValueSourceを使う


概要

このエントリは、JUnit5で単体テストを書くとき、パラメータを変えたテストを書くのを楽にしてくれる「ParametrisedTest」の「@ValueSource」を使用する方法を書きます。

Enterprise電卓を作る Advent Calendar 2019の2日目のエントリです。

想定読者

  • JUnit4には慣れているけれどもまだJUnit5のお便利機能を使っていない方。

JUnit5のParametrisedTest

JUnit5は、JUnit4を大幅刷新したテストフレームワークです。ばっさり削除された機能もあれば、新たに追加になった機能もあります。

新たに追加になった機能の中に「Parameterized Tests」があります。これは、一つのテストケースの引数に対して、値の種類を様々に変えてパラメータとして渡すことで、簡単にテストが書けるような支援をしてくれるものです。

準備

ドキュメントによれば、Parameterized Testsを実行するには、「junit-jupiter-params」のアーティファクトを利用可能になっている必要があります。
このエントリでは、SpringBootを使っており、テスト用にspring-boot-starter-testを使用していますが、この場合はspring-boot-starter-testを一行書いておくだけでjunit-jupiter-paramsへの依存関係も指定されています。

build.gradleに下記のような指定を入れています。
SpringInitializrを使うと、JUnit3やJunit4で書かれたテストを実行することをサポートする「junit-vintage-engine」は使用しない指定も入れてくれました。

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }

@ValueSourceでテストを書いてみる

JUnitを書くとき、結果の確認には、読みやすさが好きなので「AssertJ」を使っています。build.gradleに下記の一行を追加しています。

    testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.14.0'

ValueSourceを使ったテストのソースの例を下記に示します。


    @ParameterizedTest
    @ValueSource(chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'})
    public void push_single_success(char c) {
        DeskCalculator dc = new DeskCalculator();
        dc.pushChar(c);
        assertThat(dc.getCurrentValue()).isEqualTo(new BigDecimal(new String(new char[]{c})));
    }

このテストで対象としているDeskCalculatorクラスの「pushChar」メソッドは、下記の機能を持っています。

  1. 数値("0-9"と".")を示すcharは入力し、内部バッファに保持する
  2. それ以外は無視する
  3. 内部の数値バッファはインスタンス内の文字列で保持する。外部から値を問われたときにはBigDecimalで返す。

テスト実行結果は下図のとおりです。10個分テストされていますね。

数値が入ることは上記でテストしましたが、2番目の動作を確認するため、次のテストも書きます。

    @ParameterizedTest
    @ValueSource(chars = {'+', '-', '*', '/', 'A', '!', ' '})
    public void push_single_invalid_char_success(char c) {
        DeskCalculator dc = new DeskCalculator();
        dc.pushChar(c);
        assertThat(dc.getCurrentValue()).isEqualTo(BigDecimal.ZERO);
    }

上記2つの例で挙げたように、@ValueSourceの部分にパラメータを複数渡してあげることで、複数の値に対するテストが実行されます。

おわりに

本エントリでは、JUnit5で追加となった「ParametrisedTest」について取り上げました。
ParametrisedTestは、@ValueSourceのほかにも、複数の引数を渡してあげる機能、CSVから値を読み込む機能なども提供されています。

このエントリで使用したコードは、GitHubにタグをつけて格納しています。https://github.com/hrkt/commandline-calculator/releases/tag/0.0.3