So-net無料ブログ作成
検索選択

ScalaCheck を試す [Scala]

The fun of programming の第2章は QuickCheck という Haskell 用のテスト支援ツールの紹介。Scala にも QuickCheck を参考にした ScalaCheck [1] というのがあるので触ってみることにした。

* インストール

sbaz をセットアップしてあれば sbaz install scalacheck とするか、よくわからなければ ScalaCheck-0.2.jar をダウンロードしてきて Scala の lib ディレクトリに おけばよい。

* 使ってみる

インタプリタ上で使うことにします。まずは以下の名前をインポート。

scala> import scalacheck._
import scalacheck._

scala> import scalacheck.Gen._
import scalacheck.Gen._

scala> import scalacheck.Prop._
import scalacheck.Prop._

scala> import scalacheck.Test._
import scalacheck.Test._

加算演算子について「結合法則を満たす」という性質をテストしたい場合は以下のように仕様を書きます。

scala> val propAssoc = property( (x:Int, y:Int, z:Int) => (x + y) + z == x + (y + z) )
propAssoc: scalacheck.Gen[scalacheck.Prop.PropRes] = scalacheck.Gen$$anon$0@1fe500a

これをテストするには check メソッドを使います。

scala> check(propAssoc)
+++ OK, passed 100 tests.
res0: scalacheck.TestStats = TestStats(TestPassed(),100,0)

これで自動的にテストデータを100件作ってテストをしてくれました。(テストされたデータをログとして残すことはできないのだろうか?)
本ではこれを整数でなく浮動小数点数にすると丸め誤差でテストを通らなくなる!というのが面白かったのですが ScalaCheck には任意の浮動小数点数データを生成してくれる機能は今のところ無い模様。

今度は与えられた整数の桁数を求める関数 (cf. [2]) を以下のように定義してみます。

scala> def len(x: Int) = Math.floor(Math.log(x) / Math.log(10)).toInt + 1
len: (Int)Int

この関数はきっと次の性質を満たすことでしょう。

scala> val propLen = property ( (x:Int) => len(x) == x.toString.length )
propLen: scalacheck.Gen[scalacheck.Prop.PropRes] = scalacheck.Gen$$anon$0@3da1dc

テストしてみます。

scala> check(propLen)
*** Failed, after 0 successful tests:
The arguments that caused the failure was:
List(0)

res4: scalacheck.TestStats = TestStats(TestFailed(List(0)),0,0)

失敗しました。List の内容が失敗する場合の引数の例のようで、この関数は引数が 0 の時は失敗するということです。あー、本当はそういう仕様かも、ということで仕様のほうを変えてしまいます。「引数が 0 より大きい場合は」というような前提条件をつけるには ==> を使います(演算子の優先順位に注意)。

scala> val propLen = property ( (x:Int) => x > 0 ==> (len(x) == x.toString.length) )
propLen: scalacheck.Gen[scalacheck.Prop.PropRes] = scalacheck.Gen$$anon$0@1bf446e

scala> check(propLen)
+++ OK, passed 100 tests.
res5: scalacheck.TestStats = TestStats(TestPassed(),100,123)

今度はテストを通りました。実はこれも log の誤差で失敗してほしかったのですが

どうも Scala の Int の範囲では失敗しない様子です。

追記: x が 1000 のときにちゃんと?誤差が出るようになっていました。check(propLen) は何度やっても成功するのでたまたま当たらないということでしょうか。なんかいきなり ScalaCheck の限界を見てしまったような…

続くかも。

[1] http://code.google.com/p/scalacheck/
[2] http://ja.doukaku.org/40/


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この記事のトラックバックURL:
※言及リンクのないトラックバックは受信されません。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。