LoginSignup
5

More than 5 years have passed since last update.

JavaでProperty-Based testing その2 [junit-quickcheck]

Posted at

テストツールAdventCalendar 2015 18日目の記事です。

導入

先日、ランダムデータを作ってテストしたいケースがあり、ランダムデータ生成やProperty-based testingのライブラリを探しました。
jPopulatorに続き、junit-quickcheckを試してみることにしました。
readmeを読みながら試してみます

使い方

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

    import com.pholser.junit.quickcheck.JUnitQuickcheck;
    import com.pholser.junit.quickcheck.Property;
    import org.junit.runner.RunWith;

    import static org.junit.Assert.*;

    @RunWith(JUnitQuickcheck.class)
    public class StringProperties {
        @Property public void concatenationLength(String s1, String s2) {
            assertEquals(s1.length() + s2.length(), (s1 + s2).length());
        }
    }

これでconcatenationLengthのテストが0~200文字のランダムな文字列で100回呼ばれます。

Generatorを指定して実行

@FromアノテーションでGeneratorのクラスを指定することでいろいろな値を生成することができます。

@RunWith(JUnitQuickcheck.class)
    public class IdentificationProperties {
        @Property public void shouldHold(@From(Version5.class) UUID u) {
            // ...
        }
    }

カスタムGeneratorはcom.pholser.junit.quickcheck.generator.Generatorkurasu を実装するだけで作成できます。実装が必要なabstract methodはgenerate()メソッド一つなので簡単です。

import com.pholser.junit.quickcheck.generator.GenerationStatus;
import com.pholser.junit.quickcheck.generator.Generator;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;

public class HogeGenerator extends Generator<String> {
    public HogeGenerator() {
        super(String.class);
    }

    @Override
    public String generate(SourceOfRandomness random, GenerationStatus status) {
        return "hoge";
    }

}

@InRangeを使った生成データの範囲指定

import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.junit.Assume.assumeThat;

import java.util.List;

import org.junit.runner.RunWith;

import com.pholser.junit.quickcheck.Property;
import com.pholser.junit.quickcheck.generator.InRange;
import com.pholser.junit.quickcheck.runner.JUnitQuickcheck;

@RunWith(JUnitQuickcheck.class)
public class SingleDigitProperties {
    @Property
    public void hold(@InRange(min = "0", max = "9") int digit) {
        // hope we get enough single digits
        assumeThat(digit, greaterThanOrEqualTo(0));
        assumeThat(digit, lessThanOrEqualTo(9));
        System.out.println(digit);
        // ...
    }

    @Property
    public void hold(List<@InRange(min = "0", max = "9") Integer> digits) {
        System.out.println(digits);
        // ...
    }
}

assumeThat

今回試したときにはバグがあって正しく動作しなかった。

@When OGNL記法

@When(satisfies = "#_ >= 0 && #_ <= 9")
この記法は動作しなかった

その他

シンプルに回数指定

@Property(trials = 250) public void northernHemisphere(
Propertyにtrialsの値を渡すと指定した回数実施される。

Seed と Shrink

今回は時間がなくて試すことができなかった。

Readmeのサンプルコードで使っているHamcrest

HamcrestのMatherは2.0を使っている様子

まとめ

alphaバージョンだけあって、ドキュメント通りにやってみて動かない機能や、そもそも動かない機能があった。スマートに書けるので今後に期待したい。

今日は以上です。

次はFunctional-JavaのQuickcheckに挑戦する予定。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5