2013-08-29 40 views
11

我使用QuickCheck測試以下程序:雖然響應變化爲什麼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的運行時間?

回答

17

的方式==>作品是第一個快速檢查將生成隨機值xsb,然後檢查謂詞length xs > 0 && b >= 0 && b < length xs納才把它會檢查屬性的滿足性。

由於有多少測試用例會產生限制,可能會發生上述謂詞不滿足的情況。所以在生成足夠的有效測試用例(滿足謂詞)之前,quickcheck會放棄。

您應該將Arbitrary實例聲明爲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) 
+0

曾與同[99哈斯克爾問題提問]同樣的問題(http://www.haskell.org/haskellwiki/99_questions/1_to_10),它似乎很好地工作。但是爲我運行'verboseCheck prop_elementAt'會返回僅包含元素'()'的無盡列表,這意味着'elementAt(x:xs)_ = x'的實現仍然通過。任何想法如何生成一個列表中的實際元素? – ThomasH

+1

那是因爲它推斷了prop_elemAt的錯誤類型。給它顯式類型(例子'prop_elementAt :: Foo [Int] Int - > Bool')。 – Satvik

+0

解決了它,謝謝! – ThomasH