[英]Test.QuickCheck: speed up testing multiple properties for the same type
我正在測試一個生成我自己類型實例的隨機生成器。 為此,我有一個Arbitrary
的自定義實例:
complexGenerator :: (RandomGen g) => g -> (MyType, g)
instance Arbitrary MyType where
arbitrary = liftM (fst . complexGenerator . mkStdGen) arbitrary
這適用於Test.QuickCheck
(實際上是Test.Framework
),用於測試生成的值是否包含某些屬性。 但是,我想檢查的屬性有很多,而且我添加的越多,驗證它們所需的時間就越多。
有沒有辦法使用相同的生成值來測試每個屬性,而不是每次都重新生成它們? 我顯然仍然希望在失敗時看到哪些屬性不成立,所以制造一個巨大的財產and
不是最優的。
我顯然仍然希望在失敗時看到哪些屬性不成立,所以制造一個巨大的財產
and
不是最優的。
你可以使用標簽每個屬性printTestCase
使一個巨大的性能與前conjoin
。
例如,你認為這是一個壞主意:
prop_giant :: MyType -> Bool
prop_giant x = and [prop_one x, prop_two x, prop_three x]
這將是有效的,但給你更好的輸出:
prop_giant :: MyType -> Property
prop_giant x = conjoin [printTestCase "one" $ prop_one x,
printTestCase "two" $ prop_two x,
printTestCase "three" $ prop_three x]
(話雖如此,我從來沒有用過這種方法我自己和我只是假設它會工作; conjoin
。可能是標記為一個原因文檔中實驗)
結合投票的答案,我發現有用的是使用帶有Writer monad的Reader變換器:
type Predicate r = ReaderT r (Writer String) Bool
在這種情況下,Reader“共享環境”是經過測試的輸入。 然后你可以組成這樣的屬性:
inv_even :: Predicate Int
inv_even = do
lift . tell $ "this is the even invariant"
(==) 0 . flip mod 2 <$> ask
toLabeledProp :: r -> Predicate r -> Property
toLabeledProp cause r =
let (effect, msg) = runWriter . (runReaderT r) $ cause in
printTestCase ("inv: " ++ msg) . property $ effect
並結合:
fromPredicates :: [Predicate r] -> r -> Property
fromPredicates predicates cause =
conjoin . map (toLabeledProp cause) $ predicates
我懷疑還有另一種方法涉及類似於Either或WriterT的東西 - 這將簡單地將不同類型的謂詞組合成一個結果。 但至少,這允許記錄屬性,這些屬性根據輸入的值強加不同的后置條件。
編輯:這個想法產生了一個庫: http : //github.com/jfeltz/quickcheck-property-comb
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.