12

QuickCheck用来测试以下程序:

{-# LANGUAGE TemplateHaskell #-}

import Test.QuickCheck
import Test.QuickCheck.All

elementAt :: (Integral b) => [a] -> b -> a
elementAt [x] _ = x
elementAt (x:xs) 1 = x
elementAt (x:xs) b = elementAt xs (b - 1)

prop_elementAt xs b = length xs > 0 && b >= 0 && b < length xs ==> elementAt xs (b + 1) == xs !! b

main = $(quickCheckAll)

尽管反应各不相同,但我不断收到消息

*** Gave up! Passed only x tests.

这是我应该关心的事情吗?还是测试输入的性质决定了 QuickCheck 将运行多长时间?

4

1 回答 1

18

工作方式==>是首先快速检查将为xsand生成随机值b,然后检查谓词length xs > 0 && b >= 0 && b < length xs是否满足,然后它将检查属性的可满足性。

由于它将生成多少测试用例是有限制的,因此可能会在很多时候不满足上述谓词。所以 quickcheck 在生成足够的有效测试用例(满足谓词)之前就放弃了。

相反,您应该将Arbitraryinstance 声明为 newtype 以仅生成满足这些谓词的测试用例。

{-# LANGUAGE TemplateHaskell #-}

import Test.QuickCheck
import Test.QuickCheck.All

elementAt :: (Integral b) => [a] -> b -> a
elementAt [x] _ = x
elementAt (x:xs) 1 = x
elementAt (x:xs) b = elementAt xs (b - 1)

prop_elementAt (Foo xs b) = elementAt xs (b + 1) == xs !! b

data Foo a b = Foo [a] b deriving (Show)

instance (Integral b, Arbitrary a, Arbitrary b) => Arbitrary (Foo a b) where
  arbitrary = do
    as <- listOf1 arbitrary           -- length xs > 0
    b <- choose (0,length as - 1)     -- b >= 0 and b < length xs
    return (Foo as $ fromIntegral b)

main = $(quickCheckAll)
于 2013-08-29T05:27:48.207 回答