概要
ScalaCheckはPropertyベースのテスト用ライブラリです。
ランダムなパラメータを生成し、テスト対象の関数の振る舞いをテストします。
標準で文字列や数値をランダムに生成する便利なGeneratorがありますが、独自のGeneratorを作成することも可能です。
この記事では独自にGeneratorを作成してみます。
事前準備
ScalaCheckを使えるようにするため、build.sbt
に以下を追加します
build.sbt
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.12.5" % "test"
検査対象クラス
今回は以下のようなクラスでテストしてみます
MyClass.scala
case class MyClass(number: Int, multiplier: Multiplier) {
def calc: Int = {
number * multiplier.number
}
}
case class Multiplier(number: Int)
MyClassはnumber
とmultiplier
というメンバ変数を持っていて、calc
メソッドでnumber
とmultiplier
を掛けた値を返します。
また、Multiplierはnumber
をメンバ変数に持つようにしています。
テストクラス
検査対象クラスに対してテストクラスは以下のように書いてみました。
MyClassTest.scala
import org.scalacheck.{Arbitrary, Gen, Prop, Properties}
object MyClassTest extends Properties("MyClass") {
// MultiplierのGenerator
// -1000 ~ 1000のnumberを持つMultiplierを生成します
val genMultiplier: Gen[Multiplier] = for {
number <- Gen.chooseNum(-1000, 1000)
} yield Multiplier(number)
// MyClassのGenerator
// -1000 ~ 1000のnumberとgenMultiplierで生成したMultiplierを持つMyClassを生成します
val genMyClass: Gen[MyClass] = for {
number <- Gen.chooseNum(-1000, 1000)
multiplier <- genMultiplier
} yield MyClass(number, multiplier)
// Prop.forAllでMyClassの乱数を呼び出す際にArbitraryを定義
implicit val arbMyClass = Arbitrary {genMyClass}
// テストの実行
// 100パターンのMyClassをランダムに生成してcalcの挙動を
property("calc") = Prop.forAll{(myClass: MyClass) =>
myClass.calc == myClass.number * myClass.multiplier.number
}
}
これでテストを実行してみます
$ sbt test
~
[info] + MyClass.calc: OK, passed 100 tests.
[info] Passed: Total 1, Failed 0, Errors 0, Passed 1
[success] Total time: 4 s, completed 2016/01/28 11:28:23
うまくいったみたいですね <3