JavaでProperty-Based testing その1 [JPopulator + Junit]


テストツールAdventCalendar 2015 11日目の記事です。
1日遅れてしまってすいません。

導入

先日、ランダムデータを作ってテストしたいケースがあり、ランダムデータ生成やProperty-based testingのライブラリを探しました。
そこで見つけたjPopulatorが簡単に使えて便利そうだったので紹介しようと思います。

使い方

まず、もっともシンプルな使い方です。

Populator generator = new PopulatorBuilder().build();
generator.populateBean(Person.class);

populateBeanメソッドの引数に指定したクラスのデータが自動的に生成できます。
他のフレームワークに依存しておらず、たったこれだけの記述でランダムデータを生成できます。
また、フィールドにクラスがある場合も自動的にそのクラス内のフィールドもランダムデータで埋めてくれます。

普段テストするとき、本当はできるだけ現実で使われるデータに近いデータを用意したいのに、必要最低限で済ますことが多いかと思います。
簡単に記述できるるので、テストの視認性を下げずに、重要度が低いと考えているフィールドにもとりあえず値を詰めておくということができます。

生成データのコントロール

生成データを調整することも簡単にできます。

フィールドを除外して生成

generator.populateBean(Person.class, "age");

指定数のインスタンスをまとめて作成

generator.populateBeans(Person.class, 100);

ランダムな数のインスタンスをまとめて作成

generator.populateBeans(Person.class);

生成されるデータのバリエーションを変える

Randomizerインターフェースを実装することで生成データの内容も自由にカスタマイズできます。

public class AgeRandomizer implements Randomizer<Integer> {
    @Override
    public Integer getRandomValue() {
        return ((Double) (Math.random() * 50)).intValue();
    }
}

RandomizerはSAM Typeなのでもちろんラムダ式で書くことができます。

Populator generator = new PopulatorBuilder()
                .registerRandomizer(Person.class, Integer.class, "age", () -> ((Double) (Math.random() * 50)).intValue())
                .build();
}

既成のRandomizerもいくつか用意されているので便利に使えると思います。

既成のRandomizer

Randomizerの使用例

Populator generator = new PopulatorBuilder()
                .registerRandomizer(Person.class, String.class, "name", new FirstNameRandomizer())
                .build();

最後にテストへの応用例としてJUnitのDataPointsを利用してテスト用のランダムデータを生成するコードを紹介します。

import org.junit.contrib.theories.DataPoints;
import org.junit.contrib.theories.Theories;
import org.junit.contrib.theories.Theory;
import org.junit.runner.RunWith;

import io.github.benas.jpopulator.api.Populator;
import io.github.benas.jpopulator.impl.PopulatorBuilder;
import io.github.benas.jpopulator.randomizers.CityRandomizer;
import io.github.benas.jpopulator.randomizers.FirstNameRandomizer;

@RunWith(Theories.class)
public class UseJpopulator {
    @DataPoints
    public static Person[] getParameters() {
        Populator generator =
            new PopulatorBuilder()
                .registerRandomizer(Person.class, String.class, "name", new FirstNameRandomizer())
                .registerRandomizer(Person.class, Integer.class, "age", () -> ((Double) (Math.random() * 50)).intValue())
                .registerRandomizer(Address.class, String.class, "city", new CityRandomizer())
                .build();
        return generator.populateBeans(Person.class, 100).toArray(new Person[0]);
    }
    @Theory
    public void XXX(Person p) {
        // TODO some tests
    }
}

生成結果

今日は以上です。

次はJunit-Quickcheckについて書くつもりです。