18 Apr 2015, 08:59

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

はじめに

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

[toc]

Property-based Testing とは

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

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

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

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

英語:

ScalaCheck

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

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

target

<div class="outline-text-3" id="text-unnumbered-4">
  <p>
    以下のコードをテスト.
  </p>

  <p>
    [sourcecode language=&#8221;java&#8221; title=&#8221;&#8221;]<br /> package example;
  </p>

  <p>
    public class MyArithmetic {<br /> public static int add (int a, int b) { return a + b; }<br /> public static int del (int a, int b) { return a &#8211; b; }
  </p>

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

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 はどうだろう? 乱数による総当たりテストならば, 信じてくれるのではないだろうか?