我使用QuickCheck
在我的代碼上運行任意測試用例。然而,在我的代碼一個部分我有型同義詞:如何在使用類型同義詞時約束QuickCheck?
type Vector = [Double]
我也有接受一些Vector
S作爲輸入的一些功能。但是,所有這些功能都要求Vector
的長度相同。
有沒有辦法限制QuickCheck
,這樣它只會生成長度爲的列表??
我使用QuickCheck
在我的代碼上運行任意測試用例。然而,在我的代碼一個部分我有型同義詞:如何在使用類型同義詞時約束QuickCheck?
type Vector = [Double]
我也有接受一些Vector
S作爲輸入的一些功能。但是,所有這些功能都要求Vector
的長度相同。
有沒有辦法限制QuickCheck
,這樣它只會生成長度爲的列表??
一個簡單的解決方案是不具有任意實例,而是像做
import Test.QuickCheck
import Control.Monad
prop_vec :: Int -> Gen [Double]
prop_vec = flip replicateM arbitrary . abs
prop_addComm :: Int -> Gen Bool
prop_addComm i = do
v <- prop_vec i
u <- prop_vec i
return $ u + v = v + u --assuming you'd added a Num instance for your vectors
從來沒有一個類型類別,所以你得到的幫助較少的故障,但鞭打起來更簡單。
這裏有一種可能性。我們將爲可以構建隨尺寸而定的隨機值的類型定義一個新類。然後,你可以創建一個類型級別的列表或樹或任何其他的並且爲這些實例聲明一個Arbitrary
實例。
import Control.Monad
import Test.QuickCheck
class SizedArbitrary a where
sizedArbitrary :: Int -> Gen a
instance Arbitrary a => SizedArbitrary [a] where
sizedArbitrary n = replicateM n arbitrary
data Branch a b = a :+ b deriving (Eq, Ord, Show, Read)
instance (SizedArbitrary a, SizedArbitrary b) => SizedArbitrary (Branch a b) where
sizedArbitrary n = liftM2 (:+) (sizedArbitrary n) (sizedArbitrary n)
instance (SizedArbitrary a, SizedArbitrary b) => Arbitrary (Branch a b) where
arbitrary = arbitrarySizedIntegral >>= sizedArbitrary . abs
然後我們就可以在ghci中加載它,並檢查了它的工作原理:
*Main> let allSameLength (xs:xss) = all (==length xs) (map length xss)
*Main> quickCheck (\(xs :+ ys) -> allSameLength [xs, ys])
+++ OK, passed 100 tests.
*Main> quickCheck (\(ws :+ xs :+ ys :+ zs) -> allSameLength [ws, xs, ys, zs])
+++ OK, passed 100 tests.
您可以使用==>
表示法設置約束條件。
一個例子是:現在
*** Failed! Exception: 'Prelude.minimum: empty list' (after 1 test):
[]
與約束:
prop_test xs = minimum xs == (head $ sort xs)
從而未能
prop_test xs = not (null xs) ==> minimum xs == (head $ sort xs)
它的工作原理:
*Main> quickCheck prop_test
+++ OK, passed 100 tests.
你的情況:
prop_test xs ys = length xs == length ys ==> undefined -- whatever you want
中顯示一個例子。這可能真的很慢,但是隨機生成兩個相同大小的列表的機會很渺茫。 – jozefg
另一個明顯的解決方案是產生一個元組列表,並對其進行解壓縮。例如,在ghci中:
> let allSameLength (xs:xss) = all (==length xs) (map length xss)
> quickCheck (\xys -> let (xs, ys) = unzip xys in allSameLength [xs, ys])
+++ OK, passed 100 tests.
> :{
| quickCheck (\wxyzs -> let
| (wxs, yzs) = unzip wxyzs
| (ws, xs) = unzip wxs
| (ys, zs) = unzip yzs
| in allSameLength [ws, xs, ys, zs])
| :}
+++ OK, passed 100 tests.
我沒有資格判斷哪個答案最好 - 所以我選擇這個答案是因爲我正在尋找一個快速解決方案。 – sdasdadas
這實際上似乎需要相當長的時間才能達到QuickCheck的100個測試用例上限......我只是使用'zipWith'將這些矢量加在一起。 – sdasdadas
@sdasdadas嘗試約束數字的大小,我可以在 – jozefg