サーチ…


プロパティの宣言

最も単純なプロパティは、 Boolを返す関数です。

prop_reverseDoesNotChangeLength xs = length (reverse xs) == length xs

プロパティは、プログラムの高水準の不変量を宣言します。 QuickCheckテストランナーは、100個のランダム入力を使って関数を評価し、結果が常にTrueであることを確認しTrue

慣例により、プロパティである関数の名前はprop_prop_ます。

単一のプロパティをチェックする

quickCheck関数は、100のランダム入力のプロパティをテストします。

ghci> quickCheck prop_reverseDoesNotChangeLength
+++ OK, passed 100 tests.

何らかの入力に対してプロパティが失敗した場合、 quickCheckは反例を出力します。

prop_reverseIsAlwaysEmpty xs = reverse xs == []  -- plainly not true for all xs

ghci> quickCheck prop_reverseIsAlwaysEmpty
*** Failed! Falsifiable (after 2 tests):                  
[()]

ファイル内のすべてのプロパティのチェック

quickCheckAllは、名前がprop_で始まる現在のファイル内のすべての定義を見つけてテストするTemplate Haskellヘルパーです。

{-# LANGUAGE TemplateHaskell #-}

import Test.QuickCheck (quickCheckAll)
import Data.List (sort)

idempotent :: Eq a => (a -> a) -> a -> Bool
idempotent f x = f (f x) == f x

prop_sortIdempotent = idempotent sort

-- does not begin with prop_, will not be picked up by the test runner
sortDoesNotChangeLength xs = length (sort xs) == length xs


return []
main = $quickCheckAll

return []行が必要であるreturn []注意してください。これは、その行の上のテキスト定義をTemplate Haskellに見えるようにします。

$ runhaskell QuickCheckAllExample.hs
=== prop_sortIdempotent from tree.hs:7 ===
+++ OK, passed 100 tests.

カスタムタイプのデータをランダムに生成する

Arbitraryクラスは、QuickCheckでランダムに生成できるタイプのクラスです。

Arbitraryの最小限の実装はarbitrary方法で、 Genモナドで実行され、ランダムな値を生成します。

空ではないリストの次のデータ型に対するArbitraryインスタンスがあります。

import Test.QuickCheck.Arbitrary (Arbitrary(..))
import Test.QuickCheck.Gen (oneof)
import Control.Applicative ((<$>), (<*>))

data NonEmpty a = End a | Cons a (NonEmpty a)

instance Arbitrary a => Arbitrary (NonEmpty a) where
    arbitrary = oneof [  -- randomly select one of the cases from the list
        End <$> arbitrary,  -- call a's instance of Arbitrary
        Cons <$>
            arbitrary <*>  -- call a's instance of Arbitrary
            arbitrary  -- recursively call NonEmpty's instance of Arbitrary
        ]

含意(==>)を使用して前提条件でプロパティをチェックする

prop_evenNumberPlusOneIsOdd :: Integer -> Property
prop_evenNumberPlusOneIsOdd x = even x ==> odd (x + 1)

前提条件が成立していることを条件にプロパティが保持されていることを確認したい場合は、 ==>演算子を使用できます。任意の入力が前提条件と一致する可能性が非常に低い場合、QuickCheckは早期に諦める可能性があることに注意してください。

prop_overlySpecific x y = x == 0 ==> x * y == 0

ghci> quickCheck prop_overlySpecific
*** Gave up! Passed only 31 tests.

テストデータのサイズを制限する

ランダム入力が通常はサイズ制限されていないため、quickcheckを使用すると、複雑な漸近的な複雑さで関数をテストすることは困難です。入力の大きさに上限を加えることによって、これらの高価な関数をテストすることができます。

import Data.List(permutations)
import Test.QuickCheck

longRunningFunction :: [a] -> Int
longRunningFunction xs = length (permutations xs)

factorial :: Integral a => a -> a
factorial n = product [1..n]

prop_numberOfPermutations xs =
    longRunningFunction xs == factorial (length xs)

ghci> quickCheckWith (stdArgs { maxSize = 10}) prop_numberOfPermutations

quickCheckWithquickCheckWithの修正版でstdArgsすることで、入力のサイズを10以下に制限することができます。この場合、リストを生成するときに、これはサイズ10までのリストを生成することを意味します。これらの短いリストのために実行するには時間がかかりますが、私たちはまだ私たちの定義が正しいことを合理的に確信することができます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow