ScalaCheck をつかって Java の性質テスト (Property-based Testing) をしてみる

    はじめに

    Property-based Testing というものを知ったので, Java でできるか試してみました.

    [toc]

    Property-based Testing とは

    うまい日本語訳がないのだが, この記事では性質テストとする.

    ある集合のなかにある要素から取り出した値をつかって, 総当たりテストをして, 条件式がなりたつことを確認するテスト.

    よく数学の問題で, 任意の x について hogehoge がなりたつことを証明せよ みたいなのがあるが, hogehoge が 性質にあたるもの.

    上手く説明できないので, 大量の参照リンクをはっておく.

    英語:

    ScalaCheck

    Scala の 性質テスト用ツールで, ScalaCheck というものがある.

    Scala なので, Java にもつかえるか試す.(私は, 現在 java プログラマなので)

    target

    以下のコードをテスト.

    [sourcecode language=”java” title=””]
    package example;

    public class MyArithmetic {
    public static int add (int a, int b) { return a + b; }
    public static int del (int a, int b) { return a – b; }

    public static void main (String[] args) {
    System.out.println (add (1, 2));
    }
    }
    [/sourcecode]

    Java で sbt をつかう

    scala のテストツールなので, scala の ビルドツール sbt をつかうのが楽.

    src/main/java 配下に ソースをおいて, root で sbt を起動すると なんと Java コードが sbt で使えてしまう.

    これはこれで, 手軽さに驚いた. Java のビルドツールとして使えそう.

    [sourcecode language=”bash” title=””]
    # コンパイル
    > compile

    # main 関数を自動で検索して実行
    > run
    [/sourcecode]

    ScalaCheck をつかう

    以下のようなファイルを作成して, src/test/scala 配下におく.

    [sourcecode language=”scala” title=””]
    import org.scalacheck.Properties
    import org.scalacheck.Prop.forAll

    import example._

    object MyArithmeticSpecification extends Properties ("MyArithmetic") {

    property ("add") = forAll { (a : Int, b : Int) =>
    val aa = a % 100
    val bb = b % 100
    val c = MyArithmetic.add (aa*aa, bb*bb)
    c >= aa*aa && c >= bb*bb
    }

    property ("add2") = forAll { (a : Int) =>
    val aa = a % 100
    aa * aa >= aa
    }

    property ("del") = forAll { (a : Int, b : Int) =>
    val aa = a g% 100
    val bb = b % 100

    val c = MyArithmetic.del (aa*aa, bb*bb)

    c <= aa*aa || c <= bb*bb
    }
    }
    [/sourcecode]

    root ディレクトリの build.sbt に以下を書く.

    [sourcecode language=”bash” title=””]
    libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.12.2" % "test"
    [/sourcecode]

    ファイル構成はいかのようなかんじ

    [sourcecode language=”bash” title=””]
    — build.sbt
    src
    main
    java
    MyArithmetic.java
    test
    scala
    MyArithmeticSpecification.scala
    [/sourcecode]

    テスト実行

    [sourcecode language=”bash” title=””]
    $ sbt test
    [info] + MyArithmetic.add: OK, passed 100 tests.
    [info] + MyArithmetic.add2: OK, passed 100 tests.
    [info] + MyArithmetic.del: OK, passed 100 tests.
    [info] Passed: Total 3, Failed 0, Errors 0, Passed 3
    [success] Total time: 1 s, completed 2015/04/18 17:54:54
    [/sourcecode]

    おわりに

    むかしむかし, CUnit のことを課長にはなしたことがあったのだが, (うたぐり深い) 課長は, xUnit のようなものでは品質がとれないと突っかかってきた.

    全部網羅したテストじゃないと, 完全にバグがないなんて言いきれない

    自分はこれに対して反論ができなかった.

    いまならば, 反論できる.Property-based Testing はどうだろう? 乱数による総当たりテストならば, 信じてくれるのではないだろうか?