Testing Test.QuickCheck:加快测试同一类型的多个属性

Testing Test.QuickCheck:加快测试同一类型的多个属性,testing,haskell,quickcheck,htf,Testing,Haskell,Quickcheck,Htf,我正在测试生成我自己类型实例的随机生成器。为此,我有一个自定义的任意: complexGenerator :: (RandomGen g) => g -> (MyType, g) instance Arbitrary MyType where arbitrary = liftM (fst . complexGenerator . mkStdGen) arbitrary 这与Test.QuickCheck(实际上是Test.Framework)配合使用,可以测试生成的值是否

我正在测试生成我自己类型实例的随机生成器。为此,我有一个自定义的
任意

complexGenerator :: (RandomGen g) => g -> (MyType, g)

instance Arbitrary MyType where
    arbitrary = liftM (fst . complexGenerator . mkStdGen) arbitrary
这与
Test.QuickCheck
(实际上是
Test.Framework
)配合使用,可以测试生成的值是否具有某些属性。但是,我要检查的属性很多,添加的越多,验证所有属性所需的时间就越多

是否有一种方法可以使用相同的生成值来测试每个属性,而不是每次都重新生成它们?显然,我仍然希望看到,在失败时,哪个属性不成立,因此使用
创建一个巨大的属性并不是最优的

显然,我仍然希望看到,在失败时,哪个属性不成立,因此使用
创建一个巨大的属性并不是最优的

在使用创建大型属性之前,可以标记每个属性

e、 g.你认为这是个坏主意:

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:

type Predicate r = ReaderT r (Writer String) Bool
在本例中,读卡器“共享环境”是经过测试的输入。然后,您可以像这样组合属性:

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
我怀疑还有另一种方法涉及类似于或writer的东西,它可以将不同类型的谓词简洁地组合成一个结果。但至少,这允许记录根据输入值施加不同post条件的属性

编辑:这个想法催生了一个图书馆:

fromPredicates :: [Predicate r] -> r -> Property
fromPredicates predicates cause =
  conjoin . map (toLabeledProp cause) $ predicates