QuickCheck メモ
QuickCheck はテストケースを自動で作成してくれる、というのを知った。http://d.hatena.ne.jp/kazu-yamamoto/20101027/1288173335。少し試してみた。
sample code
import Test.QuickCheck -- 標準の lookup 関数と同様の関数 search :: Eq k => k -> [(k,v)] -> Maybe v search _ [] = Nothing search k ((key, value) : xs) | k == key = Just value | otherwise = search k xs prop_model0 :: String -> [(String, Int)] -> Bool prop_model0 k xs = search k xs == lookup k xs
run test
GHCi> quickCheck prop_model0 +++ OK, passed 100 tests.
search という関数は、Prelude で定義されている lookup と同じ機能の関数なので、prop_model0 の定義は簡潔になっている。ただ、実践的なモノを作る場合、すでに定義されている関数と同様の関数を作ることはまずない。そういった場合のテストケースの定義はどうすればよいのだろう。その定義が正しいかどうかは、どうやって保証するのだろう。
わざと間違えてみる
search :: Eq k => k -> [(k,v)] -> Maybe v search _ [] = Nothing search k ((key, value) : xs) | k == key = Just value | otherwise = Nothing -- ここを変更
run test
GHCi> quickCheck prop_model0 *** Failed! Falsifiable (after 59 tests and 8 shrinks): "" [("a",0),("",0)]
テストで使用されるパターンは毎回別のパターンになるらしく、少ない確率だけれどテストをパスすることがある。